LLVM API Documentation
00001 //===- Win32/MappedFile.cpp - Win32 MappedFile Implementation ---*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by Jeff Cohen and is distributed under the 00006 // University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file provides the Win32 implementation of the MappedFile concept. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 //===----------------------------------------------------------------------===// 00015 //=== WARNING: Implementation here must contain only Win32 code. 00016 //===----------------------------------------------------------------------===// 00017 00018 #include "Win32.h" 00019 #include "llvm/System/Process.h" 00020 00021 namespace llvm { 00022 using namespace sys; 00023 00024 struct sys::MappedFileInfo { 00025 HANDLE hFile; 00026 HANDLE hMapping; 00027 size_t size; 00028 }; 00029 00030 void MappedFile::initialize() { 00031 assert(!info_); 00032 info_ = new MappedFileInfo; 00033 info_->hFile = INVALID_HANDLE_VALUE; 00034 info_->hMapping = NULL; 00035 00036 DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ; 00037 DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING; 00038 DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ; 00039 share = options_ & SHARED_MAPPING ? share : 0; 00040 info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition, 00041 FILE_ATTRIBUTE_NORMAL, NULL); 00042 if (info_->hFile == INVALID_HANDLE_VALUE) { 00043 delete info_; 00044 info_ = NULL; 00045 ThrowError(std::string("Can't open file: ") + path_.toString()); 00046 } 00047 00048 LARGE_INTEGER size; 00049 if (!GetFileSizeEx(info_->hFile, &size) || 00050 (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) { 00051 CloseHandle(info_->hFile); 00052 delete info_; 00053 info_ = NULL; 00054 ThrowError(std::string("Can't get size of file: ") + path_.toString()); 00055 } 00056 } 00057 00058 void MappedFile::terminate() { 00059 unmap(); 00060 if (info_->hFile != INVALID_HANDLE_VALUE) 00061 CloseHandle(info_->hFile); 00062 delete info_; 00063 info_ = NULL; 00064 } 00065 00066 void MappedFile::unmap() { 00067 assert(info_ && "MappedFile not initialized"); 00068 if (isMapped()) { 00069 UnmapViewOfFile(base_); 00070 base_ = NULL; 00071 } 00072 if (info_->hMapping != INVALID_HANDLE_VALUE) { 00073 CloseHandle(info_->hMapping); 00074 info_->hMapping = NULL; 00075 } 00076 } 00077 00078 void* MappedFile::map() { 00079 if (!isMapped()) { 00080 DWORD prot = PAGE_READONLY; 00081 if (options_ & EXEC_ACCESS) 00082 prot = SEC_IMAGE; 00083 else if (options_ & WRITE_ACCESS) 00084 prot = PAGE_READWRITE; 00085 info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL); 00086 if (info_->hMapping == NULL) 00087 ThrowError(std::string("Can't map file: ") + path_.toString()); 00088 00089 prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ; 00090 base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL); 00091 if (base_ == NULL) { 00092 CloseHandle(info_->hMapping); 00093 info_->hMapping = NULL; 00094 ThrowError(std::string("Can't map file: ") + path_.toString()); 00095 } 00096 } 00097 return base_; 00098 } 00099 00100 size_t MappedFile::size() const { 00101 assert(info_ && "MappedFile not initialized"); 00102 return info_->size; 00103 } 00104 00105 void MappedFile::size(size_t new_size) { 00106 assert(info_ && "MappedFile not initialized"); 00107 00108 // Take the mapping out of memory. 00109 unmap(); 00110 00111 // Adjust the new_size to a page boundary. 00112 size_t pagesizem1 = Process::GetPageSize() - 1; 00113 new_size = (new_size + pagesizem1) & ~pagesizem1; 00114 00115 // If the file needs to be extended, do so. 00116 if (new_size > info_->size) { 00117 LARGE_INTEGER eof; 00118 eof.QuadPart = new_size; 00119 if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN)) 00120 ThrowError(std::string("Can't set end of file: ") + path_.toString()); 00121 if (!SetEndOfFile(info_->hFile)) 00122 ThrowError(std::string("Can't set end of file: ") + path_.toString()); 00123 info_->size = new_size; 00124 } 00125 00126 // Remap the file. 00127 map(); 00128 } 00129 00130 } 00131