int mmc_map_memory(mmap_cache * cache) { HANDLE fileMap = CreateFileMapping(cache->fh, NULL, PAGE_READWRITE, 0, cache->c_size, NULL); if (fileMap == NULL) { _mmc_set_error(cache, GetLastError(), "CreateFileMapping of %s failed", cache->share_file); CloseHandle(cache->fh); return -1; } cache->mm_var = MapViewOfFile(fileMap, FILE_MAP_WRITE|FILE_MAP_READ, 0,0,0); if (cache->mm_var == NULL) { _mmc_set_error(cache, GetLastError(), "Mmap of shared file %s failed", cache->share_file); CloseHandle(fileMap); CloseHandle(cache->fh); return -1; } /* If I read the docs right, this will do nothing untill the mm_var is unmapped */ if (CloseHandle(fileMap) == FALSE) { _mmc_set_error(cache, GetLastError(), "CloseHandle(fileMap) on shared file %s failed", cache->share_file); UnmapViewOfFile(cache->mm_var); CloseHandle(fileMap); CloseHandle(cache->fh); return -1; } return 0; }
int mmc_unmap_memory(mmap_cache* cache) { int res = UnmapViewOfFile(cache->mm_var); if (res == -1) { _mmc_set_error(cache, GetLastError(), "Unmmap of shared file %s failed", cache->share_file); } return res; }
/* * mmc_unmap_memory(mmap_cache * cache) * * Unmaps cache->mm_var */ int mmc_unmap_memory(mmap_cache* cache) { int res = munmap(cache->mm_var, cache->c_size); if (res == -1) { _mmc_set_error(cache, errno, "Munmap of shared file %s failed", cache->share_file); return -1; } return res; }
/* * mmc_map_memory(mmap_cache * cache) * * maps the cache file into memory, and sets cache->mm_var as needed. */ int mmc_map_memory(mmap_cache* cache) { /* Map file into memory */ cache->mm_var = mmap(0, cache->c_size, PROT_READ | PROT_WRITE, MAP_SHARED, cache->fh, 0); if (cache->mm_var == (void *)MAP_FAILED) { mmc_close_fh(cache); _mmc_set_error(cache, errno, "Mmap of shared file %s failed", cache->share_file); return -1; } return 0; }
int mmc_lock_page(mmap_cache* cache, MU32 p_offset) { OVERLAPPED lock; DWORD lock_res, bytesTransfered; memset(&lock, 0, sizeof(lock)); lock.Offset = p_offset; lock.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (LockFileEx(cache->fh, 0, 0, cache->c_page_size, 0, &lock) == 0) { _mmc_set_error(cache, GetLastError(), "LockFileEx failed"); return -1; } lock_res = WaitForSingleObjectEx(lock.hEvent, 10000, FALSE); if (lock_res != WAIT_OBJECT_0 || GetOverlappedResult(cache->fh, &lock, &bytesTransfered, FALSE) == FALSE) { CloseHandle(lock.hEvent); _mmc_set_error(cache, GetLastError(), "Overlapped Lock failed"); return -1; } return 0; }
char* _mmc_get_def_share_filename(mmap_cache * cache) { int ret; static char buf[MAX_PATH]; ret = GetTempPath(MAX_PATH, buf); if (ret > MAX_PATH) { _mmc_set_error(cache, GetLastError(), "Unable to get temp path"); return NULL; } return strcat(buf, "sharefile"); }
int mmc_lock_page(mmap_cache* cache, MU32 p_offset) { struct flock lock; int old_alarm, alarm_left = 10; int lock_res = -1; /* Setup fcntl locking structure */ lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = p_offset; lock.l_len = cache->c_page_size; if (cache->catch_deadlocks) old_alarm = alarm(alarm_left); while (lock_res != 0) { /* Lock the page (block till done, signal, or timeout) */ lock_res = fcntl(cache->fh, F_SETLKW, &lock); /* Continue immediately if success */ if (lock_res == 0) { if (cache->catch_deadlocks) alarm(old_alarm); break; } /* Turn off alarm for a moment */ if (cache->catch_deadlocks) alarm_left = alarm(0); /* Some signal interrupted, and it wasn't the alarm? Rerun lock */ if (lock_res == -1 && errno == EINTR && alarm_left) { if (cache->catch_deadlocks) alarm(alarm_left); continue; } /* Lock failed? */ _mmc_set_error(cache, errno, "Lock failed"); if (cache->catch_deadlocks) alarm(old_alarm); return -1; } return 0; }
int mmc_open_cache_file(mmap_cache* cache, int * do_init) { int res, i, fh; void * tmp; struct stat statbuf; /* Check if file exists */ res = stat(cache->share_file, &statbuf); /* Remove if different size or remove requested */ if (!res && (cache->init_file || (statbuf.st_size != cache->c_size))) { res = remove(cache->share_file); if (res == -1 && errno != ENOENT) { _mmc_set_error(cache, errno, "Unlink of existing share file %s failed", cache->share_file); return -1; } } /* Create file if it doesn't exist */ *do_init = 0; res = stat(cache->share_file, &statbuf); if (res == -1) { res = open(cache->share_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_APPEND, 0640); if (res == -1) { _mmc_set_error(cache, errno, "Create of share file %s failed", cache->share_file); return -1; } /* Fill file with 0's */ tmp = malloc(cache->c_page_size); if (!tmp) { _mmc_set_error(cache, errno, "Malloc of tmp space failed"); return -1; } memset(tmp, 0, cache->c_page_size); for (i = 0; i < cache->c_num_pages; i++) { int written = write(res, tmp, cache->c_page_size); if (written < 0) { _mmc_set_error(cache, errno, "Write to share file %s failed", cache->share_file); return -1; } if (written < cache->c_page_size) { _mmc_set_error(cache, errno, "Write to share file %s failed; short write (%d of %d bytes written)", cache->share_file, written, cache->c_page_size); return -1; } } free(tmp); /* Later on initialise page structures */ *do_init = 1; close(res); } /* Open for reading/writing */ fh = open(cache->share_file, O_RDWR); if (fh == -1) { _mmc_set_error(cache, errno, "Open of share file %s failed", cache->share_file); return -1; } /* Automatically close cache fd on exec */ fcntl(fh, F_SETFD, FD_CLOEXEC); cache->fh = fh; return 0; }
int mmc_open_cache_file(mmap_cache* cache, int* do_init) { int i; void *tmp; HANDLE fh, fileMap, findHandle; WIN32_FIND_DATA statbuf; *do_init = 0; findHandle = FindFirstFile(cache->share_file, &statbuf); /* Create file if it doesn't exist */ if (findHandle == INVALID_HANDLE_VALUE) { fh = CreateFile(cache->share_file, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); if (fh == INVALID_HANDLE_VALUE) { _mmc_set_error(cache, GetLastError(), "Create of share file %s failed", cache->share_file); return -1; } /* Fill file with 0's */ tmp = malloc(cache->c_page_size); if (!tmp) { _mmc_set_error(cache, GetLastError(), "Malloc of tmp space failed"); return -1; } memset(tmp, 0, cache->c_page_size); for (i = 0; i < cache->c_num_pages; i++) { DWORD tmpOut; WriteFile(fh, tmp, cache->c_page_size, &tmpOut, NULL); } free(tmp); /* Later on initialise page structures */ *do_init = 1; CloseHandle(fh); } else { FindClose(findHandle); if (cache->init_file || (statbuf.nFileSizeLow != cache->c_size)) { *do_init = 1; fh = CreateFile(cache->share_file, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); if (fh == INVALID_HANDLE_VALUE) { _mmc_set_error(cache, GetLastError(), "Truncate of existing share file %s failed", cache->share_file); return -1; } CloseHandle(fh); } } fh = CreateFile(cache->share_file, // File Name GENERIC_READ|GENERIC_WRITE, // Desired Access FILE_SHARE_READ|FILE_SHARE_WRITE, // Share mode NULL, // Security Rights OPEN_EXISTING, // Creation Mode FILE_ATTRIBUTE_TEMPORARY, // File Attribs NULL); // Template File if (fh == INVALID_HANDLE_VALUE) { _mmc_set_error(cache, GetLastError(), "Open of share file \"%s\" failed", cache->share_file); return -1; } cache->fh = fh; return 0; }