1 // Copyright (c) 2012 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 "ui/gl/safe_shared_memory_pool.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/process_util.h"
10 #include "build/build_config.h"
12 using base::SharedMemory
;
13 using base::SharedMemoryHandle
;
17 ScopedSafeSharedMemory::ScopedSafeSharedMemory(SafeSharedMemoryPool
* pool
,
18 base::SharedMemory
* memory
,
22 DCHECK(memory
->memory());
24 original_handle_
= memory
->handle();
25 safe_shared_memory_
= pool
->AcquireSafeSharedMemory(memory
, shm_size
);
26 CHECK(safe_shared_memory_
);
29 ScopedSafeSharedMemory::~ScopedSafeSharedMemory() {
30 // Release the handle. The pool will delete the SharedMemory
31 // object when it is no longer referenced.
32 pool_
->ReleaseSafeSharedMemory(original_handle_
);
35 base::SharedMemory
* ScopedSafeSharedMemory::shared_memory() {
36 return safe_shared_memory_
;
40 SafeSharedMemoryPool::SafeSharedMemoryPool()
41 : handles_acquired_(0),
43 address_space_consumed_(0),
44 max_handles_acquired_(0),
45 max_handles_consumed_(0),
46 max_address_space_consumed_(0) {
49 SafeSharedMemoryPool::~SafeSharedMemoryPool() {
52 base::SharedMemory
* SafeSharedMemoryPool::
53 AcquireSafeSharedMemory(base::SharedMemory
* shared_memory
,
55 DCHECK(shared_memory
);
56 DCHECK(shared_memory
->memory());
57 base::AutoLock
scoped_lock(lock_
);
61 max_handles_acquired_
= std::max(max_handles_acquired_
,
64 MemoryMap::iterator it
= memory_
.find(shared_memory
->handle());
65 // If we don't already have it, duplicated it.
66 if (it
== memory_
.end()) {
67 // Duplicate a new shared memory and track it.
68 TrackedMemory tracker
;
69 tracker
.safe_shared_memory
= DuplicateSharedMemory(shared_memory
, shm_size
);
70 tracker
.reference_count
= 1;
71 tracker
.shm_size
= shm_size
;
72 memory_
[shared_memory
->handle()] = tracker
;
76 address_space_consumed_
+= shm_size
;
77 max_handles_consumed_
= std::max(max_handles_consumed_
,
79 max_address_space_consumed_
= std::max(max_address_space_consumed_
,
80 address_space_consumed_
);
81 return tracker
.safe_shared_memory
;
84 // Otherwise, add a reference and return the existing one.
85 DCHECK(it
->second
.reference_count
);
86 DCHECK(it
->second
.safe_shared_memory
);
87 DCHECK(it
->second
.safe_shared_memory
->memory());
88 it
->second
.reference_count
++;
89 return it
->second
.safe_shared_memory
;
92 void SafeSharedMemoryPool::
93 ReleaseSafeSharedMemory(const base::SharedMemoryHandle
& handle
) {
94 base::AutoLock
scoped_lock(lock_
);
98 DCHECK(handles_acquired_
>= 0);
100 MemoryMap::iterator it
= memory_
.find(handle
);
101 CHECK(it
!= memory_
.end());
102 CHECK(it
->second
.reference_count
);
103 CHECK(it
->second
.safe_shared_memory
);
104 if (--it
->second
.reference_count
== 0) {
107 address_space_consumed_
-= it
->second
.shm_size
;
108 DCHECK(handles_consumed_
>= 0);
109 DCHECK(address_space_consumed_
>= 0);
110 // Delete the safe memory and remove it.
111 delete it
->second
.safe_shared_memory
;
116 SharedMemory
* SafeSharedMemoryPool::DuplicateSharedMemory(
117 SharedMemory
* shared_memory
, size_t size
) {
118 // Duplicate the handle.
119 SharedMemoryHandle duped_shared_memory_handle
;
120 if (!shared_memory
->ShareToProcess(
121 base::GetCurrentProcessHandle(),
122 &duped_shared_memory_handle
)) {
123 LOG(ERROR
) << "Failed SharedMemory::ShareToProcess";
124 LOG(ERROR
) << "Total handles acquired " << handles_acquired_
;
125 LOG(ERROR
) << "Total handles open " << handles_consumed_
;
126 LOG(ERROR
) << "Total address space " << address_space_consumed_
;
127 LOG(ERROR
) << "Max handles acquired " << max_handles_acquired_
;
128 LOG(ERROR
) << "Max handles open " << max_handles_consumed_
;
129 LOG(ERROR
) << "Max address space " << max_address_space_consumed_
;
130 CHECK(false); // Diagnosing a crash.
133 scoped_ptr
<SharedMemory
> duped_shared_memory(
134 new SharedMemory(duped_shared_memory_handle
, false));
135 // Map the shared memory into this process. This validates the size.
136 if (!duped_shared_memory
->Map(size
)) {
137 LOG(ERROR
) << "Failed SharedMemory::Map";
138 LOG(ERROR
) << "Total handles acquired " << handles_acquired_
;
139 LOG(ERROR
) << "Total handles open " << handles_consumed_
;
140 LOG(ERROR
) << "Total address space " << address_space_consumed_
;
141 LOG(ERROR
) << "Max handles acquired " << max_handles_acquired_
;
142 LOG(ERROR
) << "Max handles open " << max_handles_consumed_
;
143 LOG(ERROR
) << "Max address space " << max_address_space_consumed_
;
144 CHECK(false); // Diagnosing a crash.
147 return duped_shared_memory
.release();