blob: fec2408c195bc3410f165c1334fe7a6654bdd8e7 [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>
Brian Gaekee789a6b2004-10-05 18:46:59 +000023#include <sys/stat.h>
Reid Spencer97374922004-10-04 11:08:32 +000024
25namespace llvm {
26using namespace sys;
27
28struct sys::MappedFileInfo {
29 int fd_;
30 struct stat sbuf_;
31};
32
33void 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
60void 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
68void 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
77void* MappedFile::map() {
78 if (!isMapped()) {
79 int prot = PROT_NONE;
Chris Lattner341e1da2004-10-05 00:46:21 +000080 int flags = 0;
81#ifdef MAP_FILE
82 flags |= MAP_FILE;
83#endif
Reid Spencer97374922004-10-04 11:08:32 +000084 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
109size_t MappedFile::size() {
110 assert(info_ && "MappedFile not initialized");
111 return info_->sbuf_.st_size;
112}
113
114void 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