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"
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
)))
17 return memory_info
.RegionSize
- (static_cast<char*>(address
) -
18 static_cast<char*>(memory_info
.AllocationBase
));
25 SharedMemory::SharedMemory()
34 SharedMemory::SharedMemory(const std::wstring
& name
)
44 SharedMemory::SharedMemory(SharedMemoryHandle handle
, bool read_only
)
45 : mapped_file_(handle
),
47 read_only_(read_only
),
53 SharedMemory::SharedMemory(SharedMemoryHandle handle
, bool read_only
,
54 ProcessHandle process
)
57 read_only_(read_only
),
61 ::DuplicateHandle(process
, handle
,
62 GetCurrentProcess(), &mapped_file_
,
63 STANDARD_RIGHTS_REQUIRED
|
64 (read_only_
? FILE_MAP_READ
: FILE_MAP_ALL_ACCESS
),
68 SharedMemory::~SharedMemory() {
75 bool SharedMemory::IsHandleValid(const SharedMemoryHandle
& handle
) {
76 return handle
!= NULL
;
80 SharedMemoryHandle
SharedMemory::NULLHandle() {
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)
103 // Check maximum accounting for overflow.
105 static_cast<size_t>(std::numeric_limits
<int>::max()) - kSectionMask
)
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());
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.
123 if (!options
.open_existing
) {
132 bool SharedMemory::Delete(const std::string
& name
) {
133 // intentionally empty -- there is nothing for us to do on Windows.
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.
152 bool SharedMemory::MapAt(off_t offset
, size_t bytes
) {
153 if (mapped_file_
== NULL
)
156 if (bytes
> static_cast<size_t>(std::numeric_limits
<int>::max()))
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
),
164 if (memory_
!= NULL
) {
165 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_
) &
166 (SharedMemory::MAP_MINIMUM_ALIGNMENT
- 1));
167 mapped_size_
= GetMemorySectionSize(memory_
);
173 bool SharedMemory::Unmap() {
177 UnmapViewOfFile(memory_
);
182 bool SharedMemory::ShareToProcessCommon(ProcessHandle process
,
183 SharedMemoryHandle
*new_handle
,
186 DWORD access
= STANDARD_RIGHTS_REQUIRED
| FILE_MAP_READ
;
188 HANDLE mapped_file
= mapped_file_
;
191 access
|= FILE_MAP_WRITE
;
193 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file.
194 options
= DUPLICATE_CLOSE_SOURCE
;
199 if (process
== GetCurrentProcess() && close_self
) {
200 *new_handle
= mapped_file
;
204 if (!DuplicateHandle(GetCurrentProcess(), mapped_file
, process
,
205 &result
, access
, FALSE
, options
))
207 *new_handle
= result
;
212 void SharedMemory::Close() {
213 if (memory_
!= NULL
) {
214 UnmapViewOfFile(memory_
);
218 if (mapped_file_
!= NULL
) {
219 CloseHandle(mapped_file_
);
224 void SharedMemory::Lock() {
225 Lock(INFINITE
, NULL
);
228 bool SharedMemory::Lock(uint32 timeout_ms
, SECURITY_ATTRIBUTES
* sec_attr
) {
230 std::wstring name
= name_
;
231 name
.append(L
"lock");
232 lock_
= CreateMutex(sec_attr
, FALSE
, name
.c_str());
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
);
249 SharedMemoryHandle
SharedMemory::handle() const {