| 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 #ifndef BASE_TRACKED_OBJECTS_H_ | 5 #ifndef BASE_TRACKED_OBJECTS_H_ |
| 6 #define BASE_TRACKED_OBJECTS_H_ | 6 #define BASE_TRACKED_OBJECTS_H_ |
| 7 | 7 |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 // | 55 // |
| 56 // First off, when the instance is created, the FROM_HERE macro is expanded | 56 // First off, when the instance is created, the FROM_HERE macro is expanded |
| 57 // to specify the birth place (file, line, function) where the instance was | 57 // to specify the birth place (file, line, function) where the instance was |
| 58 // created. That data is used to create a transient Location instance | 58 // created. That data is used to create a transient Location instance |
| 59 // encapsulating the above triple of information. The strings (like __FILE__) | 59 // encapsulating the above triple of information. The strings (like __FILE__) |
| 60 // are passed around by reference, with the assumption that they are static, and | 60 // are passed around by reference, with the assumption that they are static, and |
| 61 // will never go away. This ensures that the strings can be dealt with as atoms | 61 // will never go away. This ensures that the strings can be dealt with as atoms |
| 62 // with great efficiency (i.e., copying of strings is never needed, and | 62 // with great efficiency (i.e., copying of strings is never needed, and |
| 63 // comparisons for equality can be based on pointer comparisons). | 63 // comparisons for equality can be based on pointer comparisons). |
| 64 // | 64 // |
| 65 // Next, a Births instance is created for use ONLY on the thread where this | 65 // Next, a Births instance is constructed or found. A Births instance records |
| 66 // instance was created. That Births instance records (in a base class | 66 // (in a base class BirthOnThread) references to the static data provided in a |
| 67 // BirthOnThread) references to the static data provided in a Location instance, | 67 // Location instance, as well as a pointer to the ThreadData bound to the thread |
| 68 // as well as a pointer specifying the thread on which the birth takes place. | 68 // on which the birth takes place (see discussion on ThreadData below). There is |
| 69 // Hence there is at most one Births instance for each Location on each thread. | 69 // at most one Births instance for each Location / ThreadData pair. The derived |
| 70 // The derived Births class contains slots for recording statistics about all | 70 // Births class contains slots for recording statistics about all instances born |
| 71 // instances born at the same location. Statistics currently include only the | 71 // at the same location. Statistics currently include only the count of |
| 72 // count of instances constructed. | 72 // instances constructed. |
| 73 // | 73 // |
| 74 // Since the base class BirthOnThread contains only constant data, it can be | 74 // Since the base class BirthOnThread contains only constant data, it can be |
| 75 // freely accessed by any thread at any time (i.e., only the statistic needs to | 75 // freely accessed by any thread at any time. The statistics must be handled |
| 76 // be handled carefully, and stats are updated exclusively on the birth thread). | 76 // more carefully; they are updated exclusively by the single thread to which |
| 77 // the ThreadData is bound at a given time. |
| 77 // | 78 // |
| 78 // For Tasks, having now either constructed or found the Births instance | 79 // For Tasks, having now either constructed or found the Births instance |
| 79 // described above, a pointer to the Births instance is then recorded into the | 80 // described above, a pointer to the Births instance is then recorded into the |
| 80 // PendingTask structure in MessageLoop. This fact alone is very useful in | 81 // PendingTask structure. This fact alone is very useful in debugging, when |
| 81 // debugging, when there is a question of where an instance came from. In | 82 // there is a question of where an instance came from. In addition, the birth |
| 82 // addition, the birth time is also recorded and used to later evaluate the | 83 // time is also recorded and used to later evaluate the lifetime duration of the |
| 83 // lifetime duration of the whole Task. As a result of the above embedding, we | 84 // whole Task. As a result of the above embedding, we can find out a Task's |
| 84 // can find out a Task's location of birth, and thread of birth, without using | 85 // location of birth, and name of birth thread, without using any locks, as all |
| 85 // any locks, as all that data is constant across the life of the process. | 86 // that data is constant across the life of the process. |
| 86 // | 87 // |
| 87 // The above work *could* also be done for any other object as well by calling | 88 // The above work *could* also be done for any other object as well by calling |
| 88 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. | 89 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. |
| 89 // | 90 // |
| 90 // The amount of memory used in the above data structures depends on how many | 91 // The upper bound for the amount of memory used in the above data structures is |
| 91 // threads there are, and how many Locations of construction there are. | 92 // the product of the number of ThreadData instances and the number of |
| 92 // Fortunately, we don't use memory that is the product of those two counts, but | 93 // Locations. Fortunately, Locations are often created on a single thread and |
| 93 // rather we only need one Births instance for each thread that constructs an | 94 // the memory utilization is actually fairly restrained. |
| 94 // instance at a Location. In many cases, instances are only created on one | |
| 95 // thread, so the memory utilization is actually fairly restrained. | |
| 96 // | 95 // |
| 97 // Lastly, when an instance is deleted, the final tallies of statistics are | 96 // Lastly, when an instance is deleted, the final tallies of statistics are |
| 98 // carefully accumulated. That tallying writes into slots (members) in a | 97 // carefully accumulated. That tallying writes into slots (members) in a |
| 99 // collection of DeathData instances. For each birth place Location that is | 98 // collection of DeathData instances. For each Births / death ThreadData pair, |
| 100 // destroyed on a thread, there is a DeathData instance to record the additional | 99 // there is a DeathData instance to record the additional death count, as well |
| 101 // death count, as well as accumulate the run-time and queue-time durations for | 100 // as to accumulate the run-time and queue-time durations for the instance as it |
| 102 // the instance as it is destroyed (dies). By maintaining a single place to | 101 // is destroyed (dies). Since a ThreadData is bound to at most one thread at a |
| 103 // aggregate this running sum *only* for the given thread, we avoid the need to | 102 // time, there is no need to lock such DeathData instances. (i.e., these |
| 104 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData | 103 // accumulated stats in a DeathData instance are exclusively updated by the |
| 105 // instance are exclusively updated by the singular owning thread). | 104 // singular owning thread). |
| 106 // | 105 // |
| 107 // With the above life cycle description complete, the major remaining detail | 106 // With the above life cycle description complete, the major remaining detail is |
| 108 // is explaining how each thread maintains a list of DeathData instances, and | 107 // explaining how existing Births and DeathData instances are found to avoid |
| 109 // of Births instances, and is able to avoid additional (redundant/unnecessary) | 108 // redundant allocations. |
| 110 // allocations. | |
| 111 // | 109 // |
| 112 // Each thread maintains a list of data items specific to that thread in a | 110 // A ThreadData instance maintains maps of Births and DeathData instances. The |
| 113 // ThreadData instance (for that specific thread only). The two critical items | 111 // Births map is indexed by Location and the DeathData map is indexed by |
| 114 // are lists of DeathData and Births instances. These lists are maintained in | 112 // Births*. As noted earlier, we can compare Locations very efficiently as we |
| 115 // STL maps, which are indexed by Location. As noted earlier, we can compare | 113 // consider the underlying data (file, function, line) to be atoms, and hence |
| 116 // locations very efficiently as we consider the underlying data (file, | 114 // pointer comparison is used rather than (slow) string comparisons. |
| 117 // function, line) to be atoms, and hence pointer comparison is used rather than | |
| 118 // (slow) string comparisons. | |
| 119 // | 115 // |
| 120 // To provide a mechanism for iterating over all "known threads," which means | 116 // The first time that a thread calls ThreadData::InitializeThreadContext() or |
| 121 // threads that have recorded a birth or a death, we create a singly linked list | 117 // ThreadData::Get(), a ThreadData instance is bound to it and stored in TLS. If |
| 122 // of ThreadData instances. Each such instance maintains a pointer to the next | 118 // a ThreadData bound to a terminated thread with the same sanitized name (i.e. |
| 123 // one. A static member of ThreadData provides a pointer to the first item on | 119 // name without trailing digits) as the current thread is available, it is |
| 124 // this global list, and access via that all_thread_data_list_head_ item | 120 // reused. Otherwise, a new ThreadData instance is instantiated. Since a |
| 125 // requires the use of the list_lock_. | 121 // ThreadData is bound to at most one thread at a time, there is no need to |
| 126 // When new ThreadData instances is added to the global list, it is pre-pended, | 122 // acquire a lock to access its maps. Over time, a ThreadData may be bound to |
| 127 // which ensures that any prior acquisition of the list is valid (i.e., the | 123 // different threads that share the same sanitized name. |
| 128 // holder can iterate over it without fear of it changing, or the necessity of | 124 // |
| 129 // using an additional lock. Iterations are actually pretty rare (used | 125 // We maintain a list of all ThreadData instances for the current process. Each |
| 126 // ThreadData instance has a pointer to the next one. A static member of |
| 127 // ThreadData provides a pointer to the first item on this global list, and |
| 128 // access via that all_thread_data_list_head_ item requires the use of the |
| 129 // list_lock_. |
| 130 // |
| 131 // When new ThreadData instances are added to the global list, they are pre- |
| 132 // pended, which ensures that any prior acquisition of the list is valid (i.e., |
| 133 // the holder can iterate over it without fear of it changing, or the necessity |
| 134 // of using an additional lock. Iterations are actually pretty rare (used |
| 130 // primarily for cleanup, or snapshotting data for display), so this lock has | 135 // primarily for cleanup, or snapshotting data for display), so this lock has |
| 131 // very little global performance impact. | 136 // very little global performance impact. |
| 132 // | 137 // |
| 133 // The above description tries to define the high performance (run time) | 138 // The above description tries to define the high performance (run time) |
| 134 // portions of these classes. After gathering statistics, calls instigated | 139 // portions of these classes. After gathering statistics, calls instigated |
| 135 // by visiting about:profiler will assemble and aggregate data for display. The | 140 // by visiting about:profiler will assemble and aggregate data for display. The |
| 136 // following data structures are used for producing such displays. They are | 141 // following data structures are used for producing such displays. They are |
| 137 // not performance critical, and their only major constraint is that they should | 142 // not performance critical, and their only major constraint is that they should |
| 138 // be able to run concurrently with ongoing augmentation of the birth and death | 143 // be able to run concurrently with ongoing augmentation of the birth and death |
| 139 // data. | 144 // data. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 166 // atomically collecting all data, so we could have count that does not, for | 171 // atomically collecting all data, so we could have count that does not, for |
| 167 // example, match with the number of durations we accumulated). The advantage | 172 // example, match with the number of durations we accumulated). The advantage |
| 168 // to having fast (non-atomic) updates of the data outweighs the minimal risk of | 173 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 169 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, | 174 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 170 // not the underlying and ongoing statistic). In contrast, pointer data that | 175 // not the underlying and ongoing statistic). In contrast, pointer data that |
| 171 // is accessed during snapshotting is completely invariant, and hence is | 176 // is accessed during snapshotting is completely invariant, and hence is |
| 172 // perfectly acquired (i.e., no potential corruption, and no risk of a bad | 177 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| 173 // memory reference). | 178 // memory reference). |
| 174 // | 179 // |
| 175 // TODO(jar): We can implement a Snapshot system that *tries* to grab the | 180 // TODO(jar): We can implement a Snapshot system that *tries* to grab the |
| 176 // snapshots on the source threads *when* they have MessageLoops available | 181 // snapshots on the source threads *when* they have SingleThreadTaskRunners |
| 177 // (worker threads don't have message loops generally, and hence gathering from | 182 // available (worker threads don't have SingleThreadTaskRunners, and hence |
| 178 // them will continue to be asynchronous). We had an implementation of this in | 183 // gathering from them will continue to be asynchronous). We had an |
| 179 // the past, but the difficulty is dealing with message loops being terminated. | 184 // implementation of this in the past, but the difficulty is dealing with |
| 180 // We can *try* to spam the available threads via some task runner to | 185 // threads being terminated. We can *try* to post a task to threads that have a |
| 181 // achieve this feat, and it *might* be valuable when we are collecting data | 186 // SingleThreadTaskRunner and check if that succeeds (will fail if the thread |
| 187 // has been terminated). This *might* be valuable when we are collecting data |
| 182 // for upload via UMA (where correctness of data may be more significant than | 188 // for upload via UMA (where correctness of data may be more significant than |
| 183 // for a single screen of about:profiler). | 189 // for a single screen of about:profiler). |
| 184 // | 190 // |
| 185 // TODO(jar): We need to store DataCollections, and provide facilities for | 191 // TODO(jar): We need to store DataCollections, and provide facilities for |
| 186 // taking the difference between two gathered DataCollections. For now, we're | 192 // taking the difference between two gathered DataCollections. For now, we're |
| 187 // just adding a hack that Reset()s to zero all counts and stats. This is also | 193 // just adding a hack that Reset()s to zero all counts and stats. This is also |
| 188 // done in a slightly thread-unsafe fashion, as the resetting is done | 194 // done in a slightly thread-unsafe fashion, as the resetting is done |
| 189 // asynchronously relative to ongoing updates (but all data is 32 bit in size). | 195 // asynchronously relative to ongoing updates (but all data is 32 bit in size). |
| 190 // For basic profiling, this will work "most of the time," and should be | 196 // For basic profiling, this will work "most of the time," and should be |
| 191 // sufficient... but storing away DataCollections is the "right way" to do this. | 197 // sufficient... but storing away DataCollections is the "right way" to do this. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 222 | 228 |
| 223 //------------------------------------------------------------------------------ | 229 //------------------------------------------------------------------------------ |
| 224 // A "snapshotted" representation of the BirthOnThread class. | 230 // A "snapshotted" representation of the BirthOnThread class. |
| 225 | 231 |
| 226 struct BASE_EXPORT BirthOnThreadSnapshot { | 232 struct BASE_EXPORT BirthOnThreadSnapshot { |
| 227 BirthOnThreadSnapshot(); | 233 BirthOnThreadSnapshot(); |
| 228 explicit BirthOnThreadSnapshot(const BirthOnThread& birth); | 234 explicit BirthOnThreadSnapshot(const BirthOnThread& birth); |
| 229 ~BirthOnThreadSnapshot(); | 235 ~BirthOnThreadSnapshot(); |
| 230 | 236 |
| 231 LocationSnapshot location; | 237 LocationSnapshot location; |
| 232 std::string thread_name; | 238 std::string sanitized_thread_name; |
| 233 }; | 239 }; |
| 234 | 240 |
| 235 //------------------------------------------------------------------------------ | 241 //------------------------------------------------------------------------------ |
| 236 // A class for accumulating counts of births (without bothering with a map<>). | 242 // A class for accumulating counts of births (without bothering with a map<>). |
| 237 | 243 |
| 238 class BASE_EXPORT Births: public BirthOnThread { | 244 class BASE_EXPORT Births: public BirthOnThread { |
| 239 public: | 245 public: |
| 240 Births(const Location& location, const ThreadData& current); | 246 Births(const Location& location, const ThreadData& current); |
| 241 | 247 |
| 242 int birth_count() const; | 248 int birth_count() const; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 // A temporary collection of data that can be sorted and summarized. It is | 477 // A temporary collection of data that can be sorted and summarized. It is |
| 472 // gathered (carefully) from many threads. Instances are held in arrays and | 478 // gathered (carefully) from many threads. Instances are held in arrays and |
| 473 // processed, filtered, and rendered. | 479 // processed, filtered, and rendered. |
| 474 // The source of this data was collected on many threads, and is asynchronously | 480 // The source of this data was collected on many threads, and is asynchronously |
| 475 // changing. The data in this instance is not asynchronously changing. | 481 // changing. The data in this instance is not asynchronously changing. |
| 476 | 482 |
| 477 struct BASE_EXPORT TaskSnapshot { | 483 struct BASE_EXPORT TaskSnapshot { |
| 478 TaskSnapshot(); | 484 TaskSnapshot(); |
| 479 TaskSnapshot(const BirthOnThreadSnapshot& birth, | 485 TaskSnapshot(const BirthOnThreadSnapshot& birth, |
| 480 const DeathDataSnapshot& death_data, | 486 const DeathDataSnapshot& death_data, |
| 481 const std::string& death_thread_name); | 487 const std::string& death_sanitized_thread_name); |
| 482 ~TaskSnapshot(); | 488 ~TaskSnapshot(); |
| 483 | 489 |
| 484 BirthOnThreadSnapshot birth; | 490 BirthOnThreadSnapshot birth; |
| 485 // Delta between death data for a thread for a certain profiling phase and the | 491 // Delta between death data for a thread for a certain profiling phase and the |
| 486 // snapshot for the pervious phase, if any. Otherwise, just a snapshot. | 492 // snapshot for the pervious phase, if any. Otherwise, just a snapshot. |
| 487 DeathDataSnapshot death_data; | 493 DeathDataSnapshot death_data; |
| 488 std::string death_thread_name; | 494 std::string death_sanitized_thread_name; |
| 489 }; | 495 }; |
| 490 | 496 |
| 491 //------------------------------------------------------------------------------ | 497 //------------------------------------------------------------------------------ |
| 492 // For each thread, we have a ThreadData that stores all tracking info generated | 498 // For each thread, we have a ThreadData that stores all tracking info generated |
| 493 // on this thread. This prevents the need for locking as data accumulates. | 499 // on this thread. This prevents the need for locking as data accumulates. |
| 494 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. | 500 // We use ThreadLocalStorage to quickly identfy the current ThreadData context. |
| 495 // We also have a linked list of ThreadData instances, and that list is used to | 501 // We also have a linked list of ThreadData instances, and that list is used to |
| 496 // harvest data from all existing instances. | 502 // harvest data from all existing instances. |
| 497 | 503 |
| 498 struct ProcessDataPhaseSnapshot; | 504 struct ProcessDataPhaseSnapshot; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 514 DEACTIVATED, // No longer recording profiling. | 520 DEACTIVATED, // No longer recording profiling. |
| 515 PROFILING_ACTIVE, // Recording profiles. | 521 PROFILING_ACTIVE, // Recording profiles. |
| 516 STATUS_LAST = PROFILING_ACTIVE | 522 STATUS_LAST = PROFILING_ACTIVE |
| 517 }; | 523 }; |
| 518 | 524 |
| 519 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; | 525 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; |
| 520 typedef std::map<const Births*, DeathData> DeathMap; | 526 typedef std::map<const Births*, DeathData> DeathMap; |
| 521 | 527 |
| 522 // Initialize the current thread context with a new instance of ThreadData. | 528 // Initialize the current thread context with a new instance of ThreadData. |
| 523 // This is used by all threads that have names, and should be explicitly | 529 // This is used by all threads that have names, and should be explicitly |
| 524 // set *before* any births on the threads have taken place. It is generally | 530 // set *before* any births on the threads have taken place. |
| 525 // only used by the message loop, which has a well defined thread name. | 531 static void InitializeThreadContext(const std::string& thread_name); |
| 526 static void InitializeThreadContext(const std::string& suggested_name); | |
| 527 | 532 |
| 528 // Using Thread Local Store, find the current instance for collecting data. | 533 // Using Thread Local Store, find the current instance for collecting data. |
| 529 // If an instance does not exist, construct one (and remember it for use on | 534 // If an instance does not exist, construct one (and remember it for use on |
| 530 // this thread. | 535 // this thread. |
| 531 // This may return NULL if the system is disabled for any reason. | 536 // This may return NULL if the system is disabled for any reason. |
| 532 static ThreadData* Get(); | 537 static ThreadData* Get(); |
| 533 | 538 |
| 534 // Fills |process_data_snapshot| with phased snapshots of all profiling | 539 // Fills |process_data_snapshot| with phased snapshots of all profiling |
| 535 // phases, including the current one, identified by |current_profiling_phase|. | 540 // phases, including the current one, identified by |current_profiling_phase|. |
| 536 // |current_profiling_phase| is necessary because a child process can start | 541 // |current_profiling_phase| is necessary because a child process can start |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 // finished). | 579 // finished). |
| 575 static void TallyRunOnWorkerThreadIfTracking(const Births* births, | 580 static void TallyRunOnWorkerThreadIfTracking(const Births* births, |
| 576 const TrackedTime& time_posted, | 581 const TrackedTime& time_posted, |
| 577 const TaskStopwatch& stopwatch); | 582 const TaskStopwatch& stopwatch); |
| 578 | 583 |
| 579 // Record the end of execution in region, generally corresponding to a scope | 584 // Record the end of execution in region, generally corresponding to a scope |
| 580 // being exited. | 585 // being exited. |
| 581 static void TallyRunInAScopedRegionIfTracking(const Births* births, | 586 static void TallyRunInAScopedRegionIfTracking(const Births* births, |
| 582 const TaskStopwatch& stopwatch); | 587 const TaskStopwatch& stopwatch); |
| 583 | 588 |
| 584 const std::string& thread_name() const { return thread_name_; } | 589 const std::string& sanitized_thread_name() const { |
| 590 return sanitized_thread_name_; |
| 591 } |
| 585 | 592 |
| 586 // Initializes all statics if needed (this initialization call should be made | 593 // Initializes all statics if needed (this initialization call should be made |
| 587 // while we are single threaded). | 594 // while we are single threaded). |
| 588 static void EnsureTlsInitialization(); | 595 static void EnsureTlsInitialization(); |
| 589 | 596 |
| 590 // Sets internal status_. | 597 // Sets internal status_. |
| 591 // If |status| is false, then status_ is set to DEACTIVATED. | 598 // If |status| is false, then status_ is set to DEACTIVATED. |
| 592 // If |status| is true, then status_ is set to PROFILING_ACTIVE. | 599 // If |status| is true, then status_ is set to PROFILING_ACTIVE. |
| 593 static void InitializeAndSetTrackingStatus(Status status); | 600 static void InitializeAndSetTrackingStatus(Status status); |
| 594 | 601 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 623 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 630 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
| 624 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 631 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
| 625 | 632 |
| 626 // Type for an alternate timer function (testing only). | 633 // Type for an alternate timer function (testing only). |
| 627 typedef unsigned int NowFunction(); | 634 typedef unsigned int NowFunction(); |
| 628 | 635 |
| 629 typedef std::map<const BirthOnThread*, int> BirthCountMap; | 636 typedef std::map<const BirthOnThread*, int> BirthCountMap; |
| 630 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> | 637 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> |
| 631 DeathsSnapshot; | 638 DeathsSnapshot; |
| 632 | 639 |
| 633 // Worker thread construction creates a name since there is none. | 640 explicit ThreadData(const std::string& sanitized_thread_name); |
| 634 explicit ThreadData(int thread_number); | |
| 635 | |
| 636 // Message loop based construction should provide a name. | |
| 637 explicit ThreadData(const std::string& suggested_name); | |
| 638 | |
| 639 ~ThreadData(); | 641 ~ThreadData(); |
| 640 | 642 |
| 641 // Push this instance to the head of all_thread_data_list_head_, linking it to | 643 // Push this instance to the head of all_thread_data_list_head_, linking it to |
| 642 // the previous head. This is performed after each construction, and leaves | 644 // the previous head. This is performed after each construction, and leaves |
| 643 // the instance permanently on that list. | 645 // the instance permanently on that list. |
| 644 void PushToHeadOfList(); | 646 void PushToHeadOfList(); |
| 645 | 647 |
| 646 // (Thread safe) Get start of list of all ThreadData instances using the lock. | 648 // (Thread safe) Get start of list of all ThreadData instances using the lock. |
| 647 static ThreadData* first(); | 649 static ThreadData* first(); |
| 648 | 650 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 // uninitialized) state. If there is any chance that other threads are still | 694 // uninitialized) state. If there is any chance that other threads are still |
| 693 // using the data structures, then the |leak| argument should be passed in as | 695 // using the data structures, then the |leak| argument should be passed in as |
| 694 // true, and the data structures (birth maps, death maps, ThreadData | 696 // true, and the data structures (birth maps, death maps, ThreadData |
| 695 // insntances, etc.) will be leaked and not deleted. If you have joined all | 697 // insntances, etc.) will be leaked and not deleted. If you have joined all |
| 696 // threads since the time that InitializeAndSetTrackingStatus() was called, | 698 // threads since the time that InitializeAndSetTrackingStatus() was called, |
| 697 // then you can pass in a |leak| value of false, and this function will | 699 // then you can pass in a |leak| value of false, and this function will |
| 698 // delete recursively all data structures, starting with the list of | 700 // delete recursively all data structures, starting with the list of |
| 699 // ThreadData instances. | 701 // ThreadData instances. |
| 700 static void ShutdownSingleThreadedCleanup(bool leak); | 702 static void ShutdownSingleThreadedCleanup(bool leak); |
| 701 | 703 |
| 704 // Returns a ThreadData instance for a thread whose sanitized name is |
| 705 // |sanitized_thread_name|. The returned instance may have been extracted from |
| 706 // the list of retired ThreadData instances or newly allocated. |
| 707 static ThreadData* GetRetiredOrCreateThreadData( |
| 708 const std::string& sanitized_thread_name); |
| 709 |
| 702 // When non-null, this specifies an external function that supplies monotone | 710 // When non-null, this specifies an external function that supplies monotone |
| 703 // increasing time functcion. | 711 // increasing time functcion. |
| 704 static NowFunction* now_function_for_testing_; | 712 static NowFunction* now_function_for_testing_; |
| 705 | 713 |
| 706 // We use thread local store to identify which ThreadData to interact with. | 714 // We use thread local store to identify which ThreadData to interact with. |
| 707 static base::ThreadLocalStorage::StaticSlot tls_index_; | 715 static base::ThreadLocalStorage::StaticSlot tls_index_; |
| 708 | 716 |
| 709 // List of ThreadData instances for use with worker threads. When a worker | 717 // Linked list of ThreadData instances that were associated with threads that |
| 710 // thread is done (terminated), we push it onto this list. When a new worker | 718 // have been terminated and that have not been associated with a new thread |
| 711 // thread is created, we first try to re-use a ThreadData instance from the | 719 // since then. This is only accessed while |list_lock_| is held. |
| 712 // list, and if none are available, construct a new one. | 720 static ThreadData* first_retired_thread_data_; |
| 713 // This is only accessed while list_lock_ is held. | |
| 714 static ThreadData* first_retired_worker_; | |
| 715 | 721 |
| 716 // Link to the most recently created instance (starts a null terminated list). | 722 // Link to the most recently created instance (starts a null terminated list). |
| 717 // The list is traversed by about:profiler when it needs to snapshot data. | 723 // The list is traversed by about:profiler when it needs to snapshot data. |
| 718 // This is only accessed while list_lock_ is held. | 724 // This is only accessed while list_lock_ is held. |
| 719 static ThreadData* all_thread_data_list_head_; | 725 static ThreadData* all_thread_data_list_head_; |
| 720 | 726 |
| 721 // The next available worker thread number. This should only be accessed when | |
| 722 // the list_lock_ is held. | |
| 723 static int worker_thread_data_creation_count_; | |
| 724 | |
| 725 // The number of times TLS has called us back to cleanup a ThreadData | 727 // The number of times TLS has called us back to cleanup a ThreadData |
| 726 // instance. This is only accessed while list_lock_ is held. | 728 // instance. This is only accessed while list_lock_ is held. |
| 727 static int cleanup_count_; | 729 static int cleanup_count_; |
| 728 | 730 |
| 729 // Incarnation sequence number, indicating how many times (during unittests) | 731 // Incarnation sequence number, indicating how many times (during unittests) |
| 730 // we've either transitioned out of UNINITIALIZED, or into that state. This | 732 // we've either transitioned out of UNINITIALIZED, or into that state. This |
| 731 // value is only accessed while the list_lock_ is held. | 733 // value is only accessed while the list_lock_ is held. |
| 732 static int incarnation_counter_; | 734 static int incarnation_counter_; |
| 733 | 735 |
| 734 // Protection for access to all_thread_data_list_head_, and to | 736 // Protection for access to all_thread_data_list_head_, and to |
| 735 // unregistered_thread_data_pool_. This lock is leaked at shutdown. | 737 // unregistered_thread_data_pool_. This lock is leaked at shutdown. |
| 736 // The lock is very infrequently used, so we can afford to just make a lazy | 738 // The lock is very infrequently used, so we can afford to just make a lazy |
| 737 // instance and be safe. | 739 // instance and be safe. |
| 738 static base::LazyInstance<base::Lock>::Leaky list_lock_; | 740 static base::LazyInstance<base::Lock>::Leaky list_lock_; |
| 739 | 741 |
| 740 // We set status_ to SHUTDOWN when we shut down the tracking service. | 742 // We set status_ to SHUTDOWN when we shut down the tracking service. |
| 741 static base::subtle::Atomic32 status_; | 743 static base::subtle::Atomic32 status_; |
| 742 | 744 |
| 743 // Link to next instance (null terminated list). Used to globally track all | 745 // Link to next instance (null terminated list). Used to globally track all |
| 744 // registered instances (corresponds to all registered threads where we keep | 746 // registered instances (corresponds to all registered threads where we keep |
| 745 // data). | 747 // data). Only modified in the constructor. |
| 746 ThreadData* next_; | 748 ThreadData* next_; |
| 747 | 749 |
| 748 // Pointer to another ThreadData instance for a Worker-Thread that has been | 750 // Pointer to another retired ThreadData instance. This value is nullptr if |
| 749 // retired (its thread was terminated). This value is non-NULL only for a | 751 // this is associated with an active thread. |
| 750 // retired ThreadData associated with a Worker-Thread. | 752 ThreadData* next_retired_thread_data_; |
| 751 ThreadData* next_retired_worker_; | |
| 752 | 753 |
| 753 // The name of the thread that is being recorded. If this thread has no | 754 // The name of the thread that is being recorded, with all trailing digits |
| 754 // message_loop, then this is a worker thread, with a sequence number postfix. | 755 // replaced with a single "*" character. |
| 755 std::string thread_name_; | 756 const std::string sanitized_thread_name_; |
| 756 | |
| 757 // Indicate if this is a worker thread, and the ThreadData contexts should be | |
| 758 // stored in the unregistered_thread_data_pool_ when not in use. | |
| 759 // Value is zero when it is not a worker thread. Value is a positive integer | |
| 760 // corresponding to the created thread name if it is a worker thread. | |
| 761 int worker_thread_number_; | |
| 762 | 757 |
| 763 // A map used on each thread to keep track of Births on this thread. | 758 // A map used on each thread to keep track of Births on this thread. |
| 764 // This map should only be accessed on the thread it was constructed on. | 759 // This map should only be accessed on the thread it was constructed on. |
| 765 // When a snapshot is needed, this structure can be locked in place for the | 760 // When a snapshot is needed, this structure can be locked in place for the |
| 766 // duration of the snapshotting activity. | 761 // duration of the snapshotting activity. |
| 767 BirthMap birth_map_; | 762 BirthMap birth_map_; |
| 768 | 763 |
| 769 // Similar to birth_map_, this records informations about death of tracked | 764 // Similar to birth_map_, this records informations about death of tracked |
| 770 // instances (i.e., when a tracked instance was destroyed on this thread). | 765 // instances (i.e., when a tracked instance was destroyed on this thread). |
| 771 // It is locked before changing, and hence other threads may access it by | 766 // It is locked before changing, and hence other threads may access it by |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 ProcessDataSnapshot(const ProcessDataSnapshot& other); | 889 ProcessDataSnapshot(const ProcessDataSnapshot& other); |
| 895 ~ProcessDataSnapshot(); | 890 ~ProcessDataSnapshot(); |
| 896 | 891 |
| 897 PhasedProcessDataSnapshotMap phased_snapshots; | 892 PhasedProcessDataSnapshotMap phased_snapshots; |
| 898 base::ProcessId process_id; | 893 base::ProcessId process_id; |
| 899 }; | 894 }; |
| 900 | 895 |
| 901 } // namespace tracked_objects | 896 } // namespace tracked_objects |
| 902 | 897 |
| 903 #endif // BASE_TRACKED_OBJECTS_H_ | 898 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |