OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/stats_table.h" | 5 #include "base/stats_table.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/platform_thread.h" | 8 #include "base/platform_thread.h" |
9 #include "base/process_util.h" | |
9 #include "base/shared_memory.h" | 10 #include "base/shared_memory.h" |
10 #include "base/string_util.h" | 11 #include "base/string_util.h" |
11 #include "base/thread_local_storage.h" | 12 #include "base/thread_local_storage.h" |
12 | 13 |
13 #if defined(OS_POSIX) | 14 #if defined(OS_POSIX) |
14 #include "errno.h" | 15 #include "errno.h" |
15 #endif | 16 #endif |
16 | 17 |
17 // The StatsTable uses a shared memory segment that is laid out as follows | 18 // The StatsTable uses a shared memory segment that is laid out as follows |
18 // | 19 // |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
84 // StatsTable. This is used so that we can properly cleanup when the | 85 // StatsTable. This is used so that we can properly cleanup when the |
85 // thread exits and return the table slot. | 86 // thread exits and return the table slot. |
86 // | 87 // |
87 // Each thread that calls RegisterThread in the StatsTable will have | 88 // Each thread that calls RegisterThread in the StatsTable will have |
88 // a StatsTableTLSData stored in its TLS. | 89 // a StatsTableTLSData stored in its TLS. |
89 struct StatsTableTLSData { | 90 struct StatsTableTLSData { |
90 StatsTable* table; | 91 StatsTable* table; |
91 int slot; | 92 int slot; |
92 }; | 93 }; |
93 | 94 |
94 // The SlotReturnFunction is called at thread exit for each thread | |
95 // which used the StatsTable. | |
96 static void SlotReturnFunction(void* data) { | |
97 StatsTableTLSData* tls_data = static_cast<StatsTableTLSData*>(data); | |
98 if (tls_data) { | |
99 DCHECK(tls_data->table); | |
100 tls_data->table->UnregisterThread(); | |
101 } | |
102 } | |
103 | |
104 } // namespace | 95 } // namespace |
105 | 96 |
106 // The StatsTablePrivate maintains convenience pointers into the | 97 // The StatsTablePrivate maintains convenience pointers into the |
107 // shared memory segment. Use this class to keep the data structure | 98 // shared memory segment. Use this class to keep the data structure |
108 // clean and accessible. | 99 // clean and accessible. |
109 class StatsTablePrivate { | 100 class StatsTablePrivate { |
110 public: | 101 public: |
111 // Various header information contained in the memory mapped segment. | 102 // Various header information contained in the memory mapped segment. |
112 struct TableHeader { | 103 struct TableHeader { |
113 int version; | 104 int version; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
306 | 297 |
307 DCHECK(impl_); | 298 DCHECK(impl_); |
308 | 299 |
309 // We have space, so consume a column in the table. | 300 // We have space, so consume a column in the table. |
310 std::wstring thread_name = name; | 301 std::wstring thread_name = name; |
311 if (name.empty()) | 302 if (name.empty()) |
312 thread_name = kUnknownName; | 303 thread_name = kUnknownName; |
313 base::wcslcpy(impl_->thread_name(slot), thread_name.c_str(), | 304 base::wcslcpy(impl_->thread_name(slot), thread_name.c_str(), |
314 kMaxThreadNameLength); | 305 kMaxThreadNameLength); |
315 *(impl_->thread_tid(slot)) = PlatformThread::CurrentId(); | 306 *(impl_->thread_tid(slot)) = PlatformThread::CurrentId(); |
316 // TODO(pinkerton): these should go into process_utils when it's ported | 307 *(impl_->thread_pid(slot)) = process_util::GetCurrentProcId(); |
317 #if defined(OS_WIN) | |
318 *(impl_->thread_pid(slot)) = GetCurrentProcessId(); | |
319 #elif defined(OS_POSIX) | |
320 *(impl_->thread_pid(slot)) = getpid(); | |
321 #endif | |
322 } | 308 } |
323 | 309 |
324 // Set our thread local storage. | 310 // Set our thread local storage. |
325 StatsTableTLSData* data = new StatsTableTLSData; | 311 StatsTableTLSData* data = new StatsTableTLSData; |
326 data->table = this; | 312 data->table = this; |
327 data->slot = slot; | 313 data->slot = slot; |
328 tls_index_.Set(data); | 314 tls_index_.Set(data); |
329 return slot; | 315 return slot; |
330 } | 316 } |
331 | 317 |
332 StatsTableTLSData* StatsTable::GetTLSData() const { | 318 StatsTableTLSData* StatsTable::GetTLSData() const { |
333 StatsTableTLSData* data = | 319 StatsTableTLSData* data = |
334 static_cast<StatsTableTLSData*>(tls_index_.Get()); | 320 static_cast<StatsTableTLSData*>(tls_index_.Get()); |
335 if (!data) | 321 if (!data) |
336 return NULL; | 322 return NULL; |
337 | 323 |
338 DCHECK(data->slot); | 324 DCHECK(data->slot); |
339 DCHECK_EQ(data->table, this); | 325 DCHECK_EQ(data->table, this); |
340 return data; | 326 return data; |
341 } | 327 } |
342 | 328 |
343 void StatsTable::UnregisterThread() { | 329 void StatsTable::UnregisterThread() { |
344 StatsTableTLSData* data = GetTLSData(); | 330 UnregisterThread(GetTLSData()); |
331 } | |
332 | |
333 void StatsTable::UnregisterThread(StatsTableTLSData* data) { | |
345 if (!data) | 334 if (!data) |
346 return; | 335 return; |
347 DCHECK(impl_); | 336 DCHECK(impl_); |
348 | 337 |
349 // Mark the slot free by zeroing out the thread name. | 338 // Mark the slot free by zeroing out the thread name. |
350 wchar_t* name = impl_->thread_name(data->slot); | 339 wchar_t* name = impl_->thread_name(data->slot); |
351 *name = L'\0'; | 340 *name = L'\0'; |
352 | 341 |
353 // Remove the calling thread's TLS so that it cannot use the slot. | 342 // Remove the calling thread's TLS so that it cannot use the slot. |
354 tls_index_.Set(NULL); | 343 tls_index_.Set(NULL); |
355 delete data; | 344 delete data; |
356 } | 345 } |
357 | 346 |
Dean McNamee
2008/10/31 19:20:37
Is this because you can no longer access the TLS k
| |
347 void StatsTable::SlotReturnFunction(void* data) { | |
348 StatsTableTLSData* tls_data = static_cast<StatsTableTLSData*>(data); | |
349 if (tls_data) { | |
350 DCHECK(tls_data->table); | |
351 tls_data->table->UnregisterThread(tls_data); | |
352 } | |
353 } | |
354 | |
358 int StatsTable::CountThreadsRegistered() const { | 355 int StatsTable::CountThreadsRegistered() const { |
359 if (!impl_) | 356 if (!impl_) |
360 return 0; | 357 return 0; |
361 | 358 |
362 // Loop through the shared memory and count the threads that are active. | 359 // Loop through the shared memory and count the threads that are active. |
363 // We intentionally do not lock the table during the operation. | 360 // We intentionally do not lock the table during the operation. |
364 int count = 0; | 361 int count = 0; |
365 for (int index = 1; index <= impl_->max_threads(); index++) { | 362 for (int index = 1; index <= impl_->max_threads(); index++) { |
366 wchar_t* name = impl_->thread_name(index); | 363 wchar_t* name = impl_->thread_name(index); |
367 if (*name != L'\0') | 364 if (*name != L'\0') |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 return NULL; | 546 return NULL; |
550 | 547 |
551 // Find the counter id for the counter. | 548 // Find the counter id for the counter. |
552 std::wstring str_name(name); | 549 std::wstring str_name(name); |
553 int counter = table->FindCounter(str_name); | 550 int counter = table->FindCounter(str_name); |
554 | 551 |
555 // Now we can find the location in the table. | 552 // Now we can find the location in the table. |
556 return table->GetLocation(counter, slot); | 553 return table->GetLocation(counter, slot); |
557 } | 554 } |
558 | 555 |
OLD | NEW |