Instruction select globals with offsets better. For example, on this test
[oota-llvm.git] / lib / System / Unix / MappedFile.inc
1 //===- Unix/MappedFile.cpp - Unix MappedFile Implementation -----*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
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.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the generic Unix implementation of the MappedFile concept.
11 //
12 //===----------------------------------------------------------------------===//
13
14 //===----------------------------------------------------------------------===//
15 //=== WARNING: Implementation here must contain only generic UNIX code that
16 //===          is guaranteed to work on *all* UNIX variants.
17 //===----------------------------------------------------------------------===//
18
19 #include "llvm/System/Process.h"
20 #include "Unix.h"
21 #include <fcntl.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24
25 namespace llvm {
26 using namespace sys;
27
28 struct sys::MappedFileInfo {
29   int fd_;
30   struct stat sbuf_;
31 };
32
33 void MappedFile::initialize() {
34   if (path_.exists()) {
35     info_ = new MappedFileInfo;
36     int mode = 0;
37     if (options_&READ_ACCESS) 
38       if (options_&WRITE_ACCESS)
39         mode = O_RDWR;
40       else
41         mode = O_RDONLY;
42     else if (options_&WRITE_ACCESS)
43       mode = O_WRONLY;
44     info_->fd_ = ::open(path_.c_str(),mode);
45     if (info_->fd_ < 0) {
46       delete info_;
47       info_ = 0;
48       ThrowErrno(std::string("Can't open file: ") + path_.get());
49     }
50     struct stat sbuf;
51     if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
52       ::close(info_->fd_);
53       delete info_;
54       info_ = 0;
55       ThrowErrno(std::string("Can't stat file: ") + path_.get());
56     }
57   }
58 }
59
60 void MappedFile::terminate() {
61   assert(info_ && "MappedFile not initialized");
62   if (info_->fd_ >= 0)
63     ::close(info_->fd_);
64   delete info_;
65   info_ = 0;
66 }
67
68 void MappedFile::unmap() {
69   assert(info_ && "MappedFile not initialized");
70   if (isMapped()) {
71     if (options_ & WRITE_ACCESS)
72       ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
73     ::munmap(base_, info_->sbuf_.st_size);
74   }
75 }
76
77 void* MappedFile::map() {
78   if (!isMapped()) {
79     int prot = PROT_NONE;
80     int flags = 0;
81 #ifdef MAP_FILE
82     flags |= MAP_FILE;
83 #endif
84     if (options_ == 0) {
85       prot = PROT_READ;
86       flags = MAP_PRIVATE;
87     } else {
88       if (options_ & READ_ACCESS)
89         prot |= PROT_READ;
90       if (options_ & WRITE_ACCESS)
91         prot |= PROT_WRITE;
92       if (options_ & EXEC_ACCESS)
93         prot |= PROT_EXEC;
94       if (options_ & SHARED_MAPPING)
95         flags |= MAP_SHARED;
96       else
97         flags |= MAP_PRIVATE;
98     }
99     size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
100       Process::GetPageSize();
101
102     base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
103     if (base_ == MAP_FAILED)
104       ThrowErrno(std::string("Can't map file:") + path_.get());
105   }
106   return base_;
107 }
108
109 size_t MappedFile::size() {
110   assert(info_ && "MappedFile not initialized");
111   return info_->sbuf_.st_size;
112 }
113
114 void MappedFile::size(size_t new_size) {
115   assert(info_ && "MappedFile not initialized");
116
117   // Take the mapping out of memory
118   this->unmap();
119
120   // Adjust the current size to a page boundary
121   size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
122     Process::GetPageSize();
123
124   // Adjust the new_size to a page boundary
125   new_size = ((new_size / Process::GetPageSize())+1) *
126     Process::GetPageSize();
127
128   // If the file needs to be extended
129   if (new_size > cur_size) {
130     // Ensure we can allocate at least the idodes necessary to handle the
131     // file size requested. 
132     ::lseek(info_->fd_, new_size, SEEK_SET);
133     ::write(info_->fd_, "\0", 1);
134   }
135
136   // Seek to current end of file. 
137   this->map();
138 }
139
140 }
141
142 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab