1 // 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.
5 #include "base/shared_memory.h"
7 #include "base/logging.h"
8 #include "base/utf_string_conversions.h"
12 SharedMemory::SharedMemory()
20 SharedMemory::SharedMemory(const std::wstring
& name
)
29 SharedMemory::SharedMemory(SharedMemoryHandle handle
, bool read_only
)
30 : mapped_file_(handle
),
32 read_only_(read_only
),
37 SharedMemory::SharedMemory(SharedMemoryHandle handle
, bool read_only
,
38 ProcessHandle process
)
41 read_only_(read_only
),
44 ::DuplicateHandle(process
, handle
,
45 GetCurrentProcess(), &mapped_file_
,
46 STANDARD_RIGHTS_REQUIRED
|
47 (read_only_
? FILE_MAP_READ
: FILE_MAP_ALL_ACCESS
),
51 SharedMemory::~SharedMemory() {
58 bool SharedMemory::IsHandleValid(const SharedMemoryHandle
& handle
) {
59 return handle
!= NULL
;
63 SharedMemoryHandle
SharedMemory::NULLHandle() {
68 void SharedMemory::CloseHandle(const SharedMemoryHandle
& handle
) {
69 DCHECK(handle
!= NULL
);
70 ::CloseHandle(handle
);
73 bool SharedMemory::CreateAndMapAnonymous(uint32 size
) {
74 return CreateAnonymous(size
) && Map(size
);
77 bool SharedMemory::CreateAnonymous(uint32 size
) {
78 return CreateNamed("", false, size
);
81 bool SharedMemory::CreateNamed(const std::string
& name
,
82 bool open_existing
, uint32 size
) {
83 DCHECK(!mapped_file_
);
87 // NaCl's memory allocator requires 0mod64K alignment and size for
88 // shared memory objects. To allow passing shared memory to NaCl,
89 // therefore we round the size actually created to the nearest 64K unit.
90 // To avoid client impact, we continue to retain the size as the
91 // actual requested size.
92 uint32 rounded_size
= (size
+ 0xffff) & ~0xffff;
93 name_
= ASCIIToWide(name
);
94 mapped_file_
= CreateFileMapping(INVALID_HANDLE_VALUE
, NULL
,
95 PAGE_READWRITE
, 0, static_cast<DWORD
>(rounded_size
),
96 name_
.empty() ? NULL
: name_
.c_str());
100 created_size_
= size
;
102 // Check if the shared memory pre-exists.
103 if (GetLastError() == ERROR_ALREADY_EXISTS
) {
104 // If the file already existed, set created_size_ to 0 to show that
105 // we don't know the size.
107 if (!open_existing
) {
116 bool SharedMemory::Delete(const std::string
& name
) {
117 // intentionally empty -- there is nothing for us to do on Windows.
121 bool SharedMemory::Open(const std::string
& name
, bool read_only
) {
122 DCHECK(!mapped_file_
);
124 name_
= ASCIIToWide(name
);
125 read_only_
= read_only
;
126 mapped_file_
= OpenFileMapping(
127 read_only_
? FILE_MAP_READ
: FILE_MAP_ALL_ACCESS
, false,
128 name_
.empty() ? NULL
: name_
.c_str());
129 if (mapped_file_
!= NULL
) {
130 // Note: size_ is not set in this case.
136 bool SharedMemory::Map(uint32 bytes
) {
137 if (mapped_file_
== NULL
)
140 memory_
= MapViewOfFile(mapped_file_
,
141 read_only_
? FILE_MAP_READ
: FILE_MAP_ALL_ACCESS
, 0, 0, bytes
);
142 if (memory_
!= NULL
) {
148 bool SharedMemory::Unmap() {
152 UnmapViewOfFile(memory_
);
157 bool SharedMemory::ShareToProcessCommon(ProcessHandle process
,
158 SharedMemoryHandle
*new_handle
,
161 DWORD access
= STANDARD_RIGHTS_REQUIRED
| FILE_MAP_READ
;
163 HANDLE mapped_file
= mapped_file_
;
166 access
|= FILE_MAP_WRITE
;
168 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
169 options
= DUPLICATE_CLOSE_SOURCE
;
174 if (process
== GetCurrentProcess() && close_self
) {
175 *new_handle
= mapped_file
;
179 if (!DuplicateHandle(GetCurrentProcess(), mapped_file
, process
,
180 &result
, access
, FALSE
, options
))
182 *new_handle
= result
;
187 void SharedMemory::Close() {
188 if (memory_
!= NULL
) {
189 UnmapViewOfFile(memory_
);
193 if (mapped_file_
!= NULL
) {
194 CloseHandle(mapped_file_
);
199 void SharedMemory::Lock() {
200 Lock(INFINITE
, NULL
);
203 bool SharedMemory::Lock(uint32 timeout_ms
, SECURITY_ATTRIBUTES
* sec_attr
) {
205 std::wstring name
= name_
;
206 name
.append(L
"lock");
207 lock_
= CreateMutex(sec_attr
, FALSE
, name
.c_str());
209 PLOG(ERROR
) << "Could not create mutex.";
210 return false; // there is nothing good we can do here.
213 DWORD result
= WaitForSingleObject(lock_
, timeout_ms
);
215 // Return false for WAIT_ABANDONED, WAIT_TIMEOUT or WAIT_FAILED.
216 return (result
== WAIT_OBJECT_0
);
219 void SharedMemory::Unlock() {
220 DCHECK(lock_
!= NULL
);
224 SharedMemoryHandle
SharedMemory::handle() const {