| 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 |