blob: 508d4235c436339d70519fc50b96fa89c834b1a3 [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
Reid Spencer97374922004-10-04 11:08:32 +000019#include "Unix.h"
Reid Spencercdf54d02004-12-27 06:16:52 +000020#include "llvm/System/Process.h"
21
22#ifdef HAVE_FCNTL_H
Tanya Lattnerc5a0bbf2004-10-05 00:51:26 +000023#include <fcntl.h>
Reid Spencercdf54d02004-12-27 06:16:52 +000024#endif
25
26#ifdef HAVE_SYS_MMAN_H
Reid Spencer97374922004-10-04 11:08:32 +000027#include <sys/mman.h>
Reid Spencercdf54d02004-12-27 06:16:52 +000028#endif
29
30#ifdef HAVE_SYS_STAT_H
31#include <sys/stat.h>
32#endif
Reid Spencer97374922004-10-04 11:08:32 +000033
34namespace llvm {
35using namespace sys;
36
37struct sys::MappedFileInfo {
38 int fd_;
39 struct stat sbuf_;
40};
41
42void MappedFile::initialize() {
43 if (path_.exists()) {
44 info_ = new MappedFileInfo;
45 int mode = 0;
46 if (options_&READ_ACCESS)
47 if (options_&WRITE_ACCESS)
48 mode = O_RDWR;
49 else
50 mode = O_RDONLY;
51 else if (options_&WRITE_ACCESS)
52 mode = O_WRONLY;
53 info_->fd_ = ::open(path_.c_str(),mode);
Chris Lattner946af522005-02-13 22:46:37 +000054
Reid Spencer97374922004-10-04 11:08:32 +000055 if (info_->fd_ < 0) {
56 delete info_;
57 info_ = 0;
Reid Spencer1fce0912004-12-11 00:14:15 +000058 ThrowErrno(std::string("Can't open file: ") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +000059 }
60 struct stat sbuf;
61 if(::fstat(info_->fd_, &info_->sbuf_) < 0) {
62 ::close(info_->fd_);
63 delete info_;
64 info_ = 0;
Reid Spencer1fce0912004-12-11 00:14:15 +000065 ThrowErrno(std::string("Can't stat file: ") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +000066 }
Reid Spencer083507c2004-11-14 22:07:50 +000067 } else {
Reid Spencer1fce0912004-12-11 00:14:15 +000068 throw std::string("Can't open file: ") + path_.toString();
Reid Spencer97374922004-10-04 11:08:32 +000069 }
70}
71
72void MappedFile::terminate() {
73 assert(info_ && "MappedFile not initialized");
74 if (info_->fd_ >= 0)
75 ::close(info_->fd_);
76 delete info_;
77 info_ = 0;
78}
79
80void MappedFile::unmap() {
81 assert(info_ && "MappedFile not initialized");
82 if (isMapped()) {
83 if (options_ & WRITE_ACCESS)
84 ::msync(base_, info_->sbuf_.st_size, MS_SYNC);
85 ::munmap(base_, info_->sbuf_.st_size);
86 }
87}
88
89void* MappedFile::map() {
Reid Spencer083507c2004-11-14 22:07:50 +000090 assert(info_ && "MappedFile not initialized");
Reid Spencer97374922004-10-04 11:08:32 +000091 if (!isMapped()) {
92 int prot = PROT_NONE;
Chris Lattner341e1da2004-10-05 00:46:21 +000093 int flags = 0;
94#ifdef MAP_FILE
95 flags |= MAP_FILE;
96#endif
Reid Spencer97374922004-10-04 11:08:32 +000097 if (options_ == 0) {
98 prot = PROT_READ;
99 flags = MAP_PRIVATE;
100 } else {
101 if (options_ & READ_ACCESS)
102 prot |= PROT_READ;
103 if (options_ & WRITE_ACCESS)
104 prot |= PROT_WRITE;
105 if (options_ & EXEC_ACCESS)
106 prot |= PROT_EXEC;
107 if (options_ & SHARED_MAPPING)
108 flags |= MAP_SHARED;
109 else
110 flags |= MAP_PRIVATE;
111 }
112 size_t map_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
113 Process::GetPageSize();
114
115 base_ = ::mmap(0, map_size, prot, flags, info_->fd_, 0);
116 if (base_ == MAP_FAILED)
Reid Spencer1fce0912004-12-11 00:14:15 +0000117 ThrowErrno(std::string("Can't map file:") + path_.toString());
Reid Spencer97374922004-10-04 11:08:32 +0000118 }
119 return base_;
120}
121
Reid Spencer56c3ed82004-12-13 02:58:51 +0000122size_t MappedFile::size() const {
Reid Spencer97374922004-10-04 11:08:32 +0000123 assert(info_ && "MappedFile not initialized");
124 return info_->sbuf_.st_size;
125}
126
127void MappedFile::size(size_t new_size) {
128 assert(info_ && "MappedFile not initialized");
129
130 // Take the mapping out of memory
131 this->unmap();
132
133 // Adjust the current size to a page boundary
134 size_t cur_size = ((info_->sbuf_.st_size / Process::GetPageSize())+1) *
135 Process::GetPageSize();
136
137 // Adjust the new_size to a page boundary
138 new_size = ((new_size / Process::GetPageSize())+1) *
139 Process::GetPageSize();
140
141 // If the file needs to be extended
142 if (new_size > cur_size) {
143 // Ensure we can allocate at least the idodes necessary to handle the
144 // file size requested.
145 ::lseek(info_->fd_, new_size, SEEK_SET);
146 ::write(info_->fd_, "\0", 1);
147 }
148
149 // Seek to current end of file.
150 this->map();
151}
152
153}
154