LLVM API Documentation

Win32/MappedFile.inc

Go to the documentation of this file.
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