Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / ui / gl / safe_shared_memory_pool.cc
blobe838f56f1685c9a38dcbe56a6b2d4eeb9fa91e6a
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;
15 namespace gfx {
17 ScopedSafeSharedMemory::ScopedSafeSharedMemory(SafeSharedMemoryPool* pool,
18 base::SharedMemory* memory,
19 size_t shm_size) {
20 DCHECK(pool);
21 DCHECK(memory);
22 DCHECK(memory->memory());
23 pool_ = pool;
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),
42 handles_consumed_(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,
54 size_t shm_size) {
55 DCHECK(shared_memory);
56 DCHECK(shared_memory->memory());
57 base::AutoLock scoped_lock(lock_);
59 // Adjust stats.
60 handles_acquired_++;
61 max_handles_acquired_ = std::max(max_handles_acquired_,
62 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;
74 // Adjust stats.
75 handles_consumed_++;
76 address_space_consumed_ += shm_size;
77 max_handles_consumed_ = std::max(max_handles_consumed_,
78 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_);
96 // Adjust stats.
97 handles_acquired_--;
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) {
105 // Adjust stats.
106 handles_consumed_--;
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;
112 memory_.erase(it);
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.
131 return NULL;
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.
145 return NULL;
147 return duped_shared_memory.release();
150 } // namespace gfx