1 //===- Unix/MappedFile.cpp - Unix MappedFile Implementation -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file provides the generic Unix implementation of the MappedFile concept.
12 //===----------------------------------------------------------------------===//
14 //===----------------------------------------------------------------------===//
15 //=== WARNING: Implementation here must contain only generic UNIX code that
16 //=== is guaranteed to work on *all* UNIX variants.
17 //===----------------------------------------------------------------------===//
20 #include "llvm/System/Process.h"
26 #ifdef HAVE_SYS_MMAN_H
30 #ifdef HAVE_SYS_STAT_H
37 struct sys::MappedFileInfo {
42 bool MappedFile::initialize(std::string* ErrMsg) {
44 if (options_ & READ_ACCESS)
45 if (options_ & WRITE_ACCESS)
49 else if (options_ & WRITE_ACCESS)
52 int FD = ::open(path_.c_str(), mode);
54 MakeErrMsg(ErrMsg, "can't open file '" + path_.toString() + "'");
57 const FileStatus *Status = path_.getFileStatus(false, ErrMsg);
62 info_ = new MappedFileInfo;
64 info_->Size = Status->getSize();
68 void MappedFile::terminate() {
69 assert(info_ && "MappedFile not initialized");
75 void MappedFile::unmap() {
76 assert(info_ && "MappedFile not initialized");
78 if (options_ & WRITE_ACCESS)
79 ::msync(base_, info_->Size, MS_SYNC);
80 ::munmap(base_, info_->Size);
81 base_ = 0; // Mark this as non-mapped.
85 void* MappedFile::map(std::string* ErrMsg) {
86 assert(info_ && "MappedFile not initialized");
97 if (options_ & READ_ACCESS)
99 if (options_ & WRITE_ACCESS)
101 if (options_ & EXEC_ACCESS)
103 if (options_ & SHARED_MAPPING)
106 flags |= MAP_PRIVATE;
108 size_t map_size = ((info_->Size / Process::GetPageSize())+1) *
109 Process::GetPageSize();
111 base_ = ::mmap(0, map_size, prot, flags, info_->FD, 0);
112 if (base_ == MAP_FAILED) {
113 MakeErrMsg(ErrMsg, "Can't map file:" + path_.toString());
120 size_t MappedFile::size() const {
121 assert(info_ && "MappedFile not initialized");
125 bool MappedFile::size(size_t new_size, std::string* ErrMsg) {
126 assert(info_ && "MappedFile not initialized");
128 // Take the mapping out of memory
131 // Adjust the current size to a page boundary
132 size_t cur_size = ((info_->Size / Process::GetPageSize())+1) *
133 Process::GetPageSize();
135 // Adjust the new_size to a page boundary
136 new_size = ((new_size / Process::GetPageSize())+1) *
137 Process::GetPageSize();
139 // If the file needs to be extended
140 if (new_size > cur_size) {
141 // Ensure we can allocate at least the idodes necessary to handle the
142 // file size requested.
143 if ((off_t)-1 == ::lseek(info_->FD, new_size, SEEK_SET))
144 return MakeErrMsg(ErrMsg, "Can't lseek: ");
145 if (-1 == ::write(info_->FD, "\0", 1))
146 return MakeErrMsg(ErrMsg, "Can't write: ");
149 // Put the mapping back into memory.
150 return this->map(ErrMsg);