| OLD | NEW |
| 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 <limits.h> | 7 #include <limits.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 ThreadData* ThreadData::all_thread_data_list_head_ = NULL; | 303 ThreadData* ThreadData::all_thread_data_list_head_ = NULL; |
| 304 | 304 |
| 305 // static | 305 // static |
| 306 ThreadData* ThreadData::first_retired_worker_ = NULL; | 306 ThreadData* ThreadData::first_retired_worker_ = NULL; |
| 307 | 307 |
| 308 // static | 308 // static |
| 309 base::LazyInstance<base::Lock>::Leaky | 309 base::LazyInstance<base::Lock>::Leaky |
| 310 ThreadData::list_lock_ = LAZY_INSTANCE_INITIALIZER; | 310 ThreadData::list_lock_ = LAZY_INSTANCE_INITIALIZER; |
| 311 | 311 |
| 312 // static | 312 // static |
| 313 ThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED; | 313 base::subtle::Atomic32 ThreadData::status_ = ThreadData::UNINITIALIZED; |
| 314 | 314 |
| 315 ThreadData::ThreadData(const std::string& suggested_name) | 315 ThreadData::ThreadData(const std::string& suggested_name) |
| 316 : next_(NULL), | 316 : next_(NULL), |
| 317 next_retired_worker_(NULL), | 317 next_retired_worker_(NULL), |
| 318 worker_thread_number_(0), | 318 worker_thread_number_(0), |
| 319 incarnation_count_for_pool_(-1), | 319 incarnation_count_for_pool_(-1), |
| 320 current_stopwatch_(NULL) { | 320 current_stopwatch_(NULL) { |
| 321 DCHECK_GE(suggested_name.size(), 0u); | 321 DCHECK_GE(suggested_name.size(), 0u); |
| 322 thread_name_ = suggested_name; | 322 thread_name_ = suggested_name; |
| 323 PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. | 323 PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 } | 685 } |
| 686 } | 686 } |
| 687 | 687 |
| 688 static void OptionallyInitializeAlternateTimer() { | 688 static void OptionallyInitializeAlternateTimer() { |
| 689 NowFunction* alternate_time_source = GetAlternateTimeSource(); | 689 NowFunction* alternate_time_source = GetAlternateTimeSource(); |
| 690 if (alternate_time_source) | 690 if (alternate_time_source) |
| 691 ThreadData::SetAlternateTimeSource(alternate_time_source); | 691 ThreadData::SetAlternateTimeSource(alternate_time_source); |
| 692 } | 692 } |
| 693 | 693 |
| 694 void ThreadData::Initialize() { | 694 void ThreadData::Initialize() { |
| 695 if (status_ >= DEACTIVATED) | 695 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 696 return; // Someone else did the initialization. | 696 return; // Someone else did the initialization. |
| 697 // Due to racy lazy initialization in tests, we'll need to recheck status_ | 697 // Due to racy lazy initialization in tests, we'll need to recheck status_ |
| 698 // after we acquire the lock. | 698 // after we acquire the lock. |
| 699 | 699 |
| 700 // Ensure that we don't double initialize tls. We are called when single | 700 // Ensure that we don't double initialize tls. We are called when single |
| 701 // threaded in the product, but some tests may be racy and lazy about our | 701 // threaded in the product, but some tests may be racy and lazy about our |
| 702 // initialization. | 702 // initialization. |
| 703 base::AutoLock lock(*list_lock_.Pointer()); | 703 base::AutoLock lock(*list_lock_.Pointer()); |
| 704 if (status_ >= DEACTIVATED) | 704 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 705 return; // Someone raced in here and beat us. | 705 return; // Someone raced in here and beat us. |
| 706 | 706 |
| 707 // Put an alternate timer in place if the environment calls for it, such as | 707 // Put an alternate timer in place if the environment calls for it, such as |
| 708 // for tracking TCMalloc allocations. This insertion is idempotent, so we | 708 // for tracking TCMalloc allocations. This insertion is idempotent, so we |
| 709 // don't mind if there is a race, and we'd prefer not to be in a lock while | 709 // don't mind if there is a race, and we'd prefer not to be in a lock while |
| 710 // doing this work. | 710 // doing this work. |
| 711 if (kAllowAlternateTimeSourceHandling) | 711 if (kAllowAlternateTimeSourceHandling) |
| 712 OptionallyInitializeAlternateTimer(); | 712 OptionallyInitializeAlternateTimer(); |
| 713 | 713 |
| 714 // Perform the "real" TLS initialization now, and leave it intact through | 714 // Perform the "real" TLS initialization now, and leave it intact through |
| 715 // process termination. | 715 // process termination. |
| 716 if (!tls_index_.initialized()) { // Testing may have initialized this. | 716 if (!tls_index_.initialized()) { // Testing may have initialized this. |
| 717 DCHECK_EQ(status_, UNINITIALIZED); | 717 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); |
| 718 tls_index_.Initialize(&ThreadData::OnThreadTermination); | 718 tls_index_.Initialize(&ThreadData::OnThreadTermination); |
| 719 DCHECK(tls_index_.initialized()); | 719 DCHECK(tls_index_.initialized()); |
| 720 } else { | 720 } else { |
| 721 // TLS was initialzed for us earlier. | 721 // TLS was initialzed for us earlier. |
| 722 DCHECK_EQ(status_, DORMANT_DURING_TESTS); | 722 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); |
| 723 } | 723 } |
| 724 | 724 |
| 725 // Incarnation counter is only significant to testing, as it otherwise will | 725 // Incarnation counter is only significant to testing, as it otherwise will |
| 726 // never again change in this process. | 726 // never again change in this process. |
| 727 ++incarnation_counter_; | 727 ++incarnation_counter_; |
| 728 | 728 |
| 729 // The lock is not critical for setting status_, but it doesn't hurt. It also | 729 // The lock is not critical for setting status_, but it doesn't hurt. It also |
| 730 // ensures that if we have a racy initialization, that we'll bail as soon as | 730 // ensures that if we have a racy initialization, that we'll bail as soon as |
| 731 // we get the lock earlier in this method. | 731 // we get the lock earlier in this method. |
| 732 status_ = kInitialStartupState; | 732 base::subtle::Release_Store(&status_, kInitialStartupState); |
| 733 DCHECK(status_ != UNINITIALIZED); | 733 DCHECK(base::subtle::NoBarrier_Load(&status_) != UNINITIALIZED); |
| 734 } | 734 } |
| 735 | 735 |
| 736 // static | 736 // static |
| 737 void ThreadData::InitializeAndSetTrackingStatus(Status status) { | 737 void ThreadData::InitializeAndSetTrackingStatus(Status status) { |
| 738 DCHECK_GE(status, DEACTIVATED); | 738 DCHECK_GE(status, DEACTIVATED); |
| 739 DCHECK_LE(status, PROFILING_ACTIVE); | 739 DCHECK_LE(status, PROFILING_ACTIVE); |
| 740 | 740 |
| 741 Initialize(); // No-op if already initialized. | 741 Initialize(); // No-op if already initialized. |
| 742 | 742 |
| 743 if (status > DEACTIVATED) | 743 if (status > DEACTIVATED) |
| 744 status = PROFILING_ACTIVE; | 744 status = PROFILING_ACTIVE; |
| 745 status_ = status; | 745 base::subtle::Release_Store(&status_, status); |
| 746 } | 746 } |
| 747 | 747 |
| 748 // static | 748 // static |
| 749 ThreadData::Status ThreadData::status() { | 749 ThreadData::Status ThreadData::status() { |
| 750 return status_; | 750 return static_cast<ThreadData::Status>(base::subtle::Acquire_Load(&status_)); |
| 751 } | 751 } |
| 752 | 752 |
| 753 // static | 753 // static |
| 754 bool ThreadData::TrackingStatus() { | 754 bool ThreadData::TrackingStatus() { |
| 755 return status_ > DEACTIVATED; | 755 return base::subtle::Acquire_Load(&status_) > DEACTIVATED; |
| 756 } | 756 } |
| 757 | 757 |
| 758 // static | 758 // static |
| 759 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { | 759 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { |
| 760 DCHECK(now_function); | 760 DCHECK(now_function); |
| 761 if (kAllowAlternateTimeSourceHandling) | 761 if (kAllowAlternateTimeSourceHandling) |
| 762 now_function_ = now_function; | 762 now_function_ = now_function; |
| 763 } | 763 } |
| 764 | 764 |
| 765 // static | 765 // static |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 810 CHECK_GT(worker->worker_thread_number_, 0); | 810 CHECK_GT(worker->worker_thread_number_, 0); |
| 811 first_retired_worker_ = worker->next_retired_worker_; | 811 first_retired_worker_ = worker->next_retired_worker_; |
| 812 worker->next_retired_worker_ = NULL; | 812 worker->next_retired_worker_ = NULL; |
| 813 } | 813 } |
| 814 } | 814 } |
| 815 | 815 |
| 816 // Put most global static back in pristine shape. | 816 // Put most global static back in pristine shape. |
| 817 worker_thread_data_creation_count_ = 0; | 817 worker_thread_data_creation_count_ = 0; |
| 818 cleanup_count_ = 0; | 818 cleanup_count_ = 0; |
| 819 tls_index_.Set(NULL); | 819 tls_index_.Set(NULL); |
| 820 status_ = DORMANT_DURING_TESTS; // Almost UNINITIALIZED. | 820 // Almost UNINITIALIZED. |
| 821 base::subtle::Release_Store(&status_, DORMANT_DURING_TESTS); |
| 821 | 822 |
| 822 // To avoid any chance of racing in unit tests, which is the only place we | 823 // To avoid any chance of racing in unit tests, which is the only place we |
| 823 // call this function, we may sometimes leak all the data structures we | 824 // call this function, we may sometimes leak all the data structures we |
| 824 // recovered, as they may still be in use on threads from prior tests! | 825 // recovered, as they may still be in use on threads from prior tests! |
| 825 if (leak) { | 826 if (leak) { |
| 826 ThreadData* thread_data = thread_data_list; | 827 ThreadData* thread_data = thread_data_list; |
| 827 while (thread_data) { | 828 while (thread_data) { |
| 828 ANNOTATE_LEAKING_OBJECT_PTR(thread_data); | 829 ANNOTATE_LEAKING_OBJECT_PTR(thread_data); |
| 829 thread_data = thread_data->next(); | 830 thread_data = thread_data->next(); |
| 830 } | 831 } |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 : process_id(base::GetCurrentProcId()) { | 999 : process_id(base::GetCurrentProcId()) { |
| 999 #else | 1000 #else |
| 1000 : process_id(base::kNullProcessId) { | 1001 : process_id(base::kNullProcessId) { |
| 1001 #endif | 1002 #endif |
| 1002 } | 1003 } |
| 1003 | 1004 |
| 1004 ProcessDataSnapshot::~ProcessDataSnapshot() { | 1005 ProcessDataSnapshot::~ProcessDataSnapshot() { |
| 1005 } | 1006 } |
| 1006 | 1007 |
| 1007 } // namespace tracked_objects | 1008 } // namespace tracked_objects |
| OLD | NEW |