blob: 3112a93a8d37337a4de479151437d7337c08c845 [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/MappedFile.h"
20#include "llvm/System/Process.h"
21
22namespace llvm {
23using namespace sys;
24
25struct sys::MappedFileInfo {
26 HANDLE hFile;
27 HANDLE hMapping;
28 size_t size;
29};
Reid Spencer97374922004-10-04 11:08:32 +000030
31void MappedFile::initialize() {
Reid Spencer8545fc12004-10-14 03:05:59 +000032 assert(!info_);
33 info_ = new MappedFileInfo;
34 info_->hFile = INVALID_HANDLE_VALUE;
35 info_->hMapping = NULL;
36
37 DWORD mode = options_ & WRITE_ACCESS ? GENERIC_WRITE : GENERIC_READ;
38 DWORD disposition = options_ & WRITE_ACCESS ? OPEN_ALWAYS : OPEN_EXISTING;
39 DWORD share = options_ & WRITE_ACCESS ? FILE_SHARE_WRITE : FILE_SHARE_READ;
40 share = options_ & SHARED_MAPPING ? share : 0;
41 info_->hFile = CreateFile(path_.c_str(), mode, share, NULL, disposition,
42 FILE_ATTRIBUTE_NORMAL, NULL);
43 if (info_->hFile == INVALID_HANDLE_VALUE) {
44 delete info_;
45 info_ = NULL;
46 ThrowError(std::string("Can't open file: ") + path_.get());
47 }
48
49 LARGE_INTEGER size;
50 if (!GetFileSizeEx(info_->hFile, &size) ||
51 (info_->size = size_t(size.QuadPart), info_->size != size.QuadPart)) {
52 CloseHandle(info_->hFile);
53 delete info_;
54 info_ = NULL;
55 ThrowError(std::string("Can't get size of file: ") + path_.get());
56 }
Reid Spencer97374922004-10-04 11:08:32 +000057}
58
59void MappedFile::terminate() {
Reid Spencer8545fc12004-10-14 03:05:59 +000060 unmap();
61 if (info_->hFile != INVALID_HANDLE_VALUE)
62 CloseHandle(info_->hFile);
63 delete info_;
64 info_ = NULL;
Reid Spencer97374922004-10-04 11:08:32 +000065}
66
67void MappedFile::unmap() {
Reid Spencer8545fc12004-10-14 03:05:59 +000068 assert(info_ && "MappedFile not initialized");
69 if (isMapped()) {
70 UnmapViewOfFile(base_);
71 base_ = NULL;
72 }
73 if (info_->hMapping != INVALID_HANDLE_VALUE) {
74 CloseHandle(info_->hMapping);
75 info_->hMapping = NULL;
76 }
Reid Spencer97374922004-10-04 11:08:32 +000077}
78
79void* MappedFile::map() {
Reid Spencer8545fc12004-10-14 03:05:59 +000080 if (!isMapped()) {
81 DWORD prot = PAGE_READONLY;
82 if (options_ & EXEC_ACCESS)
83 prot = SEC_IMAGE;
84 else if (options_ & WRITE_ACCESS)
85 prot = PAGE_READWRITE;
86 info_->hMapping = CreateFileMapping(info_->hFile, NULL, prot, 0, 0, NULL);
87 if (info_->hMapping == NULL)
88 ThrowError(std::string("Can't map file: ") + path_.get());
89
90 prot = (options_ & WRITE_ACCESS) ? FILE_MAP_WRITE : FILE_MAP_READ;
91 base_ = MapViewOfFileEx(info_->hMapping, prot, 0, 0, 0, NULL);
92 if (base_ == NULL) {
93 CloseHandle(info_->hMapping);
94 info_->hMapping = NULL;
95 ThrowError(std::string("Can't map file: ") + path_.get());
96 }
97 }
98 return base_;
Reid Spencer97374922004-10-04 11:08:32 +000099}
100
101size_t MappedFile::size() {
Reid Spencer8545fc12004-10-14 03:05:59 +0000102 assert(info_ && "MappedFile not initialized");
103 return info_->size;
Reid Spencer97374922004-10-04 11:08:32 +0000104}
105
106void MappedFile::size(size_t new_size) {
Reid Spencer8545fc12004-10-14 03:05:59 +0000107 assert(info_ && "MappedFile not initialized");
108
109 // Take the mapping out of memory.
110 unmap();
111
112 // Adjust the new_size to a page boundary.
113 size_t pagesizem1 = Process::GetPageSize() - 1;
114 new_size = (new_size + pagesizem1) & ~pagesizem1;
115
116 // If the file needs to be extended, do so.
117 if (new_size > info_->size) {
118 LARGE_INTEGER eof;
119 eof.QuadPart = new_size;
120 if (!SetFilePointerEx(info_->hFile, eof, NULL, FILE_BEGIN))
121 ThrowError(std::string("Can't set end of file: ") + path_.get());
122 if (!SetEndOfFile(info_->hFile))
123 ThrowError(std::string("Can't set end of file: ") + path_.get());
124 info_->size = new_size;
125 }
126
127 // Remap the file.
128 map();
129}
130
Reid Spencer97374922004-10-04 11:08:32 +0000131}
132
133// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab