Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / base / memory / shared_memory_win.cc
blobca0d00f96466185e0ec0bc8e24297a8b10bebe70
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/shared_memory.h"
7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
10 namespace {
12 // Returns the length of the memory section starting at the supplied address.
13 size_t GetMemorySectionSize(void* address) {
14 MEMORY_BASIC_INFORMATION memory_info;
15 if (!::VirtualQuery(address, &memory_info, sizeof(memory_info)))
16 return 0;
17 return memory_info.RegionSize - (static_cast<char*>(address) -
18 static_cast<char*>(memory_info.AllocationBase));
21 } // namespace.
23 namespace base {
25 SharedMemory::SharedMemory()
26 : mapped_file_(NULL),
27 memory_(NULL),
28 read_only_(false),
29 mapped_size_(0),
30 requested_size_(0),
31 lock_(NULL) {
34 SharedMemory::SharedMemory(const std::wstring& name)
35 : mapped_file_(NULL),
36 memory_(NULL),
37 read_only_(false),
38 requested_size_(0),
39 mapped_size_(0),
40 lock_(NULL),
41 name_(name) {
44 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
45 : mapped_file_(handle),
46 memory_(NULL),
47 read_only_(read_only),
48 requested_size_(0),
49 mapped_size_(0),
50 lock_(NULL) {
53 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
54 ProcessHandle process)
55 : mapped_file_(NULL),
56 memory_(NULL),
57 read_only_(read_only),
58 requested_size_(0),
59 mapped_size_(0),
60 lock_(NULL) {
61 ::DuplicateHandle(process, handle,
62 GetCurrentProcess(), &mapped_file_,
63 STANDARD_RIGHTS_REQUIRED |
64 (read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS),
65 FALSE, 0);
68 SharedMemory::~SharedMemory() {
69 Close();
70 if (lock_ != NULL)
71 CloseHandle(lock_);
74 // static
75 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
76 return handle != NULL;
79 // static
80 SharedMemoryHandle SharedMemory::NULLHandle() {
81 return NULL;
84 // static
85 void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
86 DCHECK(handle != NULL);
87 ::CloseHandle(handle);
90 bool SharedMemory::CreateAndMapAnonymous(size_t size) {
91 return CreateAnonymous(size) && Map(size);
94 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
95 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here,
96 // wasting 32k per mapping on average.
97 static const size_t kSectionMask = 65536 - 1;
98 DCHECK(!options.executable);
99 DCHECK(!mapped_file_);
100 if (options.size == 0)
101 return false;
103 // Check maximum accounting for overflow.
104 if (options.size >
105 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask)
106 return false;
108 size_t rounded_size = (options.size + kSectionMask) & ~kSectionMask;
109 name_ = ASCIIToWide(options.name == NULL ? "" : *options.name);
110 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
111 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size),
112 name_.empty() ? NULL : name_.c_str());
113 if (!mapped_file_)
114 return false;
116 requested_size_ = options.size;
118 // Check if the shared memory pre-exists.
119 if (GetLastError() == ERROR_ALREADY_EXISTS) {
120 // If the file already existed, set requested_size_ to 0 to show that
121 // we don't know the size.
122 requested_size_ = 0;
123 if (!options.open_existing) {
124 Close();
125 return false;
129 return true;
132 bool SharedMemory::Delete(const std::string& name) {
133 // intentionally empty -- there is nothing for us to do on Windows.
134 return true;
137 bool SharedMemory::Open(const std::string& name, bool read_only) {
138 DCHECK(!mapped_file_);
140 name_ = ASCIIToWide(name);
141 read_only_ = read_only;
142 mapped_file_ = OpenFileMapping(
143 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, false,
144 name_.empty() ? NULL : name_.c_str());
145 if (mapped_file_ != NULL) {
146 // Note: size_ is not set in this case.
147 return true;
149 return false;
152 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
153 if (mapped_file_ == NULL)
154 return false;
156 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max()))
157 return false;
159 memory_ = MapViewOfFile(mapped_file_,
160 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
161 static_cast<uint64>(offset) >> 32,
162 static_cast<DWORD>(offset),
163 bytes);
164 if (memory_ != NULL) {
165 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) &
166 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
167 mapped_size_ = GetMemorySectionSize(memory_);
168 return true;
170 return false;
173 bool SharedMemory::Unmap() {
174 if (memory_ == NULL)
175 return false;
177 UnmapViewOfFile(memory_);
178 memory_ = NULL;
179 return true;
182 bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
183 SharedMemoryHandle *new_handle,
184 bool close_self) {
185 *new_handle = 0;
186 DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ;
187 DWORD options = 0;
188 HANDLE mapped_file = mapped_file_;
189 HANDLE result;
190 if (!read_only_)
191 access |= FILE_MAP_WRITE;
192 if (close_self) {
193 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
194 options = DUPLICATE_CLOSE_SOURCE;
195 mapped_file_ = NULL;
196 Unmap();
199 if (process == GetCurrentProcess() && close_self) {
200 *new_handle = mapped_file;
201 return true;
204 if (!DuplicateHandle(GetCurrentProcess(), mapped_file, process,
205 &result, access, FALSE, options))
206 return false;
207 *new_handle = result;
208 return true;
212 void SharedMemory::Close() {
213 if (memory_ != NULL) {
214 UnmapViewOfFile(memory_);
215 memory_ = NULL;
218 if (mapped_file_ != NULL) {
219 CloseHandle(mapped_file_);
220 mapped_file_ = NULL;
224 void SharedMemory::Lock() {
225 Lock(INFINITE, NULL);
228 bool SharedMemory::Lock(uint32 timeout_ms, SECURITY_ATTRIBUTES* sec_attr) {
229 if (lock_ == NULL) {
230 std::wstring name = name_;
231 name.append(L"lock");
232 lock_ = CreateMutex(sec_attr, FALSE, name.c_str());
233 if (lock_ == NULL) {
234 DPLOG(ERROR) << "Could not create mutex.";
235 return false; // there is nothing good we can do here.
238 DWORD result = WaitForSingleObject(lock_, timeout_ms);
240 // Return false for WAIT_ABANDONED, WAIT_TIMEOUT or WAIT_FAILED.
241 return (result == WAIT_OBJECT_0);
244 void SharedMemory::Unlock() {
245 DCHECK(lock_ != NULL);
246 ReleaseMutex(lock_);
249 SharedMemoryHandle SharedMemory::handle() const {
250 return mapped_file_;
253 } // namespace base