aboutsummaryrefslogtreecommitdiff
path: root/lib/System/Unix/MappedFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/System/Unix/MappedFile.cpp')
-rw-r--r--lib/System/Unix/MappedFile.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/lib/System/Unix/MappedFile.cpp b/lib/System/Unix/MappedFile.cpp
new file mode 100644
index 0000000000..d853acec4f
--- /dev/null
+++ b/lib/System/Unix/MappedFile.cpp
@@ -0,0 +1,138 @@
+//===- Unix/MappedFile.cpp - Unix MappedFile Implementation -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Reid Spencer and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the generic Unix implementation of the MappedFile concept.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/System/Process.h"
+#include "Unix.h"
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+
+namespace llvm {
+using namespace sys;
+
+struct sys::MappedFileInfo {
+ int fd_;
+ struct stat sbuf_;
+};
+
+void MappedFile::initialize() {
+ if (path_.exists()) {
+ info_ = new MappedFileInfo;
+ int mode = 0;
+ if (options_&READ_ACCESS)
+ if (options_&WRITE_ACCESS)
+ mode = O_RDWR;
+ else
+ mode = O_RDONLY;
+ else if (options_&WRITE_ACCESS)
+ mode = O_WRONLY;
+ info_->fd_ = ::open(path_.c_str(),mode);
+ if (info_->fd_ < 0) {
+ delete info_;
+ info_ = 0;
+ ThrowErrno(std::string("Can't open file: ") + path_.get());
+ }
+ struct stat sbuf;
+ if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
+ ::close(info_->fd_);
+ delete info_;
+ info_ = 0;
+ ThrowErrno(std::string("Can't stat file: ") + path_.get());
+ }
+ }
+}
+
+void MappedFile::terminate() {
+ assert(info_ && "MappedFile not initialized");
+ if (info_->fd_ >= 0)
+ ::close(info_->fd_);
+ delete info_;
+ info_ = 0;
+}
+
+void MappedFile::unmap() {
+ assert(info_ && "MappedFile not initialized");
+ if (isMapped()) {
+ if (options_ & WRITE_ACCESS)
+ ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
+ ::munmap(base_, info_->sbuf_.st_size);
+ }
+}
+
+void* MappedFile::map() {
+ if (!isMapped()) {
+ int prot = PROT_NONE;
+ int flags = MAP_FILE;
+ 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_->sbuf_.st_size / Process::GetPageSize())+1) *
+ Process::GetPageSize();
+
+ base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
+ if (base_ == MAP_FAILED)
+ ThrowErrno(std::string("Can't map file:") + path_.get());
+ }
+ return base_;
+}
+
+size_t MappedFile::size() {
+ assert(info_ && "MappedFile not initialized");
+ return info_->sbuf_.st_size;
+}
+
+void MappedFile::size(size_t new_size) {
+ assert(info_ && "MappedFile not initialized");
+
+ // Take the mapping out of memory
+ this->unmap();
+
+ // Adjust the current size to a page boundary
+ size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
+ Process::GetPageSize();
+
+ // Adjust the new_size to a page boundary
+ new_size = ((new_size / Process::GetPageSize())+1) *
+ Process::GetPageSize();
+
+ // If the file needs to be extended
+ if (new_size > cur_size) {
+ // Ensure we can allocate at least the idodes necessary to handle the
+ // file size requested.
+ ::lseek(info_->fd_, new_size, SEEK_SET);
+ ::write(info_->fd_, "\0", 1);
+ }
+
+ // Seek to current end of file.
+ this->map();
+}
+
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab