LLVM API Documentation

MappedFile.inc

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 "Unix.h"
00020 #include "llvm/System/Process.h"
00021 
00022 #ifdef HAVE_FCNTL_H
00023 #include <fcntl.h>
00024 #endif
00025 
00026 #ifdef HAVE_SYS_MMAN_H
00027 #include <sys/mman.h>
00028 #endif
00029 
00030 #ifdef HAVE_SYS_STAT_H
00031 #include <sys/stat.h>
00032 #endif
00033 
00034 namespace llvm {
00035 using namespace sys;
00036 
00037 struct sys::MappedFileInfo {
00038   int fd_;
00039   struct stat sbuf_;
00040 };
00041 
00042 void MappedFile::initialize() {
00043   if (path_.exists()) {
00044     info_ = new MappedFileInfo;
00045     int mode = 0;
00046     if (options_&READ_ACCESS) 
00047       if (options_&WRITE_ACCESS)
00048         mode = O_RDWR;
00049       else
00050         mode = O_RDONLY;
00051     else if (options_&WRITE_ACCESS)
00052       mode = O_WRONLY;
00053     info_->fd_ = ::open(path_.c_str(),mode);
00054 
00055     if (info_->fd_ < 0) {
00056       delete info_;
00057       info_ = 0;
00058       ThrowErrno(std::string("Can't open file: ") + path_.toString());
00059     }
00060     struct stat sbuf;
00061     if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
00062       ::close(info_->fd_);
00063       delete info_;
00064       info_ = 0;
00065       ThrowErrno(std::string("Can't stat file: ") + path_.toString());
00066     }
00067   } else {
00068     throw std::string("Can't open file: ") + path_.toString();
00069   }
00070 }
00071 
00072 void MappedFile::terminate() {
00073   assert(info_ && "MappedFile not initialized");
00074   if (info_->fd_ >= 0)
00075     ::close(info_->fd_);
00076   delete info_;
00077   info_ = 0;
00078 }
00079 
00080 void MappedFile::unmap() {
00081   assert(info_ && "MappedFile not initialized");
00082   if (isMapped()) {
00083     if (options_ & WRITE_ACCESS)
00084       ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
00085     ::munmap(base_, info_->sbuf_.st_size);
00086   }
00087 }
00088 
00089 void* MappedFile::map() {
00090   assert(info_ && "MappedFile not initialized");
00091   if (!isMapped()) {
00092     int prot = PROT_NONE;
00093     int flags = 0;
00094 #ifdef MAP_FILE
00095     flags |= MAP_FILE;
00096 #endif
00097     if (options_ == 0) {
00098       prot = PROT_READ;
00099       flags = MAP_PRIVATE;
00100     } else {
00101       if (options_ & READ_ACCESS)
00102         prot |= PROT_READ;
00103       if (options_ & WRITE_ACCESS)
00104         prot |= PROT_WRITE;
00105       if (options_ & EXEC_ACCESS)
00106         prot |= PROT_EXEC;
00107       if (options_ & SHARED_MAPPING)
00108         flags |= MAP_SHARED;
00109       else
00110         flags |= MAP_PRIVATE;
00111     }
00112     size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
00113       Process::GetPageSize();
00114 
00115     base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
00116     if (base_ == MAP_FAILED)
00117       ThrowErrno(std::string("Can't map file:") + path_.toString());
00118   }
00119   return base_;
00120 }
00121 
00122 size_t MappedFile::size() const {
00123   assert(info_ && "MappedFile not initialized");
00124   return info_->sbuf_.st_size;
00125 }
00126 
00127 void MappedFile::size(size_t new_size) {
00128   assert(info_ && "MappedFile not initialized");
00129 
00130   // Take the mapping out of memory
00131   this->unmap();
00132 
00133   // Adjust the current size to a page boundary
00134   size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
00135     Process::GetPageSize();
00136 
00137   // Adjust the new_size to a page boundary
00138   new_size = ((new_size / Process::GetPageSize())+1) *
00139     Process::GetPageSize();
00140 
00141   // If the file needs to be extended
00142   if (new_size > cur_size) {
00143     // Ensure we can allocate at least the idodes necessary to handle the
00144     // file size requested. 
00145     ::lseek(info_->fd_, new_size, SEEK_SET);
00146     ::write(info_->fd_, "\0", 1);
00147   }
00148 
00149   // Seek to current end of file. 
00150   this->map();
00151 }
00152 
00153 }
00154