llvm.org GIT mirror llvm / 540630f
cleanup the MappedFile API and comments. This removes and updates tons of out of date comments (really nothing throws here!) and fixes some other fairly glaring issues: "size" used to return the size of the file *and* change it, depending on how you called it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49009 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
3 changed file(s) with 157 addition(s) and 211 deletion(s). Raw diff Collapse all Expand all
2727 /// for mapping a file into memory for both read and write access. This class
2828 /// does not provide facilities for finding the file or operating on paths to
2929 /// files. The sys::Path class is used for that.
30 /// @since 1.4
31 /// @brief An abstraction for memory mapped files.
3230 class MappedFile {
33 /// @name Types
34 /// @{
31 sys::PathWithStatus Path; ///< Path to the file.
32 unsigned Options; ///< Options used to create the mapping
33 void *BasePtr; ///< Pointer to the base memory address
34 mutable MappedFileInfo *MapInfo; ///< Platform specific info for the mapping
35
36 MappedFile& operator=(const MappedFile &that); // DO NOT IMPLEMENT
37 MappedFile(const MappedFile &that); // DO NOT IMPLEMENT
3538 public:
3639 enum MappingOptions {
37 READ_ACCESS = 0x0001, ///< Map the file for reading
38 WRITE_ACCESS = 0x0002, ///< Map the file for write access
39 EXEC_ACCESS = 0x0004, ///< Map the file for execution access
40 READ_ACCESS = 0x0001, ///< Map the file for reading
41 WRITE_ACCESS = 0x0002, ///< Map the file for write access
42 EXEC_ACCESS = 0x0004, ///< Map the file for execution access
4043 SHARED_MAPPING = 0x0008 ///< Map the file shared with other processes
4144 };
42 /// @}
43 /// @name Constructors
44 /// @{
45 public:
46 /// Construct a MappedFile to the \p path in the operating system's file
47 /// system with the mapping \p options provided.
48 /// @throws std::string if an error occurs
49 MappedFile() : path_(), options_(READ_ACCESS), base_(0), info_(0) {}
45
46 MappedFile() : Options(READ_ACCESS), BasePtr(0), MapInfo(0) {}
5047
5148 /// Destruct a MappedFile and release all memory associated with it.
52 /// @throws std::string if an error occurs
53 ~MappedFile() { if (info_) terminate(); }
49 ~MappedFile() { close(); }
5450
55 /// @}
56 /// @name Accessors
57 /// @{
58 public:
51 public: // Accessors
52
5953 /// This function determines if the file is currently mapped or not.
60 /// @returns true iff the file is mapped into memory, false otherwise
61 /// @brief Determine if a MappedFile is currently mapped
62 /// @throws nothing
63 bool isMapped() const { return base_ != 0; }
54 bool isMapped() const { return BasePtr != 0; }
6455
6556 /// This function returns a void* pointer to the base address of the file
6657 /// mapping. This is the memory address of the first byte in the file.
6758 /// Note that although a non-const pointer is returned, the memory might
6859 /// not actually be writable, depending on the MappingOptions used when
6960 /// the MappedFile was opened.
70 /// @returns The base pointer to the memory mapped file.
71 /// @brief Obtain the base pointer to the memory mapped file.
72 /// @throws nothing
73 void* base() const { return base_; }
61 void* base() const { return BasePtr; }
7462
7563 /// This function returns a char* pointer to the base address of the file
7664 /// mapping. This is the memory address of the first byte in the file.
7765 /// Note that although a non-const pointer is returned, the memory might
7866 /// not actually be writable, depending on the MappingOptions used when
7967 /// the MappedFile was opened.
80 /// @returns The base pointer to the memory mapped file as a char pointer.
81 /// @brief Obtain the base pointer to the memory mapped file.
82 /// @throws nothing
83 char* charBase() const { return reinterpret_cast(base_); }
68 char* charBase() const { return reinterpret_cast(BasePtr); }
8469
8570 /// This function returns a reference to the sys::Path object kept by the
8671 /// MappedFile object. This contains the path to the file that is or
8772 /// will be mapped.
88 /// @returns sys::Path containing the path name.
89 /// @brief Returns the mapped file's path as a sys::Path
90 /// @throws nothing
91 const sys::Path& path() const { return path_; }
73 const sys::Path& path() const { return Path; }
9274
9375 /// This function returns the number of bytes in the file.
94 /// @throws std::string if an error occurs
9576 size_t size() const;
9677
97 /// @}
98 /// @name Mutators
99 /// @{
100 public:
101 /// Open a file to be mapped and get its size but don't map it yet.
102 /// @returns true if an error occurred
103 bool open(
104 const sys::Path& p, ///< Path to file to be mapped
105 int options = READ_ACCESS, ///< Access mode for the mapping
106 std::string* ErrMsg = 0 ///< Optional error string pointer
107 ) {
108 path_ = p;
109 options_ = options;
78 public: // Mutators
79
80 /// Open a file to be mapped and get its size but don't map it yet. Return
81 /// true on error.
82 bool open(const sys::Path &P, int options = READ_ACCESS,
83 std::string *ErrMsg = 0) {
84 Path = P;
85 Options = options;
11086 return initialize(ErrMsg);
11187 }
11288
113 /// The mapped file is removed from memory. If the file was mapped for
89 /// unmap - Remove the mapped file from memory. If the file was mapped for
11490 /// write access, the memory contents will be automatically synchronized
11591 /// with the file's disk contents.
116 /// @brief Remove the file mapping from memory.
11792 void unmap();
11893
119 /// The mapped file is put into memory.
120 /// @returns The base memory address of the mapped file or 0 if an error
121 /// occurred.
122 /// @brief Map the file into memory.
123 void* map(
124 std::string* ErrMsg = 0///< Optional error string pointer
125 );
94 /// map - Reserve space for the file, map it into memory, and return a
95 /// pointer to it. This returns the base memory address of the mapped file
96 /// or 0 if an error occurred.
97 void *map(std::string* ErrMsg = 0);
12698
127 /// This method causes the size of the file, and consequently the size
128 /// of the mapping to be set. This is logically the same as unmap(),
99 /// resize - This method causes the size of the file, and consequently the
100 /// size of the mapping to be set. This is logically the same as unmap(),
129101 /// adjust size of the file, map(). Consequently, when calling this
130102 /// function, the caller should not rely on previous results of the
131103 /// map(), base(), or baseChar() members as they may point to invalid
132104 /// areas of memory after this call.
133 /// @throws std::string if an error occurs
134 /// @brief Set the size of the file and memory mapping.
135 bool size(size_t new_size, std::string* ErrMsg = 0);
105 bool resize(size_t new_size, std::string *ErrMsg = 0);
136106
137 void close() { if (info_) terminate(); }
107 void close() { if (MapInfo) terminate(); }
138108
139 /// @}
140 /// @name Implementation
141 /// @{
142109 private:
143 /// @brief Initialize platform-specific portion
144 bool initialize(std::string* ErrMsg);
145
146 /// @brief Terminate platform-specific portion
147 void terminate();
148
149 /// @}
150 /// @name Data
151 /// @{
152 private:
153 sys::PathWithStatus path_; ///< Path to the file.
154 int options_; ///< Options used to create the mapping
155 void* base_; ///< Pointer to the base memory address
156 mutable MappedFileInfo* info_; ///< Platform specific info for the mapping
157
158 /// @}
159 /// @name Disabled
160 /// @{
161 private:
162 ///< Disallow assignment
163 MappedFile& operator=(const MappedFile &that);
164 ///< Disallow copying
165 MappedFile(const MappedFile& that);
166 /// @}
110 bool initialize(std::string *ErrMsg);
111 void terminate();
167112 };
168 }
169 }
113 } // end namespace sys
114 } // end namespace llvm
170115
171116 #endif
3030 #include
3131 #endif
3232
33 namespace llvm {
33 using namespace llvm;
3434 using namespace sys;
3535
36 struct sys::MappedFileInfo {
37 int FD;
38 off_t Size;
39 };
36 namespace llvm {
37 namespace sys {
38 struct MappedFileInfo {
39 int FD;
40 off_t Size;
41 };
42 }
43 }
4044
4145 bool MappedFile::initialize(std::string* ErrMsg) {
4246 int mode = 0;
43 if (options_ & READ_ACCESS)
44 if (options_ & WRITE_ACCESS)
47 if (Options & READ_ACCESS)
48 if (Options & WRITE_ACCESS)
4549 mode = O_RDWR;
4650 else
4751 mode = O_RDONLY;
48 else if (options_ & WRITE_ACCESS)
52 else if (Options & WRITE_ACCESS)
4953 mode = O_WRONLY;
5054
51 int FD = ::open(path_.c_str(), mode);
55 int FD = ::open(Path.c_str(), mode);
5256 if (FD < 0) {
53 MakeErrMsg(ErrMsg, "can't open file '" + path_.toString() + "'");
57 MakeErrMsg(ErrMsg, "can't open file '" + Path.toString() + "'");
5458 return true;
5559 }
56 const FileStatus *Status = path_.getFileStatus(false, ErrMsg);
60 const FileStatus *Status = Path.getFileStatus(false, ErrMsg);
5761 if (!Status) {
5862 ::close(FD);
5963 return true;
6064 }
61 info_ = new MappedFileInfo;
62 info_->FD = FD;
63 info_->Size = Status->getSize();
65 MapInfo = new MappedFileInfo();
66 MapInfo->FD = FD;
67 MapInfo->Size = Status->getSize();
6468 return false;
6569 }
6670
6771 void MappedFile::terminate() {
68 assert(info_ && "MappedFile not initialized");
69 ::close(info_->FD);
70 delete info_;
71 info_ = 0;
72 assert(MapInfo && "MappedFile not initialized");
73 ::close(MapInfo->FD);
74 delete MapInfo;
75 MapInfo = 0;
7276 }
7377
7478 void MappedFile::unmap() {
75 assert(info_ && "MappedFile not initialized");
76 if (isMapped()) {
77 if (options_ & WRITE_ACCESS)
78 ::msync(base_, info_->Size, MS_SYNC);
79 ::munmap(base_, info_->Size);
80 base_ = 0; // Mark this as non-mapped.
81 }
79 assert(MapInfo && "MappedFile not initialized");
80 if (!isMapped()) return;
81
82 if (Options & WRITE_ACCESS)
83 ::msync(BasePtr, MapInfo->Size, MS_SYNC);
84 ::munmap(BasePtr, MapInfo->Size);
85 BasePtr = 0; // Mark this as non-mapped.
8286 }
8387
8488 void* MappedFile::map(std::string* ErrMsg) {
85 assert(info_ && "MappedFile not initialized");
86 if (!isMapped()) {
87 int prot = PROT_NONE;
88 int flags = 0;
89 assert(MapInfo && "MappedFile not initialized");
90 if (isMapped()) return BasePtr;
91
92 int prot = PROT_NONE;
93 int flags = 0;
8994 #ifdef MAP_FILE
90 flags |= MAP_FILE;
95 flags |= MAP_FILE;
9196 #endif
92 if (options_ == 0) {
93 prot = PROT_READ;
94 flags = MAP_PRIVATE;
95 } else {
96 if (options_ & READ_ACCESS)
97 prot |= PROT_READ;
98 if (options_ & WRITE_ACCESS)
99 prot |= PROT_WRITE;
100 if (options_ & EXEC_ACCESS)
101 prot |= PROT_EXEC;
102 if (options_ & SHARED_MAPPING)
103 flags |= MAP_SHARED;
104 else
105 flags |= MAP_PRIVATE;
106 }
107 size_t map_size = ((info_->Size / Process::GetPageSize())+1) *
108 Process::GetPageSize();
97 if (Options == 0) {
98 prot = PROT_READ;
99 flags = MAP_PRIVATE;
100 } else {
101 if (Options & READ_ACCESS)
102 prot |= PROT_READ;
103 if (Options & WRITE_ACCESS)
104 prot |= PROT_WRITE;
105 if (Options & EXEC_ACCESS)
106 prot |= PROT_EXEC;
107 if (Options & SHARED_MAPPING)
108 flags |= MAP_SHARED;
109 else
110 flags |= MAP_PRIVATE;
111 }
112 size_t map_size = ((MapInfo->Size / Process::GetPageSize())+1) *
113 Process::GetPageSize();
109114
110 base_ = ::mmap(0, map_size, prot, flags, info_->FD, 0);
111 if (base_ == MAP_FAILED) {
112 MakeErrMsg(ErrMsg, "Can't map file:" + path_.toString());
113 return 0;
114 }
115 BasePtr = ::mmap(0, map_size, prot, flags, MapInfo->FD, 0);
116 if (BasePtr == MAP_FAILED) {
117 MakeErrMsg(ErrMsg, "Can't map file:" + Path.toString());
118 return 0;
115119 }
116 return base_;
120 return BasePtr;
117121 }
118122
119123 size_t MappedFile::size() const {
120 assert(info_ && "MappedFile not initialized");
121 return info_->Size;
124 assert(MapInfo && "MappedFile not initialized");
125 return MapInfo->Size;
122126 }
123127
124 bool MappedFile::size(size_t new_size, std::string* ErrMsg) {
125 assert(info_ && "MappedFile not initialized");
128 bool MappedFile::resize(size_t new_size, std::string* ErrMsg) {
129 assert(MapInfo && "MappedFile not initialized");
126130
127131 // Take the mapping out of memory
128 this->unmap();
132 unmap();
129133
130134 // Adjust the current size to a page boundary
131 size_t cur_size = ((info_->Size / Process::GetPageSize())+1) *
135 size_t cur_size = ((MapInfo->Size / Process::GetPageSize())+1) *
132136 Process::GetPageSize();
133137
134138 // Adjust the new_size to a page boundary
139143 if (new_size > cur_size) {
140144 // Ensure we can allocate at least the idodes necessary to handle the
141145 // file size requested.
142 if ((off_t)-1 == ::lseek(info_->FD, new_size, SEEK_SET))
146 if ((off_t)-1 == ::lseek(MapInfo->FD, new_size, SEEK_SET))
143147 return MakeErrMsg(ErrMsg, "Can't lseek: ");
144 if (-1 == ::write(info_->FD, "\0", 1))
148 if (-1 == ::write(MapInfo->FD, "\0", 1))
145149 return MakeErrMsg(ErrMsg, "Can't write: ");
146150 }
147151
148152 // Put the mapping back into memory.
149 return this->map(ErrMsg);
153 return map(ErrMsg);
150154 }
151
152 }
153
2727 };
2828
2929 bool MappedFile::initialize(std::string* ErrMsg) {
30 assert(!info_);
31 info_ = new MappedFileInfo;
32 info_->hFile = INVALID_HANDLE_VALUE;
33 info_->hMapping = NULL;
30 assert(!MapInfo);
31 MapInfo = new MappedFileInfo;
32 MapInfo->hFile = INVALID_HANDLE_VALUE;
33 MapInfo->hMapping = NULL;
3434
35 DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ;
36 DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING;
37 DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ;
38 share = options_ & SHARED_MAPPING ? share : 0;
39 info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition,
35 DWORD mode = Options & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ;
36 DWORD disposition = Options & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING;
37 DWORD share = Options & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ;
38 share = Options & SHARED_MAPPING ? share : 0;
39 MapInfo->hFile = CreateFile(Path.c_str(), mode, share, NULL, disposition,
4040 FILE_ATTRIBUTE_NORMAL, NULL);
41 if (info_->hFile == INVALID_HANDLE_VALUE) {
42 delete info_;
43 info_ = NULL;
41 if (MapInfo->hFile == INVALID_HANDLE_VALUE) {
42 delete MapInfo;
43 MapInfo = NULL;
4444 return MakeErrMsg(ErrMsg,
45 std::string("Can't open file: ") + path_.toString());
45 std::string("Can't open file: ") + Path.toString());
4646 }
4747
4848 LARGE_INTEGER size;
49 if (!GetFileSizeEx(info_->hFile, &size) ||
50 (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) {
51 CloseHandle(info_->hFile);
52 delete info_;
53 info_ = NULL;
49 if (!GetFileSizeEx(MapInfo->hFile, &size) ||
50 (MapInfo->size = size_t(size.QuadPart), MapInfo->size != size.QuadPart)) {
51 CloseHandle(MapInfo->hFile);
52 delete MapInfo;
53 MapInfo = NULL;
5454 return MakeErrMsg(ErrMsg,
55 std::string("Can't get size of file: ") + path_.toString());
55 std::string("Can't get size of file: ") + Path.toString());
5656 }
5757
5858 return false;
6060
6161 void MappedFile::terminate() {
6262 unmap();
63 if (info_->hFile != INVALID_HANDLE_VALUE)
64 CloseHandle(info_->hFile);
65 delete info_;
66 info_ = NULL;
63 if (MapInfo->hFile != INVALID_HANDLE_VALUE)
64 CloseHandle(MapInfo->hFile);
65 delete MapInfo;
66 MapInfo = NULL;
6767 }
6868
6969 void MappedFile::unmap() {
70 assert(info_ && "MappedFile not initialized");
70 assert(MapInfo && "MappedFile not initialized");
7171 if (isMapped()) {
72 UnmapViewOfFile(base_);
73 base_ = NULL;
72 UnmapViewOfFile(BasePtr);
73 BasePtr = NULL;
7474 }
75 if (info_->hMapping != INVALID_HANDLE_VALUE) {
76 CloseHandle(info_->hMapping);
77 info_->hMapping = NULL;
75 if (MapInfo->hMapping != INVALID_HANDLE_VALUE) {
76 CloseHandle(MapInfo->hMapping);
77 MapInfo->hMapping = NULL;
7878 }
7979 }
8080
8181 void* MappedFile::map(std::string* ErrMsg) {
8282 if (!isMapped()) {
8383 DWORD prot = PAGE_READONLY;
84 if (options_ & EXEC_ACCESS)
84 if (Options & EXEC_ACCESS)
8585 prot = SEC_IMAGE;
86 else if (options_ & WRITE_ACCESS)
86 else if (Options & WRITE_ACCESS)
8787 prot = PAGE_READWRITE;
88 info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL);
89 if (info_->hMapping == NULL) {
90 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString());
88 MapInfo->hMapping = CreateFileMapping(MapInfo->hFile, NULL, prot, 0, 0, NULL);
89 if (MapInfo->hMapping == NULL) {
90 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + Path.toString());
9191 return 0;
9292 }
9393
94 prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ;
95 base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL);
96 if (base_ == NULL) {
97 CloseHandle(info_->hMapping);
98 info_->hMapping = NULL;
99 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + path_.toString());
94 prot = (Options & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ;
95 BasePtr = MapViewOfFileEx(MapInfo->hMapping, prot, 0, 0, 0, NULL);
96 if (BasePtr == NULL) {
97 CloseHandle(MapInfo->hMapping);
98 MapInfo->hMapping = NULL;
99 MakeErrMsg(ErrMsg, std::string("Can't map file: ") + Path.toString());
100100 return 0;
101101 }
102102 }
103 return base_;
103 return BasePtr;
104104 }
105105
106106 size_t MappedFile::size() const {
107 assert(info_ && "MappedFile not initialized");
108 return info_->size;
107 assert(MapInfo && "MappedFile not initialized");
108 return MapInfo->size;
109109 }
110110
111 bool MappedFile::size(size_t new_size, std::string* ErrMsg) {
112 assert(info_ && "MappedFile not initialized");
111 bool MappedFile::resize(size_t new_size, std::string* ErrMsg) {
112 assert(MapInfo && "MappedFile not initialized");
113113
114114 // Take the mapping out of memory.
115115 unmap();
119119 new_size = (new_size + pagesizem1) & ~pagesizem1;
120120
121121 // If the file needs to be extended, do so.
122 if (new_size > info_->size) {
122 if (new_size > MapInfo->size) {
123123 LARGE_INTEGER eof;
124124 eof.QuadPart = new_size;
125 if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN))
125 if (!SetFilePointerEx(MapInfo->hFile, eof, NULL, FILE_BEGIN))
126126 return MakeErrMsg(ErrMsg,
127 std::string("Can't set end of file: ") + path_.toString());
128 if (!SetEndOfFile(info_->hFile))
127 std::string("Can't set end of file: ") + Path.toString());
128 if (!SetEndOfFile(MapInfo->hFile))
129129 return MakeErrMsg(ErrMsg,
130 std::string("Can't set end of file: ") + path_.toString());
131 info_->size = new_size;
130 std::string("Can't set end of file: ") + Path.toString());
131 MapInfo->size = new_size;
132132 }
133133
134134 // Remap the file.