void MemoryMappedFile::PrefetchRange( Range<const char*> memoryRange ) const { # if( WIN8_MEMORY_MAPPED_FILE_AVAILABLE ) WIN32_MEMORY_RANGE_ENTRY ranges[] = { { const_cast<char*>( memoryRange.first ), memoryRange.GetSize() } }; PrefetchVirtualMemory( GetCurrentProcess(), _countof( ranges ), ranges, 0 ); # else for( auto temp( memoryRange.Begin() ); temp < memoryRange.End(); temp += PrefetchStride ) { // TODO: Is it possible to use prefetch instructions to avoid polluting the processor caches? register int readTarget = *reinterpret_cast<const int*>(temp); } # endif }
void* mmap_load(const char* fname, size_t* fsize, bool writable, bool populate) { #ifdef _MSC_VER LARGE_INTEGER lsize; HANDLE hFile = CreateFileA(fname , GENERIC_READ |(writable ? GENERIC_WRITE : 0) , FILE_SHARE_DELETE | FILE_SHARE_READ | (writable ? FILE_SHARE_WRITE : 0) , NULL // lpSecurityAttributes , writable ? OPEN_ALWAYS : OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL // hTemplateFile ); if (INVALID_HANDLE_VALUE == hFile) { DWORD err = GetLastError(); THROW_STD(logic_error, "CreateFile(fname=%s).Err=%d(%X)" , fname, err, err); } if (writable) { // bool isNewFile = GetLastError() != ERROR_ALREADY_EXISTS; bool isNewFile = GetLastError() == 0; if (isNewFile) { SetFilePointer(hFile, 8*1024, NULL, SEEK_SET); SetEndOfFile(hFile); SetFilePointer(hFile, 0, NULL, SEEK_SET); } } if (!GetFileSizeEx(hFile, &lsize)) { DWORD err = GetLastError(); CloseHandle(hFile); THROW_STD(logic_error, "GetFileSizeEx(fname=%s).Err=%d(%X)" , fname, err, err); } if (lsize.QuadPart > size_t(-1)) { CloseHandle(hFile); THROW_STD(logic_error, "fname=%s fsize=%I64u(%I64X) too large" , fname, lsize.QuadPart, lsize.QuadPart); } *fsize = size_t(lsize.QuadPart); DWORD flProtect = writable ? PAGE_READWRITE : PAGE_READONLY; HANDLE hMmap = CreateFileMapping(hFile, NULL, flProtect, 0, 0, NULL); if (NULL == hMmap) { DWORD err = GetLastError(); CloseHandle(hFile); THROW_STD(runtime_error, "CreateFileMapping(fname=%s).Err=%d(0x%X)" , fname, err, err); } DWORD desiredAccess = (writable ? FILE_MAP_WRITE : 0) | FILE_MAP_READ; void* base = MapViewOfFile(hMmap, desiredAccess, 0, 0, 0); if (NULL == base) { DWORD err = GetLastError(); ::CloseHandle(hMmap); ::CloseHandle(hFile); THROW_STD(runtime_error, "MapViewOfFile(fname=%s).Err=%d(0x%X)" , fname, err, err); } if (populate) { WIN32_MEMORY_RANGE_ENTRY vm; vm.VirtualAddress = base; vm.NumberOfBytes = *fsize; PrefetchVirtualMemory(GetCurrentProcess(), 1, &vm, 0); } ::CloseHandle(hMmap); // close before UnmapViewOfFile is OK ::CloseHandle(hFile); #else int openFlags = writable ? O_RDWR : O_RDONLY; int fd = ::open(fname, openFlags); if (fd < 0) { int err = errno; THROW_STD(logic_error, "open(fname=%s, %s) = %d(%X): %s" , fname, writable ? "O_RDWR" : "O_RDONLY" , err, err, strerror(err)); } struct stat st; if (::fstat(fd, &st) < 0) { THROW_STD(logic_error, "stat(fname=%s) = %s", fname, strerror(errno)); } *fsize = st.st_size; int flProtect = (writable ? PROT_WRITE : 0) | PROT_READ; int flags = MAP_SHARED | (populate ? MAP_POPULATE : 0); void* base = ::mmap(NULL, st.st_size, flProtect, flags, fd, 0); if (MAP_FAILED == base) { ::close(fd); THROW_STD(logic_error, "mmap(fname=%s, %s SHARED, size=%lld) = %s" , fname, writable ? "READWRITE" : "READ" , (long long)st.st_size, strerror(errno)); } ::close(fd); #endif return base; }