blob: a0b2a5aafd65ef643005aac7cb1f1d639387722f [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commitd7cae122008-07-26 21:49:384
5#include "base/shared_memory.h"
6
7#include "base/logging.h"
[email protected]b6413b49b2010-09-29 20:32:228#include "base/utf_string_conversions.h"
initial.commitd7cae122008-07-26 21:49:389
[email protected]176aa482008-11-14 03:25:1510namespace base {
11
initial.commitd7cae122008-07-26 21:49:3812SharedMemory::SharedMemory()
13 : mapped_file_(NULL),
14 memory_(NULL),
15 read_only_(false),
[email protected]54e3dfa22010-10-27 18:16:0616 created_size_(0),
initial.commitd7cae122008-07-26 21:49:3817 lock_(NULL) {
18}
19
20SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
21 : mapped_file_(handle),
22 memory_(NULL),
23 read_only_(read_only),
[email protected]54e3dfa22010-10-27 18:16:0624 created_size_(0),
initial.commitd7cae122008-07-26 21:49:3825 lock_(NULL) {
26}
27
28SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
29 ProcessHandle process)
30 : mapped_file_(NULL),
31 memory_(NULL),
32 read_only_(read_only),
[email protected]54e3dfa22010-10-27 18:16:0633 created_size_(0),
initial.commitd7cae122008-07-26 21:49:3834 lock_(NULL) {
35 ::DuplicateHandle(process, handle,
36 GetCurrentProcess(), &mapped_file_,
37 STANDARD_RIGHTS_REQUIRED |
38 (read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS),
39 FALSE, 0);
40}
41
42SharedMemory::~SharedMemory() {
43 Close();
44 if (lock_ != NULL)
45 CloseHandle(lock_);
46}
47
[email protected]5fe733de2009-02-11 18:59:2048// static
49bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) {
50 return handle != NULL;
51}
52
[email protected]76aac1e2009-03-16 16:45:3653// static
54SharedMemoryHandle SharedMemory::NULLHandle() {
55 return NULL;
56}
57
[email protected]b0af04c2009-05-18 17:46:3158// static
59void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) {
60 DCHECK(handle != NULL);
61 ::CloseHandle(handle);
62}
63
[email protected]54e3dfa22010-10-27 18:16:0664bool SharedMemory::CreateAndMapAnonymous(uint32 size) {
65 return CreateAnonymous(size) && Map(size);
66}
67
68bool SharedMemory::CreateAnonymous(uint32 size) {
69 return CreateNamed("", false, size);
70}
71
72bool SharedMemory::CreateNamed(const std::string& name,
73 bool open_existing, uint32 size) {
initial.commitd7cae122008-07-26 21:49:3874 DCHECK(mapped_file_ == NULL);
[email protected]54e3dfa22010-10-27 18:16:0675 if (size == 0)
76 return false;
initial.commitd7cae122008-07-26 21:49:3877
[email protected]97684352010-03-25 15:40:2478 // NaCl's memory allocator requires 0mod64K alignment and size for
79 // shared memory objects. To allow passing shared memory to NaCl,
80 // therefore we round the size actually created to the nearest 64K unit.
81 // To avoid client impact, we continue to retain the size as the
82 // actual requested size.
83 uint32 rounded_size = (size + 0xffff) & ~0xffff;
[email protected]b6413b49b2010-09-29 20:32:2284 name_ = ASCIIToWide(name);
initial.commitd7cae122008-07-26 21:49:3885 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
[email protected]54e3dfa22010-10-27 18:16:0686 PAGE_READWRITE, 0, static_cast<DWORD>(rounded_size),
[email protected]b6413b49b2010-09-29 20:32:2287 name_.empty() ? NULL : name_.c_str());
initial.commitd7cae122008-07-26 21:49:3888 if (!mapped_file_)
89 return false;
90
[email protected]54e3dfa22010-10-27 18:16:0691 created_size_ = size;
92
initial.commitd7cae122008-07-26 21:49:3893 // Check if the shared memory pre-exists.
[email protected]54e3dfa22010-10-27 18:16:0694 if (GetLastError() == ERROR_ALREADY_EXISTS) {
95 // If the file already existed, set created_size_ to 0 to show that
96 // we don't know the size.
97 created_size_ = 0;
98 if (!open_existing) {
99 Close();
100 return false;
101 }
initial.commitd7cae122008-07-26 21:49:38102 }
[email protected]54e3dfa22010-10-27 18:16:06103
initial.commitd7cae122008-07-26 21:49:38104 return true;
105}
106
[email protected]b6413b49b2010-09-29 20:32:22107bool SharedMemory::Delete(const std::string& name) {
[email protected]9e51af92009-02-04 00:58:39108 // intentionally empty -- there is nothing for us to do on Windows.
109 return true;
110}
111
[email protected]b6413b49b2010-09-29 20:32:22112bool SharedMemory::Open(const std::string& name, bool read_only) {
initial.commitd7cae122008-07-26 21:49:38113 DCHECK(mapped_file_ == NULL);
114
[email protected]b6413b49b2010-09-29 20:32:22115 name_ = ASCIIToWide(name);
initial.commitd7cae122008-07-26 21:49:38116 read_only_ = read_only;
117 mapped_file_ = OpenFileMapping(
118 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, false,
[email protected]b6413b49b2010-09-29 20:32:22119 name_.empty() ? NULL : name_.c_str());
initial.commitd7cae122008-07-26 21:49:38120 if (mapped_file_ != NULL) {
121 // Note: size_ is not set in this case.
122 return true;
123 }
124 return false;
125}
126
[email protected]b5ab3982010-02-16 23:58:27127bool SharedMemory::Map(uint32 bytes) {
initial.commitd7cae122008-07-26 21:49:38128 if (mapped_file_ == NULL)
129 return false;
130
131 memory_ = MapViewOfFile(mapped_file_,
132 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, 0, 0, bytes);
133 if (memory_ != NULL) {
134 return true;
135 }
136 return false;
137}
138
139bool SharedMemory::Unmap() {
140 if (memory_ == NULL)
141 return false;
142
143 UnmapViewOfFile(memory_);
144 memory_ = NULL;
145 return true;
146}
147
148bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
149 SharedMemoryHandle *new_handle,
150 bool close_self) {
151 *new_handle = 0;
152 DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ;
153 DWORD options = 0;
154 HANDLE mapped_file = mapped_file_;
155 HANDLE result;
156 if (!read_only_)
157 access |= FILE_MAP_WRITE;
158 if (close_self) {
159 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
160 options = DUPLICATE_CLOSE_SOURCE;
161 mapped_file_ = NULL;
162 Unmap();
163 }
164
165 if (process == GetCurrentProcess() && close_self) {
166 *new_handle = mapped_file;
167 return true;
168 }
169
170 if (!DuplicateHandle(GetCurrentProcess(), mapped_file, process,
171 &result, access, FALSE, options))
172 return false;
173 *new_handle = result;
174 return true;
175}
176
177
178void SharedMemory::Close() {
179 if (memory_ != NULL) {
180 UnmapViewOfFile(memory_);
181 memory_ = NULL;
182 }
183
184 if (mapped_file_ != NULL) {
185 CloseHandle(mapped_file_);
186 mapped_file_ = NULL;
187 }
188}
189
190void SharedMemory::Lock() {
191 if (lock_ == NULL) {
192 std::wstring name = name_;
193 name.append(L"lock");
194 lock_ = CreateMutex(NULL, FALSE, name.c_str());
195 DCHECK(lock_ != NULL);
196 if (lock_ == NULL) {
197 DLOG(ERROR) << "Could not create mutex" << GetLastError();
198 return; // there is nothing good we can do here.
199 }
200 }
201 WaitForSingleObject(lock_, INFINITE);
202}
203
204void SharedMemory::Unlock() {
205 DCHECK(lock_ != NULL);
206 ReleaseMutex(lock_);
207}
license.botbf09a502008-08-24 00:55:55208
[email protected]5fe733de2009-02-11 18:59:20209SharedMemoryHandle SharedMemory::handle() const {
210 return mapped_file_;
211}
212
[email protected]176aa482008-11-14 03:25:15213} // namespace base