blob: 36a17e0f2c4b9535fff18a04ee07d99916575f0b [file] [log] [blame]
Reid Spencer97374922004-10-04 11:08:32 +00001//===- 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"
Tanya Lattnerc5a0bbf2004-10-05 00:51:26 +000021#include <fcntl.h>
Reid Spencer97374922004-10-04 11:08:32 +000022#include <sys/mman.h>
23
24namespace llvm {
25using namespace sys;
26
27struct sys::MappedFileInfo {
28 int fd_;
29 struct stat sbuf_;
30};
31
32void MappedFile::initialize() {
33 if (path_.exists()) {
34 info_ = new MappedFileInfo;
35 int mode = 0;
36 if (options_&READ_ACCESS)
37 if (options_&WRITE_ACCESS)
38 mode = O_RDWR;
39 else
40 mode = O_RDONLY;
41 else if (options_&WRITE_ACCESS)
42 mode = O_WRONLY;
43 info_->fd_ = ::open(path_.c_str(),mode);
44 if (info_->fd_ < 0) {
45 delete info_;
46 info_ = 0;
Reid Spencer1fce0912004-12-11 00:14:15 +000047 ThrowErrno(std::string("Can't open file: ") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +000048 }
49 struct stat sbuf;
50 if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
51 ::close(info_->fd_);
52 delete info_;
53 info_ = 0;
Reid Spencer1fce0912004-12-11 00:14:15 +000054 ThrowErrno(std::string("Can't stat file: ") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +000055 }
Reid Spencer083507c2004-11-14 22:07:50 +000056 } else {
Reid Spencer1fce0912004-12-11 00:14:15 +000057 throw std::string("Can't open file: ") + path_.toString();
Reid Spencer97374922004-10-04 11:08:32 +000058 }
59}
60
61void MappedFile::terminate() {
62 assert(info_ && "MappedFile not initialized");
63 if (info_->fd_ >= 0)
64 ::close(info_->fd_);
65 delete info_;
66 info_ = 0;
67}
68
69void MappedFile::unmap() {
70 assert(info_ && "MappedFile not initialized");
71 if (isMapped()) {
72 if (options_ & WRITE_ACCESS)
73 ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
74 ::munmap(base_, info_->sbuf_.st_size);
75 }
76}
77
78void* MappedFile::map() {
Reid Spencer083507c2004-11-14 22:07:50 +000079 assert(info_ && "MappedFile not initialized");
Reid Spencer97374922004-10-04 11:08:32 +000080 if (!isMapped()) {
81 int prot = PROT_NONE;
Chris Lattner341e1da2004-10-05 00:46:21 +000082 int flags = 0;
83#ifdef MAP_FILE
84 flags |= MAP_FILE;
85#endif
Reid Spencer97374922004-10-04 11:08:32 +000086 if (options_ == 0) {
87 prot = PROT_READ;
88 flags = MAP_PRIVATE;
89 } else {
90 if (options_ & READ_ACCESS)
91 prot |= PROT_READ;
92 if (options_ & WRITE_ACCESS)
93 prot |= PROT_WRITE;
94 if (options_ & EXEC_ACCESS)
95 prot |= PROT_EXEC;
96 if (options_ & SHARED_MAPPING)
97 flags |= MAP_SHARED;
98 else
99 flags |= MAP_PRIVATE;
100 }
101 size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
102 Process::GetPageSize();
103
104 base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
105 if (base_ == MAP_FAILED)
Reid Spencer1fce0912004-12-11 00:14:15 +0000106 ThrowErrno(std::string("Can't map file:") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +0000107 }
108 return base_;
109}
110
Reid Spencer56c3ed82004-12-13 02:58:51 +0000111size_t MappedFile::size() const {
Reid Spencer97374922004-10-04 11:08:32 +0000112 assert(info_ && "MappedFile not initialized");
113 return info_->sbuf_.st_size;
114}
115
116void MappedFile::size(size_t new_size) {
117 assert(info_ && "MappedFile not initialized");
118
119 // Take the mapping out of memory
120 this->unmap();
121
122 // Adjust the current size to a page boundary
123 size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
124 Process::GetPageSize();
125
126 // Adjust the new_size to a page boundary
127 new_size = ((new_size / Process::GetPageSize())+1) *
128 Process::GetPageSize();
129
130 // If the file needs to be extended
131 if (new_size > cur_size) {
132 // Ensure we can allocate at least the idodes necessary to handle the
133 // file size requested.
134 ::lseek(info_->fd_, new_size, SEEK_SET);
135 ::write(info_->fd_, "\0", 1);
136 }
137
138 // Seek to current end of file.
139 this->map();
140}
141
142}
143
144// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab