OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/metrics/stats_table.h" | 5 #include "base/metrics/stats_table.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/memory/shared_memory.h" | 9 #include "base/memory/shared_memory.h" |
10 #include "base/process/process_handle.h" | 10 #include "base/process/process_handle.h" |
11 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
14 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
15 #include "base/threading/thread_local_storage.h" | 15 #include "base/threading/thread_local_storage.h" |
16 | 16 |
17 #if defined(OS_POSIX) | |
18 #include "base/posix/global_descriptors.h" | |
19 #include "errno.h" | |
20 #include "ipc/ipc_descriptors.h" | |
21 #endif | |
22 | |
23 namespace base { | 17 namespace base { |
24 | 18 |
25 // The StatsTable uses a shared memory segment that is laid out as follows | 19 // The StatsTable uses a shared memory segment that is laid out as follows |
26 // | 20 // |
27 // +-------------------------------------------+ | 21 // +-------------------------------------------+ |
28 // | Version | Size | MaxCounters | MaxThreads | | 22 // | Version | Size | MaxCounters | MaxThreads | |
29 // +-------------------------------------------+ | 23 // +-------------------------------------------+ |
30 // | Thread names table | | 24 // | Thread names table | |
31 // +-------------------------------------------+ | 25 // +-------------------------------------------+ |
32 // | Thread TID table | | 26 // | Thread TID table | |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 // Various header information contained in the memory mapped segment. | 92 // Various header information contained in the memory mapped segment. |
99 struct TableHeader { | 93 struct TableHeader { |
100 int version; | 94 int version; |
101 int size; | 95 int size; |
102 int max_counters; | 96 int max_counters; |
103 int max_threads; | 97 int max_threads; |
104 }; | 98 }; |
105 | 99 |
106 // Construct a new Internal based on expected size parameters, or | 100 // Construct a new Internal based on expected size parameters, or |
107 // return NULL on failure. | 101 // return NULL on failure. |
108 static Internal* New(const std::string& name, | 102 static Internal* New(const StatsTable::TableIdentifier& table, |
109 int size, | 103 int size, |
110 int max_threads, | 104 int max_threads, |
111 int max_counters); | 105 int max_counters); |
112 | 106 |
113 SharedMemory* shared_memory() { return shared_memory_.get(); } | 107 SharedMemory* shared_memory() { return shared_memory_.get(); } |
114 | 108 |
115 // Accessors for our header pointers | 109 // Accessors for our header pointers |
116 TableHeader* table_header() const { return table_header_; } | 110 TableHeader* table_header() const { return table_header_; } |
117 int version() const { return table_header_->version; } | 111 int version() const { return table_header_->version; } |
118 int size() const { return table_header_->size; } | 112 int size() const { return table_header_->size; } |
(...skipping 25 matching lines...) Expand all Loading... |
144 : shared_memory_(shared_memory), | 138 : shared_memory_(shared_memory), |
145 table_header_(NULL), | 139 table_header_(NULL), |
146 thread_names_table_(NULL), | 140 thread_names_table_(NULL), |
147 thread_tid_table_(NULL), | 141 thread_tid_table_(NULL), |
148 thread_pid_table_(NULL), | 142 thread_pid_table_(NULL), |
149 counter_names_table_(NULL), | 143 counter_names_table_(NULL), |
150 data_table_(NULL) { | 144 data_table_(NULL) { |
151 } | 145 } |
152 | 146 |
153 // Create or open the SharedMemory used by the stats table. | 147 // Create or open the SharedMemory used by the stats table. |
154 static SharedMemory* CreateSharedMemory(const std::string& name, | 148 static SharedMemory* CreateSharedMemory( |
155 int size); | 149 const StatsTable::TableIdentifier& table, |
| 150 int size); |
156 | 151 |
157 // Initializes the table on first access. Sets header values | 152 // Initializes the table on first access. Sets header values |
158 // appropriately and zeroes all counters. | 153 // appropriately and zeroes all counters. |
159 void InitializeTable(void* memory, int size, int max_counters, | 154 void InitializeTable(void* memory, int size, int max_counters, |
160 int max_threads); | 155 int max_threads); |
161 | 156 |
162 // Initializes our in-memory pointers into a pre-created StatsTable. | 157 // Initializes our in-memory pointers into a pre-created StatsTable. |
163 void ComputeMappedPointers(void* memory); | 158 void ComputeMappedPointers(void* memory); |
164 | 159 |
165 scoped_ptr<SharedMemory> shared_memory_; | 160 scoped_ptr<SharedMemory> shared_memory_; |
166 TableHeader* table_header_; | 161 TableHeader* table_header_; |
167 char* thread_names_table_; | 162 char* thread_names_table_; |
168 PlatformThreadId* thread_tid_table_; | 163 PlatformThreadId* thread_tid_table_; |
169 int* thread_pid_table_; | 164 int* thread_pid_table_; |
170 char* counter_names_table_; | 165 char* counter_names_table_; |
171 int* data_table_; | 166 int* data_table_; |
172 | 167 |
173 DISALLOW_COPY_AND_ASSIGN(Internal); | 168 DISALLOW_COPY_AND_ASSIGN(Internal); |
174 }; | 169 }; |
175 | 170 |
176 // static | 171 // static |
177 StatsTable::Internal* StatsTable::Internal::New(const std::string& name, | 172 StatsTable::Internal* StatsTable::Internal::New( |
178 int size, | 173 const StatsTable::TableIdentifier& table, |
179 int max_threads, | 174 int size, |
180 int max_counters) { | 175 int max_threads, |
181 scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(name, size)); | 176 int max_counters) { |
| 177 scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(table, size)); |
182 if (!shared_memory.get()) | 178 if (!shared_memory.get()) |
183 return NULL; | 179 return NULL; |
184 if (!shared_memory->Map(size)) | 180 if (!shared_memory->Map(size)) |
185 return NULL; | 181 return NULL; |
186 void* memory = shared_memory->memory(); | 182 void* memory = shared_memory->memory(); |
187 | 183 |
188 scoped_ptr<Internal> internal(new Internal(shared_memory.release())); | 184 scoped_ptr<Internal> internal(new Internal(shared_memory.release())); |
189 TableHeader* header = static_cast<TableHeader*>(memory); | 185 TableHeader* header = static_cast<TableHeader*>(memory); |
190 | 186 |
191 // If the version does not match, then assume the table needs | 187 // If the version does not match, then assume the table needs |
192 // to be initialized. | 188 // to be initialized. |
193 if (header->version != kTableVersion) | 189 if (header->version != kTableVersion) |
194 internal->InitializeTable(memory, size, max_counters, max_threads); | 190 internal->InitializeTable(memory, size, max_counters, max_threads); |
195 | 191 |
196 // We have a valid table, so compute our pointers. | 192 // We have a valid table, so compute our pointers. |
197 internal->ComputeMappedPointers(memory); | 193 internal->ComputeMappedPointers(memory); |
198 | 194 |
199 return internal.release(); | 195 return internal.release(); |
200 } | 196 } |
201 | 197 |
202 // static | 198 // static |
203 SharedMemory* StatsTable::Internal::CreateSharedMemory(const std::string& name, | 199 SharedMemory* StatsTable::Internal::CreateSharedMemory( |
204 int size) { | 200 const StatsTable::TableIdentifier& table, |
| 201 int size) { |
205 #if defined(OS_POSIX) | 202 #if defined(OS_POSIX) |
206 GlobalDescriptors* global_descriptors = GlobalDescriptors::GetInstance(); | 203 // Check for existing table. |
207 if (global_descriptors->MaybeGet(kStatsTableSharedMemFd) != -1) { | 204 if (table.fd != -1) |
208 // Open the shared memory file descriptor passed by the browser process. | 205 return new SharedMemory(table, false); |
209 FileDescriptor file_descriptor( | 206 |
210 global_descriptors->Get(kStatsTableSharedMemFd), false); | |
211 return new SharedMemory(file_descriptor, false); | |
212 } | |
213 // Otherwise we need to create it. | 207 // Otherwise we need to create it. |
214 scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); | 208 scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); |
215 if (!shared_memory->CreateAnonymous(size)) | 209 if (!shared_memory->CreateAnonymous(size)) |
216 return NULL; | 210 return NULL; |
217 return shared_memory.release(); | 211 return shared_memory.release(); |
218 #elif defined(OS_WIN) | 212 #elif defined(OS_WIN) |
219 scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); | 213 scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); |
220 if (!shared_memory->CreateNamedDeprecated(name, true, size)) | 214 if (table.empty()) { |
221 return NULL; | 215 // Create an anonymous table. |
| 216 if (!shared_memory->CreateAnonymous(size)) |
| 217 return NULL; |
| 218 } else { |
| 219 // Create a named table for sharing between processes. |
| 220 if (!shared_memory->CreateNamedDeprecated(table, true, size)) |
| 221 return NULL; |
| 222 } |
222 return shared_memory.release(); | 223 return shared_memory.release(); |
223 #endif | 224 #endif |
224 } | 225 } |
225 | 226 |
226 void StatsTable::Internal::InitializeTable(void* memory, int size, | 227 void StatsTable::Internal::InitializeTable(void* memory, int size, |
227 int max_counters, | 228 int max_counters, |
228 int max_threads) { | 229 int max_threads) { |
229 // Zero everything. | 230 // Zero everything. |
230 memset(memory, 0, size); | 231 memset(memory, 0, size); |
231 | 232 |
232 // Initialize the header. | 233 // Initialize the header. |
233 TableHeader* header = static_cast<TableHeader*>(memory); | 234 TableHeader* header = static_cast<TableHeader*>(memory); |
234 header->version = kTableVersion; | 235 header->version = kTableVersion; |
235 header->size = size; | 236 header->size = size; |
236 header->max_counters = max_counters; | 237 header->max_counters = max_counters; |
237 header->max_threads = max_threads; | 238 header->max_threads = max_threads; |
238 } | 239 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 // Each thread that calls RegisterThread in the StatsTable will have | 280 // Each thread that calls RegisterThread in the StatsTable will have |
280 // a TLSData stored in its TLS. | 281 // a TLSData stored in its TLS. |
281 struct StatsTable::TLSData { | 282 struct StatsTable::TLSData { |
282 StatsTable* table; | 283 StatsTable* table; |
283 int slot; | 284 int slot; |
284 }; | 285 }; |
285 | 286 |
286 // We keep a singleton table which can be easily accessed. | 287 // We keep a singleton table which can be easily accessed. |
287 StatsTable* global_table = NULL; | 288 StatsTable* global_table = NULL; |
288 | 289 |
289 StatsTable::StatsTable(const std::string& name, int max_threads, | 290 StatsTable::StatsTable(const TableIdentifier& table, |
| 291 int max_threads, |
290 int max_counters) | 292 int max_counters) |
291 : internal_(NULL), | 293 : internal_(NULL), |
292 tls_index_(SlotReturnFunction) { | 294 tls_index_(SlotReturnFunction) { |
293 int table_size = | 295 int table_size = |
294 AlignedSize(sizeof(Internal::TableHeader)) + | 296 AlignedSize(sizeof(Internal::TableHeader)) + |
295 AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) + | 297 AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) + |
296 AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) + | 298 AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) + |
297 AlignedSize(max_threads * sizeof(int)) + | 299 AlignedSize(max_threads * sizeof(int)) + |
298 AlignedSize(max_threads * sizeof(int)) + | 300 AlignedSize(max_threads * sizeof(int)) + |
299 AlignedSize((sizeof(int) * (max_counters * max_threads))); | 301 AlignedSize((sizeof(int) * (max_counters * max_threads))); |
300 | 302 |
301 internal_ = Internal::New(name, table_size, max_threads, max_counters); | 303 internal_ = Internal::New(table, table_size, max_threads, max_counters); |
302 | 304 |
303 if (!internal_) | 305 if (!internal_) |
304 DPLOG(ERROR) << "StatsTable did not initialize"; | 306 DPLOG(ERROR) << "StatsTable did not initialize"; |
305 } | 307 } |
306 | 308 |
307 StatsTable::~StatsTable() { | 309 StatsTable::~StatsTable() { |
308 // Before we tear down our copy of the table, be sure to | 310 // Before we tear down our copy of the table, be sure to |
309 // unregister our thread. | 311 // unregister our thread. |
310 UnregisterThread(); | 312 UnregisterThread(); |
311 | 313 |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 | 606 |
605 #if defined(OS_POSIX) | 607 #if defined(OS_POSIX) |
606 SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const { | 608 SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const { |
607 if (!internal_) | 609 if (!internal_) |
608 return SharedMemory::NULLHandle(); | 610 return SharedMemory::NULLHandle(); |
609 return internal_->shared_memory()->handle(); | 611 return internal_->shared_memory()->handle(); |
610 } | 612 } |
611 #endif | 613 #endif |
612 | 614 |
613 } // namespace base | 615 } // namespace base |
OLD | NEW |