Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: base/tracked_objects.cc

Issue 2488073002: Reuse ThreadData instances associated with terminated named threads. (Closed)
Patch Set: fix test error Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/tracked_objects.h" 5 #include "base/tracked_objects.h"
6 6
7 #include <ctype.h>
7 #include <limits.h> 8 #include <limits.h>
8 #include <stdlib.h> 9 #include <stdlib.h>
9 10
10 #include "base/atomicops.h" 11 #include "base/atomicops.h"
11 #include "base/base_switches.h" 12 #include "base/base_switches.h"
12 #include "base/command_line.h" 13 #include "base/command_line.h"
13 #include "base/compiler_specific.h" 14 #include "base/compiler_specific.h"
14 #include "base/debug/leak_annotations.h" 15 #include "base/debug/leak_annotations.h"
15 #include "base/logging.h" 16 #include "base/logging.h"
16 #include "base/process/process_handle.h" 17 #include "base/process/process_handle.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/third_party/valgrind/memcheck.h" 18 #include "base/third_party/valgrind/memcheck.h"
19 #include "base/threading/worker_pool.h" 19 #include "base/threading/worker_pool.h"
20 #include "base/tracking_info.h" 20 #include "base/tracking_info.h"
21 #include "build/build_config.h" 21 #include "build/build_config.h"
22 22
23 using base::TimeDelta; 23 using base::TimeDelta;
24 24
25 namespace base { 25 namespace base {
26 class TimeDelta; 26 class TimeDelta;
27 } 27 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 switches::kProfilerTiming) == 67 switches::kProfilerTiming) ==
68 switches::kProfilerTimingDisabledValue) 68 switches::kProfilerTimingDisabledValue)
69 ? DISABLED_TIMING 69 ? DISABLED_TIMING
70 : ENABLED_TIMING; 70 : ENABLED_TIMING;
71 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, 71 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled,
72 current_timing_enabled); 72 current_timing_enabled);
73 } 73 }
74 return current_timing_enabled == ENABLED_TIMING; 74 return current_timing_enabled == ENABLED_TIMING;
75 } 75 }
76 76
77 // Sanitize a thread name by replacing trailing sequence of digits with "*".
78 // Examples:
79 // 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*"
80 // 2. "Chrome_IOThread" => "Chrome_IOThread"
81 std::string SanitizeThreadName(const std::string& thread_name) {
82 size_t i = thread_name.length();
83
84 while (i > 0 && isdigit(thread_name[i - 1]))
85 --i;
86
87 if (i == thread_name.length())
88 return thread_name;
89
90 return thread_name.substr(0, i) + '*';
91 }
92
77 } // namespace 93 } // namespace
78 94
79 //------------------------------------------------------------------------------ 95 //------------------------------------------------------------------------------
80 // DeathData tallies durations when a death takes place. 96 // DeathData tallies durations when a death takes place.
81 97
82 DeathData::DeathData() 98 DeathData::DeathData()
83 : count_(0), 99 : count_(0),
84 sample_probability_count_(0), 100 sample_probability_count_(0),
85 run_duration_sum_(0), 101 run_duration_sum_(0),
86 queue_duration_sum_(0), 102 queue_duration_sum_(0),
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 : location_(location), 261 : location_(location),
246 birth_thread_(&current) { 262 birth_thread_(&current) {
247 } 263 }
248 264
249 //------------------------------------------------------------------------------ 265 //------------------------------------------------------------------------------
250 BirthOnThreadSnapshot::BirthOnThreadSnapshot() { 266 BirthOnThreadSnapshot::BirthOnThreadSnapshot() {
251 } 267 }
252 268
253 BirthOnThreadSnapshot::BirthOnThreadSnapshot(const BirthOnThread& birth) 269 BirthOnThreadSnapshot::BirthOnThreadSnapshot(const BirthOnThread& birth)
254 : location(birth.location()), 270 : location(birth.location()),
255 thread_name(birth.birth_thread()->thread_name()) { 271 thread_name(birth.birth_thread()->sanitized_thread_name()) {}
256 }
257 272
258 BirthOnThreadSnapshot::~BirthOnThreadSnapshot() { 273 BirthOnThreadSnapshot::~BirthOnThreadSnapshot() {
259 } 274 }
260 275
261 //------------------------------------------------------------------------------ 276 //------------------------------------------------------------------------------
262 Births::Births(const Location& location, const ThreadData& current) 277 Births::Births(const Location& location, const ThreadData& current)
263 : BirthOnThread(location, current), 278 : BirthOnThread(location, current),
264 birth_count_(1) { } 279 birth_count_(1) { }
265 280
266 int Births::birth_count() const { return birth_count_; } 281 int Births::birth_count() const { return birth_count_; }
(...skipping 11 matching lines...) Expand all
278 // static 293 // static
279 ThreadData::NowFunction* ThreadData::now_function_for_testing_ = NULL; 294 ThreadData::NowFunction* ThreadData::now_function_for_testing_ = NULL;
280 295
281 // A TLS slot which points to the ThreadData instance for the current thread. 296 // A TLS slot which points to the ThreadData instance for the current thread.
282 // We do a fake initialization here (zeroing out data), and then the real 297 // We do a fake initialization here (zeroing out data), and then the real
283 // in-place construction happens when we call tls_index_.Initialize(). 298 // in-place construction happens when we call tls_index_.Initialize().
284 // static 299 // static
285 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; 300 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER;
286 301
287 // static 302 // static
288 int ThreadData::worker_thread_data_creation_count_ = 0;
289
290 // static
291 int ThreadData::cleanup_count_ = 0; 303 int ThreadData::cleanup_count_ = 0;
292 304
293 // static 305 // static
294 int ThreadData::incarnation_counter_ = 0; 306 int ThreadData::incarnation_counter_ = 0;
295 307
296 // static 308 // static
297 ThreadData* ThreadData::all_thread_data_list_head_ = NULL; 309 ThreadData* ThreadData::all_thread_data_list_head_ = NULL;
298 310
299 // static 311 // static
300 ThreadData* ThreadData::first_retired_worker_ = NULL; 312 ThreadData* ThreadData::first_retired_thread_data_ = NULL;
301 313
302 // static 314 // static
303 base::LazyInstance<base::Lock>::Leaky 315 base::LazyInstance<base::Lock>::Leaky
304 ThreadData::list_lock_ = LAZY_INSTANCE_INITIALIZER; 316 ThreadData::list_lock_ = LAZY_INSTANCE_INITIALIZER;
305 317
306 // static 318 // static
307 base::subtle::Atomic32 ThreadData::status_ = ThreadData::UNINITIALIZED; 319 base::subtle::Atomic32 ThreadData::status_ = ThreadData::UNINITIALIZED;
308 320
309 ThreadData::ThreadData(const std::string& suggested_name) 321 ThreadData::ThreadData(const std::string& sanitized_thread_name)
310 : next_(NULL), 322 : next_(NULL),
311 next_retired_worker_(NULL), 323 next_retired_(NULL),
312 worker_thread_number_(0), 324 sanitized_thread_name_(sanitized_thread_name),
313 incarnation_count_for_pool_(-1), 325 incarnation_count_for_pool_(-1),
314 current_stopwatch_(NULL) { 326 current_stopwatch_(NULL) {
315 DCHECK_GE(suggested_name.size(), 0u);
316 thread_name_ = suggested_name;
317 PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. 327 PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
318 } 328 }
319 329
320 ThreadData::ThreadData(int thread_number)
321 : next_(NULL),
322 next_retired_worker_(NULL),
323 worker_thread_number_(thread_number),
324 incarnation_count_for_pool_(-1),
325 current_stopwatch_(NULL) {
326 CHECK_GT(thread_number, 0);
327 base::StringAppendF(&thread_name_, "WorkerThread-%d", thread_number);
328 PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
329 }
330
331 ThreadData::~ThreadData() { 330 ThreadData::~ThreadData() {
332 } 331 }
333 332
334 void ThreadData::PushToHeadOfList() { 333 void ThreadData::PushToHeadOfList() {
335 // Toss in a hint of randomness (atop the uniniitalized value). 334 // Toss in a hint of randomness (atop the uniniitalized value).
336 (void)VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(&random_number_, 335 (void)VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(&random_number_,
337 sizeof(random_number_)); 336 sizeof(random_number_));
338 MSAN_UNPOISON(&random_number_, sizeof(random_number_)); 337 MSAN_UNPOISON(&random_number_, sizeof(random_number_));
339 random_number_ += static_cast<uint32_t>(this - static_cast<ThreadData*>(0)); 338 random_number_ += static_cast<uint32_t>(this - static_cast<ThreadData*>(0));
340 random_number_ ^= (Now() - TrackedTime()).InMilliseconds(); 339 random_number_ ^= (Now() - TrackedTime()).InMilliseconds();
341 340
342 DCHECK(!next_); 341 DCHECK(!next_);
343 base::AutoLock lock(*list_lock_.Pointer()); 342 base::AutoLock lock(*list_lock_.Pointer());
344 incarnation_count_for_pool_ = incarnation_counter_; 343 incarnation_count_for_pool_ = incarnation_counter_;
345 next_ = all_thread_data_list_head_; 344 next_ = all_thread_data_list_head_;
346 all_thread_data_list_head_ = this; 345 all_thread_data_list_head_ = this;
347 } 346 }
348 347
349 // static 348 // static
350 ThreadData* ThreadData::first() { 349 ThreadData* ThreadData::first() {
351 base::AutoLock lock(*list_lock_.Pointer()); 350 base::AutoLock lock(*list_lock_.Pointer());
352 return all_thread_data_list_head_; 351 return all_thread_data_list_head_;
353 } 352 }
354 353
355 ThreadData* ThreadData::next() const { return next_; } 354 ThreadData* ThreadData::next() const { return next_; }
356 355
357 // static 356 // static
358 void ThreadData::InitializeThreadContext(const std::string& suggested_name) { 357 void ThreadData::InitializeThreadContext(const std::string& thread_name) {
359 if (base::WorkerPool::RunsTasksOnCurrentThread()) 358 if (base::WorkerPool::RunsTasksOnCurrentThread())
360 return; 359 return;
361 EnsureTlsInitialization(); 360 EnsureTlsInitialization();
362 ThreadData* current_thread_data = 361 ThreadData* current_thread_data =
363 reinterpret_cast<ThreadData*>(tls_index_.Get()); 362 reinterpret_cast<ThreadData*>(tls_index_.Get());
364 if (current_thread_data) 363 if (current_thread_data)
365 return; // Browser tests instigate this. 364 return; // Browser tests instigate this.
366 current_thread_data = new ThreadData(suggested_name); 365 current_thread_data =
366 GetRetiredOrCreateThreadData(SanitizeThreadName(thread_name));
367 tls_index_.Set(current_thread_data); 367 tls_index_.Set(current_thread_data);
368 } 368 }
369 369
370 // static 370 // static
371 ThreadData* ThreadData::Get() { 371 ThreadData* ThreadData::Get() {
372 if (!tls_index_.initialized()) 372 if (!tls_index_.initialized())
373 return NULL; // For unittests only. 373 return NULL; // For unittests only.
374 ThreadData* registered = reinterpret_cast<ThreadData*>(tls_index_.Get()); 374 ThreadData* registered = reinterpret_cast<ThreadData*>(tls_index_.Get());
375 if (registered) 375 if (registered)
376 return registered; 376 return registered;
377 377
378 // We must be a worker thread, since we didn't pre-register. 378 // We must be a worker thread, since we didn't pre-register.
379 ThreadData* worker_thread_data = NULL; 379 ThreadData* worker_thread_data =
380 int worker_thread_number = 0; 380 GetRetiredOrCreateThreadData("WorkerThread-*");
381 {
382 base::AutoLock lock(*list_lock_.Pointer());
383 if (first_retired_worker_) {
384 worker_thread_data = first_retired_worker_;
385 first_retired_worker_ = first_retired_worker_->next_retired_worker_;
386 worker_thread_data->next_retired_worker_ = NULL;
387 } else {
388 worker_thread_number = ++worker_thread_data_creation_count_;
389 }
390 }
391
392 // If we can't find a previously used instance, then we have to create one.
393 if (!worker_thread_data) {
394 DCHECK_GT(worker_thread_number, 0);
395 worker_thread_data = new ThreadData(worker_thread_number);
396 }
397 DCHECK_GT(worker_thread_data->worker_thread_number_, 0);
398
399 tls_index_.Set(worker_thread_data); 381 tls_index_.Set(worker_thread_data);
400 return worker_thread_data; 382 return worker_thread_data;
401 } 383 }
402 384
403 // static 385 // static
404 void ThreadData::OnThreadTermination(void* thread_data) { 386 void ThreadData::OnThreadTermination(void* thread_data) {
405 DCHECK(thread_data); // TLS should *never* call us with a NULL. 387 DCHECK(thread_data); // TLS should *never* call us with a NULL.
406 // We must NOT do any allocations during this callback. There is a chance 388 // We must NOT do any allocations during this callback. There is a chance
407 // that the allocator is no longer active on this thread. 389 // that the allocator is no longer active on this thread.
408 reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); 390 reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup();
409 } 391 }
410 392
411 void ThreadData::OnThreadTerminationCleanup() { 393 void ThreadData::OnThreadTerminationCleanup() {
394 // We must NOT do any allocations during this callback. There is a chance that
395 // the allocator is no longer active on this thread.
396
412 // The list_lock_ was created when we registered the callback, so it won't be 397 // The list_lock_ was created when we registered the callback, so it won't be
413 // allocated here despite the lazy reference. 398 // allocated here despite the lazy reference.
414 base::AutoLock lock(*list_lock_.Pointer()); 399 base::AutoLock lock(*list_lock_.Pointer());
415 if (incarnation_counter_ != incarnation_count_for_pool_) 400 if (incarnation_counter_ != incarnation_count_for_pool_)
416 return; // ThreadData was constructed in an earlier unit test. 401 return; // ThreadData was constructed in an earlier unit test.
417 ++cleanup_count_; 402 ++cleanup_count_;
418 // Only worker threads need to be retired and reused. 403
419 if (!worker_thread_number_) { 404 // Add this ThreadData to a retired list so that it can be reused by a thread
420 return; 405 // with the same name sanitized name in the future.
421 } 406 DCHECK(!next_retired_);
422 // We must NOT do any allocations during this callback. 407 next_retired_ = first_retired_thread_data_;
423 // Using the simple linked lists avoids all allocations. 408 first_retired_thread_data_ = this;
424 DCHECK_EQ(this->next_retired_worker_, reinterpret_cast<ThreadData*>(NULL));
425 this->next_retired_worker_ = first_retired_worker_;
426 first_retired_worker_ = this;
427 } 409 }
428 410
429 // static 411 // static
430 void ThreadData::Snapshot(int current_profiling_phase, 412 void ThreadData::Snapshot(int current_profiling_phase,
431 ProcessDataSnapshot* process_data_snapshot) { 413 ProcessDataSnapshot* process_data_snapshot) {
432 // Get an unchanging copy of a ThreadData list. 414 // Get an unchanging copy of a ThreadData list.
433 ThreadData* my_list = ThreadData::first(); 415 ThreadData* my_list = ThreadData::first();
434 416
435 // Gather data serially. 417 // Gather data serially.
436 // This hackish approach *can* get some slightly corrupt tallies, as we are 418 // This hackish approach *can* get some slightly corrupt tallies, as we are
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 // phase, if any. Store the deltas in the result. 610 // phase, if any. Store the deltas in the result.
629 for (const DeathDataPhaseSnapshot* phase = &death.second; phase; 611 for (const DeathDataPhaseSnapshot* phase = &death.second; phase;
630 phase = phase->prev) { 612 phase = phase->prev) {
631 const DeathDataSnapshot& death_data = 613 const DeathDataSnapshot& death_data =
632 phase->prev ? phase->death_data.Delta(phase->prev->death_data) 614 phase->prev ? phase->death_data.Delta(phase->prev->death_data)
633 : phase->death_data; 615 : phase->death_data;
634 616
635 if (death_data.count > 0) { 617 if (death_data.count > 0) {
636 (*phased_snapshots)[phase->profiling_phase].tasks.push_back( 618 (*phased_snapshots)[phase->profiling_phase].tasks.push_back(
637 TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data, 619 TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data,
638 thread_name())); 620 sanitized_thread_name()));
639 } 621 }
640 } 622 }
641 } 623 }
642 } 624 }
643 625
644 // This may be called from another thread. 626 // This may be called from another thread.
645 void ThreadData::SnapshotMaps(int profiling_phase, 627 void ThreadData::SnapshotMaps(int profiling_phase,
646 BirthMap* birth_map, 628 BirthMap* birth_map,
647 DeathsSnapshot* deaths) { 629 DeathsSnapshot* deaths) {
648 base::AutoLock lock(map_lock_); 630 base::AutoLock lock(map_lock_);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 if (now_function_for_testing_) 721 if (now_function_for_testing_)
740 return TrackedTime::FromMilliseconds((*now_function_for_testing_)()); 722 return TrackedTime::FromMilliseconds((*now_function_for_testing_)());
741 if (IsProfilerTimingEnabled() && TrackingStatus()) 723 if (IsProfilerTimingEnabled() && TrackingStatus())
742 return TrackedTime::Now(); 724 return TrackedTime::Now();
743 return TrackedTime(); // Super fast when disabled, or not compiled. 725 return TrackedTime(); // Super fast when disabled, or not compiled.
744 } 726 }
745 727
746 // static 728 // static
747 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) { 729 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) {
748 base::AutoLock lock(*list_lock_.Pointer()); 730 base::AutoLock lock(*list_lock_.Pointer());
749 if (worker_thread_data_creation_count_ == 0)
750 return; // We haven't really run much, and couldn't have leaked.
751 731
752 // TODO(jar): until this is working on XP, don't run the real test. 732 // TODO(jar): until this is working on XP, don't run the real test.
753 #if 0 733 #if 0
754 // Verify that we've at least shutdown/cleanup the major namesd threads. The 734 // Verify that we've at least shutdown/cleanup the major namesd threads. The
755 // caller should tell us how many thread shutdowns should have taken place by 735 // caller should tell us how many thread shutdowns should have taken place by
756 // now. 736 // now.
757 CHECK_GT(cleanup_count_, major_threads_shutdown_count); 737 CHECK_GT(cleanup_count_, major_threads_shutdown_count);
758 #endif 738 #endif
759 } 739 }
760 740
761 // static 741 // static
762 void ThreadData::ShutdownSingleThreadedCleanup(bool leak) { 742 void ThreadData::ShutdownSingleThreadedCleanup(bool leak) {
763 // This is only called from test code, where we need to cleanup so that 743 // This is only called from test code, where we need to cleanup so that
764 // additional tests can be run. 744 // additional tests can be run.
765 // We must be single threaded... but be careful anyway. 745 // We must be single threaded... but be careful anyway.
766 InitializeAndSetTrackingStatus(DEACTIVATED); 746 InitializeAndSetTrackingStatus(DEACTIVATED);
767 747
768 ThreadData* thread_data_list; 748 ThreadData* thread_data_list;
769 { 749 {
770 base::AutoLock lock(*list_lock_.Pointer()); 750 base::AutoLock lock(*list_lock_.Pointer());
771 thread_data_list = all_thread_data_list_head_; 751 thread_data_list = all_thread_data_list_head_;
772 all_thread_data_list_head_ = NULL; 752 all_thread_data_list_head_ = NULL;
773 ++incarnation_counter_; 753 ++incarnation_counter_;
774 // To be clean, break apart the retired worker list (though we leak them). 754 // To be clean, break apart the retired worker list (though we leak them).
775 while (first_retired_worker_) { 755 while (first_retired_thread_data_) {
776 ThreadData* worker = first_retired_worker_; 756 ThreadData* thread_data = first_retired_thread_data_;
777 CHECK_GT(worker->worker_thread_number_, 0); 757 first_retired_thread_data_ = thread_data->next_retired_;
778 first_retired_worker_ = worker->next_retired_worker_; 758 thread_data->next_retired_ = nullptr;
779 worker->next_retired_worker_ = NULL;
780 } 759 }
781 } 760 }
782 761
783 // Put most global static back in pristine shape. 762 // Put most global static back in pristine shape.
784 worker_thread_data_creation_count_ = 0;
785 cleanup_count_ = 0; 763 cleanup_count_ = 0;
786 tls_index_.Set(NULL); 764 tls_index_.Set(NULL);
787 // Almost UNINITIALIZED. 765 // Almost UNINITIALIZED.
788 base::subtle::Release_Store(&status_, DORMANT_DURING_TESTS); 766 base::subtle::Release_Store(&status_, DORMANT_DURING_TESTS);
789 767
790 // To avoid any chance of racing in unit tests, which is the only place we 768 // To avoid any chance of racing in unit tests, which is the only place we
791 // call this function, we may sometimes leak all the data structures we 769 // call this function, we may sometimes leak all the data structures we
792 // recovered, as they may still be in use on threads from prior tests! 770 // recovered, as they may still be in use on threads from prior tests!
793 if (leak) { 771 if (leak) {
794 ThreadData* thread_data = thread_data_list; 772 ThreadData* thread_data = thread_data_list;
(...skipping 11 matching lines...) Expand all
806 ThreadData* next_thread_data = thread_data_list; 784 ThreadData* next_thread_data = thread_data_list;
807 thread_data_list = thread_data_list->next(); 785 thread_data_list = thread_data_list->next();
808 786
809 for (BirthMap::iterator it = next_thread_data->birth_map_.begin(); 787 for (BirthMap::iterator it = next_thread_data->birth_map_.begin();
810 next_thread_data->birth_map_.end() != it; ++it) 788 next_thread_data->birth_map_.end() != it; ++it)
811 delete it->second; // Delete the Birth Records. 789 delete it->second; // Delete the Birth Records.
812 delete next_thread_data; // Includes all Death Records. 790 delete next_thread_data; // Includes all Death Records.
813 } 791 }
814 } 792 }
815 793
794 // static
795 ThreadData* ThreadData::GetRetiredOrCreateThreadData(
796 const std::string& sanitized_thread_name) {
797 {
798 base::AutoLock lock(*list_lock_.Pointer());
799 ThreadData** previous_thread_data_next_retired_pointer =
800 &first_retired_thread_data_;
801 ThreadData* current_thread_data = first_retired_thread_data_;
802
803 // Assuming that there aren't more than a few tens of retired ThreadData
Ilya Sherman 2016/11/12 01:21:16 Is it worth DCHECKing the list size?
fdoray 2016/11/14 14:32:07 Done. DCHECKed that it stays under 30.
804 // instances, this lookup should be quick compared to the thread creation
805 // time. Retired ThreadData instances cannot be stored in a map because
806 // insertions are done from OnThreadTerminationCleanup() where allocations
807 // are not allowed.
808 while (current_thread_data) {
809 if (current_thread_data->sanitized_thread_name() ==
810 sanitized_thread_name) {
811 DCHECK_EQ(*previous_thread_data_next_retired_pointer,
812 current_thread_data);
813 *previous_thread_data_next_retired_pointer =
814 current_thread_data->next_retired_;
815 current_thread_data->next_retired_ = nullptr;
816 return current_thread_data;
817 }
818 previous_thread_data_next_retired_pointer =
819 &current_thread_data->next_retired_;
820 current_thread_data = current_thread_data->next_retired_;
821 }
822 }
823 return new ThreadData(sanitized_thread_name);
824 }
825
816 //------------------------------------------------------------------------------ 826 //------------------------------------------------------------------------------
817 TaskStopwatch::TaskStopwatch() 827 TaskStopwatch::TaskStopwatch()
818 : wallclock_duration_ms_(0), 828 : wallclock_duration_ms_(0),
819 current_thread_data_(NULL), 829 current_thread_data_(NULL),
820 excluded_duration_ms_(0), 830 excluded_duration_ms_(0),
821 parent_(NULL) { 831 parent_(NULL) {
822 #if DCHECK_IS_ON() 832 #if DCHECK_IS_ON()
823 state_ = CREATED; 833 state_ = CREATED;
824 child_ = NULL; 834 child_ = NULL;
825 #endif 835 #endif
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 #endif 981 #endif
972 } 982 }
973 983
974 ProcessDataSnapshot::ProcessDataSnapshot(const ProcessDataSnapshot& other) = 984 ProcessDataSnapshot::ProcessDataSnapshot(const ProcessDataSnapshot& other) =
975 default; 985 default;
976 986
977 ProcessDataSnapshot::~ProcessDataSnapshot() { 987 ProcessDataSnapshot::~ProcessDataSnapshot() {
978 } 988 }
979 989
980 } // namespace tracked_objects 990 } // namespace tracked_objects
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698