blob: 237e1962fbb864fd7d280b30733b594dde832829 [file] [log] [blame]
Reid Spencer97374922004-10-04 11:08:32 +00001//===- Win32/MappedFile.cpp - Win32 MappedFile Implementation ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Reid Spencer8545fc12004-10-14 03:05:59 +00005// This file was developed by Jeff Cohen and is distributed under the
Reid Spencer97374922004-10-04 11:08:32 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Reid Spencer8545fc12004-10-14 03:05:59 +000010// This file provides the Win32 implementation of the MappedFile concept.
Reid Spencer97374922004-10-04 11:08:32 +000011//
12//===----------------------------------------------------------------------===//
13
Reid Spencer8545fc12004-10-14 03:05:59 +000014//===----------------------------------------------------------------------===//
15//=== WARNING: Implementation here must contain only Win32 code.
16//===----------------------------------------------------------------------===//
17
Reid Spencer97374922004-10-04 11:08:32 +000018#include "Win32.h"
Reid Spencer8545fc12004-10-14 03:05:59 +000019#include "llvm/System/Process.h"
20
21namespace llvm {
22using namespace sys;
23
24struct sys::MappedFileInfo {
25 HANDLE hFile;
26 HANDLE hMapping;
27 size_t size;
28};
Reid Spencer97374922004-10-04 11:08:32 +000029
30void MappedFile::initialize() {
Reid Spencer8545fc12004-10-14 03:05:59 +000031 assert(!info_);
32 info_ = new MappedFileInfo;
33 info_->hFile = INVALID_HANDLE_VALUE;
34 info_->hMapping = NULL;
35
36 DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ;
37 DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING;
38 DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ;
39 share = options_ & SHARED_MAPPING ? share : 0;
40 info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition,
41 FILE_ATTRIBUTE_NORMAL, NULL);
42 if (info_->hFile == INVALID_HANDLE_VALUE) {
43 delete info_;
44 info_ = NULL;
45 ThrowError(std::string("Can't open file: ") + path_.get());
46 }
47
48 LARGE_INTEGER size;
49 if (!GetFileSizeEx(info_->hFile, &size) ||
50 (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) {
51 CloseHandle(info_->hFile);
52 delete info_;
53 info_ = NULL;
54 ThrowError(std::string("Can't get size of file: ") + path_.get());
55 }
Reid Spencer97374922004-10-04 11:08:32 +000056}
57
58void MappedFile::terminate() {
Reid Spencer8545fc12004-10-14 03:05:59 +000059 unmap();
60 if (info_->hFile != INVALID_HANDLE_VALUE)
61 CloseHandle(info_->hFile);
62 delete info_;
63 info_ = NULL;
Reid Spencer97374922004-10-04 11:08:32 +000064}
65
66void MappedFile::unmap() {
Reid Spencer8545fc12004-10-14 03:05:59 +000067 assert(info_ && "MappedFile not initialized");
68 if (isMapped()) {
69 UnmapViewOfFile(base_);
70 base_ = NULL;
71 }
72 if (info_->hMapping != INVALID_HANDLE_VALUE) {
73 CloseHandle(info_->hMapping);
74 info_->hMapping = NULL;
75 }
Reid Spencer97374922004-10-04 11:08:32 +000076}
77
78void* MappedFile::map() {
Reid Spencer8545fc12004-10-14 03:05:59 +000079 if (!isMapped()) {
80 DWORD prot = PAGE_READONLY;
81 if (options_ & EXEC_ACCESS)
82 prot = SEC_IMAGE;
83 else if (options_ & WRITE_ACCESS)
84 prot = PAGE_READWRITE;
85 info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL);
86 if (info_->hMapping == NULL)
87 ThrowError(std::string("Can't map file: ") + path_.get());
88
89 prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ;
90 base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL);
91 if (base_ == NULL) {
92 CloseHandle(info_->hMapping);
93 info_->hMapping = NULL;
94 ThrowError(std::string("Can't map file: ") + path_.get());
95 }
96 }
97 return base_;
Reid Spencer97374922004-10-04 11:08:32 +000098}
99
100size_t MappedFile::size() {
Reid Spencer8545fc12004-10-14 03:05:59 +0000101 assert(info_ && "MappedFile not initialized");
102 return info_->size;
Reid Spencer97374922004-10-04 11:08:32 +0000103}
104
105void MappedFile::size(size_t new_size) {
Reid Spencer8545fc12004-10-14 03:05:59 +0000106 assert(info_ && "MappedFile not initialized");
107
108 // Take the mapping out of memory.
109 unmap();
110
111 // Adjust the new_size to a page boundary.
112 size_t pagesizem1 = Process::GetPageSize() - 1;
113 new_size = (new_size + pagesizem1) & ~pagesizem1;
114
115 // If the file needs to be extended, do so.
116 if (new_size > info_->size) {
117 LARGE_INTEGER eof;
118 eof.QuadPart = new_size;
119 if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN))
120 ThrowError(std::string("Can't set end of file: ") + path_.get());
121 if (!SetEndOfFile(info_->hFile))
122 ThrowError(std::string("Can't set end of file: ") + path_.get());
123 info_->size = new_size;
124 }
125
126 // Remap the file.
127 map();
128}
129
Reid Spencer97374922004-10-04 11:08:32 +0000130}
131
132// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab