diff --git a/include/llvm/System/MappedFile.h b/include/llvm/System/MappedFile.h index af13cbb5afe..6f902d28a1e 100644 --- a/include/llvm/System/MappedFile.h +++ b/include/llvm/System/MappedFile.h @@ -28,145 +28,90 @@ namespace sys { /// for mapping a file into memory for both read and write access. This class /// does not provide facilities for finding the file or operating on paths to /// files. The sys::Path class is used for that. - /// @since 1.4 - /// @brief An abstraction for memory mapped files. class MappedFile { - /// @name Types - /// @{ + sys::PathWithStatus Path; ///< Path to the file. + unsigned Options; ///< Options used to create the mapping + void *BasePtr; ///< Pointer to the base memory address + mutable MappedFileInfo *MapInfo; ///< Platform specific info for the mapping + + MappedFile& operator=(const MappedFile &that); // DO NOT IMPLEMENT + MappedFile(const MappedFile &that); // DO NOT IMPLEMENT public: enum MappingOptions { - READ_ACCESS = 0x0001, ///< Map the file for reading - WRITE_ACCESS = 0x0002, ///< Map the file for write access - EXEC_ACCESS = 0x0004, ///< Map the file for execution access + READ_ACCESS = 0x0001, ///< Map the file for reading + WRITE_ACCESS = 0x0002, ///< Map the file for write access + EXEC_ACCESS = 0x0004, ///< Map the file for execution access SHARED_MAPPING = 0x0008 ///< Map the file shared with other processes }; - /// @} - /// @name Constructors - /// @{ - public: - /// Construct a MappedFile to the \p path in the operating system's file - /// system with the mapping \p options provided. - /// @throws std::string if an error occurs - MappedFile() : path_(), options_(READ_ACCESS), base_(0), info_(0) {} + + MappedFile() : Options(READ_ACCESS), BasePtr(0), MapInfo(0) {} /// Destruct a MappedFile and release all memory associated with it. - /// @throws std::string if an error occurs - ~MappedFile() { if (info_) terminate(); } + ~MappedFile() { close(); } + + public: // Accessors - /// @} - /// @name Accessors - /// @{ - public: /// This function determines if the file is currently mapped or not. - /// @returns true iff the file is mapped into memory, false otherwise - /// @brief Determine if a MappedFile is currently mapped - /// @throws nothing - bool isMapped() const { return base_ != 0; } + bool isMapped() const { return BasePtr != 0; } /// This function returns a void* pointer to the base address of the file /// mapping. This is the memory address of the first byte in the file. /// Note that although a non-const pointer is returned, the memory might /// not actually be writable, depending on the MappingOptions used when /// the MappedFile was opened. - /// @returns The base pointer to the memory mapped file. - /// @brief Obtain the base pointer to the memory mapped file. - /// @throws nothing - void* base() const { return base_; } + void* base() const { return BasePtr; } /// This function returns a char* pointer to the base address of the file /// mapping. This is the memory address of the first byte in the file. /// Note that although a non-const pointer is returned, the memory might /// not actually be writable, depending on the MappingOptions used when /// the MappedFile was opened. - /// @returns The base pointer to the memory mapped file as a char pointer. - /// @brief Obtain the base pointer to the memory mapped file. - /// @throws nothing - char* charBase() const { return reinterpret_cast(base_); } + char* charBase() const { return reinterpret_cast(BasePtr); } /// This function returns a reference to the sys::Path object kept by the /// MappedFile object. This contains the path to the file that is or /// will be mapped. - /// @returns sys::Path containing the path name. - /// @brief Returns the mapped file's path as a sys::Path - /// @throws nothing - const sys::Path& path() const { return path_; } + const sys::Path& path() const { return Path; } /// This function returns the number of bytes in the file. - /// @throws std::string if an error occurs size_t size() const; - /// @} - /// @name Mutators - /// @{ - public: - /// Open a file to be mapped and get its size but don't map it yet. - /// @returns true if an error occurred - bool open( - const sys::Path& p, ///< Path to file to be mapped - int options = READ_ACCESS, ///< Access mode for the mapping - std::string* ErrMsg = 0 ///< Optional error string pointer - ) { - path_ = p; - options_ = options; + public: // Mutators + + /// Open a file to be mapped and get its size but don't map it yet. Return + /// true on error. + bool open(const sys::Path &P, int options = READ_ACCESS, + std::string *ErrMsg = 0) { + Path = P; + Options = options; return initialize(ErrMsg); } - /// The mapped file is removed from memory. If the file was mapped for + /// unmap - Remove the mapped file from memory. If the file was mapped for /// write access, the memory contents will be automatically synchronized /// with the file's disk contents. - /// @brief Remove the file mapping from memory. void unmap(); - /// The mapped file is put into memory. - /// @returns The base memory address of the mapped file or 0 if an error - /// occurred. - /// @brief Map the file into memory. - void* map( - std::string* ErrMsg = 0///< Optional error string pointer - ); + /// map - Reserve space for the file, map it into memory, and return a + /// pointer to it. This returns the base memory address of the mapped file + /// or 0 if an error occurred. + void *map(std::string* ErrMsg = 0); - /// This method causes the size of the file, and consequently the size - /// of the mapping to be set. This is logically the same as unmap(), + /// resize - This method causes the size of the file, and consequently the + /// size of the mapping to be set. This is logically the same as unmap(), /// adjust size of the file, map(). Consequently, when calling this /// function, the caller should not rely on previous results of the /// map(), base(), or baseChar() members as they may point to invalid /// areas of memory after this call. - /// @throws std::string if an error occurs - /// @brief Set the size of the file and memory mapping. - bool size(size_t new_size, std::string* ErrMsg = 0); + bool resize(size_t new_size, std::string *ErrMsg = 0); - void close() { if (info_) terminate(); } + void close() { if (MapInfo) terminate(); } - /// @} - /// @name Implementation - /// @{ private: - /// @brief Initialize platform-specific portion - bool initialize(std::string* ErrMsg); - - /// @brief Terminate platform-specific portion - void terminate(); - - /// @} - /// @name Data - /// @{ - private: - sys::PathWithStatus path_; ///< Path to the file. - int options_; ///< Options used to create the mapping - void* base_; ///< Pointer to the base memory address - mutable MappedFileInfo* info_; ///< Platform specific info for the mapping - - /// @} - /// @name Disabled - /// @{ - private: - ///< Disallow assignment - MappedFile& operator=(const MappedFile &that); - ///< Disallow copying - MappedFile(const MappedFile& that); - /// @} + bool initialize(std::string *ErrMsg); + void terminate(); }; -} -} +} // end namespace sys +} // end namespace llvm #endif diff --git a/lib/System/Unix/MappedFile.inc b/lib/System/Unix/MappedFile.inc index 546a226ef31..dcfd1892f84 100644 --- a/lib/System/Unix/MappedFile.inc +++ b/lib/System/Unix/MappedFile.inc @@ -31,105 +31,109 @@ #include #endif -namespace llvm { +using namespace llvm; using namespace sys; -struct sys::MappedFileInfo { - int FD; - off_t Size; -}; +namespace llvm { + namespace sys { + struct MappedFileInfo { + int FD; + off_t Size; + }; + } +} bool MappedFile::initialize(std::string* ErrMsg) { int mode = 0; - if (options_ & READ_ACCESS) - if (options_ & WRITE_ACCESS) + if (Options & READ_ACCESS) + if (Options & WRITE_ACCESS) mode = O_RDWR; else mode = O_RDONLY; - else if (options_ & WRITE_ACCESS) + else if (Options & WRITE_ACCESS) mode = O_WRONLY; - int FD = ::open(path_.c_str(), mode); + int FD = ::open(Path.c_str(), mode); if (FD < 0) { - MakeErrMsg(ErrMsg, "can't open file '" + path_.toString() + "'"); + MakeErrMsg(ErrMsg, "can't open file '" + Path.toString() + "'"); return true; } - const FileStatus *Status = path_.getFileStatus(false, ErrMsg); + const FileStatus *Status = Path.getFileStatus(false, ErrMsg); if (!Status) { ::close(FD); return true; } - info_ = new MappedFileInfo; - info_->FD = FD; - info_->Size = Status->getSize(); + MapInfo = new MappedFileInfo(); + MapInfo->FD = FD; + MapInfo->Size = Status->getSize(); return false; } void MappedFile::terminate() { - assert(info_ && "MappedFile not initialized"); - ::close(info_->FD); - delete info_; - info_ = 0; + assert(MapInfo && "MappedFile not initialized"); + ::close(MapInfo->FD); + delete MapInfo; + MapInfo = 0; } void MappedFile::unmap() { - assert(info_ && "MappedFile not initialized"); - if (isMapped()) { - if (options_ & WRITE_ACCESS) - ::msync(base_, info_->Size, MS_SYNC); - ::munmap(base_, info_->Size); - base_ = 0; // Mark this as non-mapped. - } + assert(MapInfo && "MappedFile not initialized"); + if (!isMapped()) return; + + if (Options & WRITE_ACCESS) + ::msync(BasePtr, MapInfo->Size, MS_SYNC); + ::munmap(BasePtr, MapInfo->Size); + BasePtr = 0; // Mark this as non-mapped. } void* MappedFile::map(std::string* ErrMsg) { - assert(info_ && "MappedFile not initialized"); - if (!isMapped()) { - int prot = PROT_NONE; - int flags = 0; + assert(MapInfo && "MappedFile not initialized"); + if (isMapped()) return BasePtr; + + int prot = PROT_NONE; + int flags = 0; #ifdef MAP_FILE - flags |= MAP_FILE; + flags |= MAP_FILE; #endif - if (options_ == 0) { - prot = PROT_READ; - flags = MAP_PRIVATE; - } else { - if (options_ & READ_ACCESS) - prot |= PROT_READ; - if (options_ & WRITE_ACCESS) - prot |= PROT_WRITE; - if (options_ & EXEC_ACCESS) - prot |= PROT_EXEC; - if (options_ & SHARED_MAPPING) - flags |= MAP_SHARED; - else - flags |= MAP_PRIVATE; - } - size_t map_size = ((info_->Size / Process::GetPageSize())+1) * - Process::GetPageSize(); - - base_ = ::mmap(0, map_size, prot, flags, info_->FD, 0); - if (base_ == MAP_FAILED) { - MakeErrMsg(ErrMsg, "Can't map file:" + path_.toString()); - return 0; - } + if (Options == 0) { + prot = PROT_READ; + flags = MAP_PRIVATE; + } else { + if (Options & READ_ACCESS) + prot |= PROT_READ; + if (Options & WRITE_ACCESS) + prot |= PROT_WRITE; + if (Options & EXEC_ACCESS) + prot |= PROT_EXEC; + if (Options & SHARED_MAPPING) + flags |= MAP_SHARED; + else + flags |= MAP_PRIVATE; } - return base_; + size_t map_size = ((MapInfo->Size / Process::GetPageSize())+1) * + Process::GetPageSize(); + + BasePtr = ::mmap(0, map_size, prot, flags, MapInfo->FD, 0); + if (BasePtr == MAP_FAILED) { + MakeErrMsg(ErrMsg, "Can't map file:" + Path.toString()); + return 0; + } + return BasePtr; } size_t MappedFile::size() const { - assert(info_ && "MappedFile not initialized"); - return info_->Size; + assert(MapInfo && "MappedFile not initialized"); + return MapInfo->Size; } -bool MappedFile::size(size_t new_size, std::string* ErrMsg) { - assert(info_ && "MappedFile not initialized"); +bool MappedFile::resize(size_t new_size, std::string* ErrMsg) { + assert(MapInfo && "MappedFile not initialized"); // Take the mapping out of memory - this->unmap(); + unmap(); // Adjust the current size to a page boundary - size_t cur_size = ((info_->Size / Process::GetPageSize())+1) * + size_t cur_size = ((MapInfo->Size / Process::GetPageSize())+1) * Process::GetPageSize(); // Adjust the new_size to a page boundary @@ -140,15 +144,12 @@ bool MappedFile::size(size_t new_size, std::string* ErrMsg) { if (new_size > cur_size) { // Ensure we can allocate at least the idodes necessary to handle the // file size requested. - if ((off_t)-1 == ::lseek(info_->FD, new_size, SEEK_SET)) + if ((off_t)-1 == ::lseek(MapInfo->FD, new_size, SEEK_SET)) return MakeErrMsg(ErrMsg, "Can't lseek: "); - if (-1 == ::write(info_->FD, "\0", 1)) + if (-1 == ::write(MapInfo->FD, "\0", 1)) return MakeErrMsg(ErrMsg, "Can't write: "); } // Put the mapping back into memory. - return this->map(ErrMsg); + return map(ErrMsg); } - -} - diff --git a/lib/System/Win32/MappedFile.inc b/lib/System/Win32/MappedFile.inc index 28dbb9856d4..de8eec3673d 100644 --- a/lib/System/Win32/MappedFile.inc +++ b/lib/System/Win32/MappedFile.inc @@ -28,32 +28,32 @@ struct sys::MappedFileInfo { }; bool MappedFile::initialize(std::string* ErrMsg) { - assert(!info_); - info_ = new MappedFileInfo; - info_->hFile = INVALID_HANDLE_VALUE; - info_->hMapping = NULL; + assert(!MapInfo); + MapInfo = new MappedFileInfo; + MapInfo->hFile = INVALID_HANDLE_VALUE; + MapInfo->hMapping = NULL; - DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ; - DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING; - DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ; - share = options_ & SHARED_MAPPING ? share : 0; - info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition, + DWORD mode = Options & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ; + DWORD disposition = Options & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING; + DWORD share = Options & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ; + share = Options & SHARED_MAPPING ? share : 0; + MapInfo->hFile = CreateFile(Path.c_str(), mode, share, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if (info_->hFile == INVALID_HANDLE_VALUE) { - delete info_; - info_ = NULL; + if (MapInfo->hFile == INVALID_HANDLE_VALUE) { + delete MapInfo; + MapInfo = NULL; return MakeErrMsg(ErrMsg, - std::string("Can't open file: ") + path_.toString()); + std::string("Can't open file: ") + Path.toString()); } LARGE_INTEGER size; - if (!GetFileSizeEx(info_->hFile, &size) || - (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) { - CloseHandle(info_->hFile); - delete info_; - info_ = NULL; + if (!GetFileSizeEx(MapInfo->hFile, &size) || + (MapInfo->size = size_t(size.QuadPart), MapInfo->size != size.QuadPart)) { + CloseHandle(MapInfo->hFile); + delete MapInfo; + MapInfo = NULL; return MakeErrMsg(ErrMsg, - std::string("Can't get size of file: ") + path_.toString()); + std::string("Can't get size of file: ") + Path.toString()); } return false; @@ -61,56 +61,56 @@ bool MappedFile::initialize(std::string* ErrMsg) { void MappedFile::terminate() { unmap(); - if (info_->hFile != INVALID_HANDLE_VALUE) - CloseHandle(info_->hFile); - delete info_; - info_ = NULL; + if (MapInfo->hFile != INVALID_HANDLE_VALUE) + CloseHandle(MapInfo->hFile); + delete MapInfo; + MapInfo = NULL; } void MappedFile::unmap() { - assert(info_ && "MappedFile not initialized"); + assert(MapInfo && "MappedFile not initialized"); if (isMapped()) { - UnmapViewOfFile(base_); - base_ = NULL; + UnmapViewOfFile(BasePtr); + BasePtr = NULL; } - if (info_->hMapping != INVALID_HANDLE_VALUE) { - CloseHandle(info_->hMapping); - info_->hMapping = NULL; + if (MapInfo->hMapping != INVALID_HANDLE_VALUE) { + CloseHandle(MapInfo->hMapping); + MapInfo->hMapping = NULL; } } void* MappedFile::map(std::string* ErrMsg) { if (!isMapped()) { DWORD prot = PAGE_READONLY; - if (options_ & EXEC_ACCESS) + if (Options & EXEC_ACCESS) prot = SEC_IMAGE; - else if (options_ & WRITE_ACCESS) + else if (Options & WRITE_ACCESS) prot = PAGE_READWRITE; - info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL); - if (info_->hMapping == NULL) { - MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString()); + MapInfo->hMapping = CreateFileMapping(MapInfo->hFile, NULL, prot, 0, 0, NULL); + if (MapInfo->hMapping == NULL) { + MakeErrMsg(ErrMsg, std::string("Can't map file: ") + Path.toString()); return 0; } - prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ; - base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL); - if (base_ == NULL) { - CloseHandle(info_->hMapping); - info_->hMapping = NULL; - MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString()); + prot = (Options & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ; + BasePtr = MapViewOfFileEx(MapInfo->hMapping, prot, 0, 0, 0, NULL); + if (BasePtr == NULL) { + CloseHandle(MapInfo->hMapping); + MapInfo->hMapping = NULL; + MakeErrMsg(ErrMsg, std::string("Can't map file: ") + Path.toString()); return 0; } } - return base_; + return BasePtr; } size_t MappedFile::size() const { - assert(info_ && "MappedFile not initialized"); - return info_->size; + assert(MapInfo && "MappedFile not initialized"); + return MapInfo->size; } -bool MappedFile::size(size_t new_size, std::string* ErrMsg) { - assert(info_ && "MappedFile not initialized"); +bool MappedFile::resize(size_t new_size, std::string* ErrMsg) { + assert(MapInfo && "MappedFile not initialized"); // Take the mapping out of memory. unmap(); @@ -120,16 +120,16 @@ bool MappedFile::size(size_t new_size, std::string* ErrMsg) { new_size = (new_size + pagesizem1) & ~pagesizem1; // If the file needs to be extended, do so. - if (new_size > info_->size) { + if (new_size > MapInfo->size) { LARGE_INTEGER eof; eof.QuadPart = new_size; - if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN)) + if (!SetFilePointerEx(MapInfo->hFile, eof, NULL, FILE_BEGIN)) return MakeErrMsg(ErrMsg, - std::string("Can't set end of file: ") + path_.toString()); - if (!SetEndOfFile(info_->hFile)) + std::string("Can't set end of file: ") + Path.toString()); + if (!SetEndOfFile(MapInfo->hFile)) return MakeErrMsg(ErrMsg, - std::string("Can't set end of file: ") + path_.toString()); - info_->size = new_size; + std::string("Can't set end of file: ") + Path.toString()); + MapInfo->size = new_size; } // Remap the file.