LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Unix/MappedFile.cpp

Go to the documentation of this file.
00001 //===- Unix/MappedFile.cpp - Unix MappedFile Implementation -----*- C++ -*-===//
00002 // 
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by Reid Spencer 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 generic Unix implementation of the MappedFile concept.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 //===----------------------------------------------------------------------===//
00015 //=== WARNING: Implementation here must contain only generic UNIX code that
00016 //===          is guaranteed to work on *all* UNIX variants.
00017 //===----------------------------------------------------------------------===//
00018 
00019 #include "llvm/System/Process.h"
00020 #include "Unix.h"
00021 #include <fcntl.h>
00022 #include <sys/mman.h>
00023 
00024 namespace llvm {
00025 using namespace sys;
00026 
00027 struct sys::MappedFileInfo {
00028   int fd_;
00029   struct stat sbuf_;
00030 };
00031 
00032 void MappedFile::initialize() {
00033   if (path_.exists()) {
00034     info_ = new MappedFileInfo;
00035     int mode = 0;
00036     if (options_&READ_ACCESS) 
00037       if (options_&WRITE_ACCESS)
00038         mode = O_RDWR;
00039       else
00040         mode = O_RDONLY;
00041     else if (options_&WRITE_ACCESS)
00042       mode = O_WRONLY;
00043     info_->fd_ = ::open(path_.c_str(),mode);
00044     if (info_->fd_ < 0) {
00045       delete info_;
00046       info_ = 0;
00047       ThrowErrno(std::string("Can't open file: ") + path_.get());
00048     }
00049     struct stat sbuf;
00050     if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
00051       ::close(info_->fd_);
00052       delete info_;
00053       info_ = 0;
00054       ThrowErrno(std::string("Can't stat file: ") + path_.get());
00055     }
00056   } else {
00057     throw std::string("Can't open file: ") + path_.get();
00058   }
00059 }
00060 
00061 void MappedFile::terminate() {
00062   assert(info_ && "MappedFile not initialized");
00063   if (info_->fd_ >= 0)
00064     ::close(info_->fd_);
00065   delete info_;
00066   info_ = 0;
00067 }
00068 
00069 void MappedFile::unmap() {
00070   assert(info_ && "MappedFile not initialized");
00071   if (isMapped()) {
00072     if (options_ & WRITE_ACCESS)
00073       ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
00074     ::munmap(base_, info_->sbuf_.st_size);
00075   }
00076 }
00077 
00078 void* MappedFile::map() {
00079   assert(info_ && "MappedFile not initialized");
00080   if (!isMapped()) {
00081     int prot = PROT_NONE;
00082     int flags = 0;
00083 #ifdef MAP_FILE
00084     flags |= MAP_FILE;
00085 #endif
00086     if (options_ == 0) {
00087       prot = PROT_READ;
00088       flags = MAP_PRIVATE;
00089     } else {
00090       if (options_ & READ_ACCESS)
00091         prot |= PROT_READ;
00092       if (options_ & WRITE_ACCESS)
00093         prot |= PROT_WRITE;
00094       if (options_ & EXEC_ACCESS)
00095         prot |= PROT_EXEC;
00096       if (options_ & SHARED_MAPPING)
00097         flags |= MAP_SHARED;
00098       else
00099         flags |= MAP_PRIVATE;
00100     }
00101     size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
00102       Process::GetPageSize();
00103 
00104     base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
00105     if (base_ == MAP_FAILED)
00106       ThrowErrno(std::string("Can't map file:") + path_.get());
00107   }
00108   return base_;
00109 }
00110 
00111 size_t MappedFile::size() {
00112   assert(info_ && "MappedFile not initialized");
00113   return info_->sbuf_.st_size;
00114 }
00115 
00116 void MappedFile::size(size_t new_size) {
00117   assert(info_ && "MappedFile not initialized");
00118 
00119   // Take the mapping out of memory
00120   this->unmap();
00121 
00122   // Adjust the current size to a page boundary
00123   size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
00124     Process::GetPageSize();
00125 
00126   // Adjust the new_size to a page boundary
00127   new_size = ((new_size / Process::GetPageSize())+1) *
00128     Process::GetPageSize();
00129 
00130   // If the file needs to be extended
00131   if (new_size > cur_size) {
00132     // Ensure we can allocate at least the idodes necessary to handle the
00133     // file size requested. 
00134     ::lseek(info_->fd_, new_size, SEEK_SET);
00135     ::write(info_->fd_, "\0", 1);
00136   }
00137 
00138   // Seek to current end of file. 
00139   this->map();
00140 }
00141 
00142 }
00143 
00144 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab