blob: ef959bacab21751710818c8271d3117e3fba3720 [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 {
Chris Lattner0af70932006-07-18 07:01:08 +000038 int FD;
39 off_t Size;
Reid Spencer97374922004-10-04 11:08:32 +000040};
41
Reid Spencer6d045fc2006-08-22 16:04:22 +000042bool MappedFile::initialize(std::string* ErrMsg) {
Chris Lattnerc22c7d32006-07-18 06:52:52 +000043 int mode = 0;
Chris Lattner84bad2f2006-07-18 07:03:14 +000044 if (options_ & READ_ACCESS)
45 if (options_ & WRITE_ACCESS)
Chris Lattnerc22c7d32006-07-18 06:52:52 +000046 mode = O_RDWR;
47 else
48 mode = O_RDONLY;
Chris Lattner84bad2f2006-07-18 07:03:14 +000049 else if (options_ & WRITE_ACCESS)
Chris Lattnerc22c7d32006-07-18 06:52:52 +000050 mode = O_WRONLY;
Chris Lattnerc22c7d32006-07-18 06:52:52 +000051
Chris Lattnercca68fa2006-07-18 06:57:51 +000052 int FD = ::open(path_.c_str(), mode);
Reid Spencer6d045fc2006-08-22 16:04:22 +000053 if (FD < 0) {
54 MakeErrMsg(ErrMsg, "can't open file '" + path_.toString() + "'");
55 return true;
56 }
Chris Lattnerc22c7d32006-07-18 06:52:52 +000057 struct stat sbuf;
Chris Lattnercca68fa2006-07-18 06:57:51 +000058 if(::fstat(FD, &sbuf) < 0) {
Reid Spencer6d045fc2006-08-22 16:04:22 +000059 MakeErrMsg(ErrMsg, "can't stat file '"+ path_.toString() + "'");
Chris Lattnercca68fa2006-07-18 06:57:51 +000060 ::close(FD);
Reid Spencer6d045fc2006-08-22 16:04:22 +000061 return true;
Reid Spencer97374922004-10-04 11:08:32 +000062 }
Chris Lattnercca68fa2006-07-18 06:57:51 +000063 info_ = new MappedFileInfo;
Chris Lattner0af70932006-07-18 07:01:08 +000064 info_->FD = FD;
65 info_->Size = sbuf.st_size;
Reid Spencer6d045fc2006-08-22 16:04:22 +000066 return false;
Reid Spencer97374922004-10-04 11:08:32 +000067}
68
69void MappedFile::terminate() {
70 assert(info_ && "MappedFile not initialized");
Chris Lattner84bad2f2006-07-18 07:03:14 +000071 ::close(info_->FD);
Reid Spencer97374922004-10-04 11:08:32 +000072 delete info_;
73 info_ = 0;
74}
75
76void MappedFile::unmap() {
77 assert(info_ && "MappedFile not initialized");
78 if (isMapped()) {
79 if (options_ & WRITE_ACCESS)
Chris Lattner0af70932006-07-18 07:01:08 +000080 ::msync(base_, info_->Size, MS_SYNC);
81 ::munmap(base_, info_->Size);
Reid Spencer97374922004-10-04 11:08:32 +000082 }
83}
84
Reid Spencer6d045fc2006-08-22 16:04:22 +000085void* MappedFile::map(std::string* ErrMsg) {
Reid Spencer083507c2004-11-14 22:07:50 +000086 assert(info_ && "MappedFile not initialized");
Reid Spencer97374922004-10-04 11:08:32 +000087 if (!isMapped()) {
88 int prot = PROT_NONE;
Chris Lattner341e1da2004-10-05 00:46:21 +000089 int flags = 0;
90#ifdef MAP_FILE
91 flags |= MAP_FILE;
92#endif
Reid Spencer97374922004-10-04 11:08:32 +000093 if (options_ == 0) {
94 prot = PROT_READ;
95 flags = MAP_PRIVATE;
96 } else {
97 if (options_ & READ_ACCESS)
98 prot |= PROT_READ;
99 if (options_ & WRITE_ACCESS)
100 prot |= PROT_WRITE;
101 if (options_ & EXEC_ACCESS)
102 prot |= PROT_EXEC;
103 if (options_ & SHARED_MAPPING)
104 flags |= MAP_SHARED;
105 else
106 flags |= MAP_PRIVATE;
107 }
Chris Lattner0af70932006-07-18 07:01:08 +0000108 size_t map_size = ((info_->Size / Process::GetPageSize())+1) *
Reid Spencer97374922004-10-04 11:08:32 +0000109 Process::GetPageSize();
110
Chris Lattner0af70932006-07-18 07:01:08 +0000111 base_ = ::mmap(0, map_size, prot, flags, info_->FD, 0);
Reid Spencer6d045fc2006-08-22 16:04:22 +0000112 if (base_ == MAP_FAILED) {
113 MakeErrMsg(ErrMsg, "Can't map file:" + path_.toString());
114 return 0;
115 }
Reid Spencer97374922004-10-04 11:08:32 +0000116 }
117 return base_;
118}
119
Reid Spencer56c3ed82004-12-13 02:58:51 +0000120size_t MappedFile::size() const {
Reid Spencer97374922004-10-04 11:08:32 +0000121 assert(info_ && "MappedFile not initialized");
Chris Lattner0af70932006-07-18 07:01:08 +0000122 return info_->Size;
Reid Spencer97374922004-10-04 11:08:32 +0000123}
124
125void MappedFile::size(size_t new_size) {
126 assert(info_ && "MappedFile not initialized");
127
128 // Take the mapping out of memory
129 this->unmap();
130
131 // Adjust the current size to a page boundary
Chris Lattner0af70932006-07-18 07:01:08 +0000132 size_t cur_size = ((info_->Size / Process::GetPageSize())+1) *
Reid Spencer97374922004-10-04 11:08:32 +0000133 Process::GetPageSize();
134
135 // Adjust the new_size to a page boundary
136 new_size = ((new_size / Process::GetPageSize())+1) *
137 Process::GetPageSize();
138
139 // If the file needs to be extended
140 if (new_size > cur_size) {
141 // Ensure we can allocate at least the idodes necessary to handle the
142 // file size requested.
Chris Lattner0af70932006-07-18 07:01:08 +0000143 ::lseek(info_->FD, new_size, SEEK_SET);
144 ::write(info_->FD, "\0", 1);
Reid Spencer97374922004-10-04 11:08:32 +0000145 }
146
Reid Spencer6d045fc2006-08-22 16:04:22 +0000147 // Put the mapping back into memory.
148 this->map(0);
Reid Spencer97374922004-10-04 11:08:32 +0000149}
150
151}
152