Chromium Code Reviews| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 // | 52 // |
| 53 // First off, when the instance is created, the FROM_HERE macro is expanded | 53 // First off, when the instance is created, the FROM_HERE macro is expanded |
| 54 // to specify the birth place (file, line, function) where the instance was | 54 // to specify the birth place (file, line, function) where the instance was |
| 55 // created. That data is used to create a transient Location instance | 55 // created. That data is used to create a transient Location instance |
| 56 // encapsulating the above triple of information. The strings (like __FILE__) | 56 // encapsulating the above triple of information. The strings (like __FILE__) |
| 57 // are passed around by reference, with the assumption that they are static, and | 57 // are passed around by reference, with the assumption that they are static, and |
| 58 // will never go away. This ensures that the strings can be dealt with as atoms | 58 // will never go away. This ensures that the strings can be dealt with as atoms |
| 59 // with great efficiency (i.e., copying of strings is never needed, and | 59 // with great efficiency (i.e., copying of strings is never needed, and |
| 60 // comparisons for equality can be based on pointer comparisons). | 60 // comparisons for equality can be based on pointer comparisons). |
| 61 // | 61 // |
| 62 // Next, a Births instance is created for use ONLY on the thread where this | 62 // Next, a Births instance is constructed or found. A Births instance records |
| 63 // instance was created. That Births instance records (in a base class | 63 // (in a base class BirthOnThread) references to the static data provided in a |
| 64 // BirthOnThread) references to the static data provided in a Location instance, | 64 // Location instance, as well as a pointer to the ThreadData bound to the thread |
| 65 // as well as a pointer specifying the thread on which the birth takes place. | 65 // on which the birth takes place (see discussion on ThreadData below). There is |
| 66 // Hence there is at most one Births instance for each Location on each thread. | 66 // at most one Births instance for each Location / ThreadData pair. The derived |
| 67 // The derived Births class contains slots for recording statistics about all | 67 // Births class contains slots for recording statistics about all instances born |
| 68 // instances born at the same location. Statistics currently include only the | 68 // at the same location. Statistics currently include only the count of |
| 69 // count of instances constructed. | 69 // instances constructed. |
| 70 // | 70 // |
| 71 // Since the base class BirthOnThread contains only constant data, it can be | 71 // Since the base class BirthOnThread contains only constant data, it can be |
| 72 // freely accessed by any thread at any time (i.e., only the statistic needs to | 72 // freely accessed by any thread at any time. The statistics must be handled |
| 73 // be handled carefully, and stats are updated exclusively on the birth thread). | 73 // more carefully; they are updated exclusively by the single thread to which |
| 74 // the ThreadData is bound at a given time. | |
| 74 // | 75 // |
| 75 // For Tasks, having now either constructed or found the Births instance | 76 // For Tasks, having now either constructed or found the Births instance |
| 76 // described above, a pointer to the Births instance is then recorded into the | 77 // described above, a pointer to the Births instance is then recorded into the |
| 77 // PendingTask structure in MessageLoop. This fact alone is very useful in | 78 // PendingTask structure. This fact alone is very useful in debugging, when |
| 78 // debugging, when there is a question of where an instance came from. In | 79 // there is a question of where an instance came from. In addition, the birth |
| 79 // addition, the birth time is also recorded and used to later evaluate the | 80 // time is also recorded and used to later evaluate the lifetime duration of the |
| 80 // lifetime duration of the whole Task. As a result of the above embedding, we | 81 // whole Task. As a result of the above embedding, we can find out a Task's |
| 81 // can find out a Task's location of birth, and thread of birth, without using | 82 // location of birth, and name of birth thread, without using any locks, as all |
| 82 // any locks, as all that data is constant across the life of the process. | 83 // that data is constant across the life of the process. |
| 83 // | 84 // |
| 84 // The above work *could* also be done for any other object as well by calling | 85 // The above work *could* also be done for any other object as well by calling |
| 85 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. | 86 // TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. |
| 86 // | 87 // |
| 87 // The amount of memory used in the above data structures depends on how many | 88 // The maxium amount of memory used in the above data structures is the product |
|
Nico
2016/11/24 01:42:04
typo maxium
Also, the changes to this paragraph a
fdoray
2016/11/29 16:10:33
I'm saying the same thing as before, with fewer wo
| |
| 88 // threads there are, and how many Locations of construction there are. | 89 // of the number of ThreadData instances and the number of Locations. |
| 89 // Fortunately, we don't use memory that is the product of those two counts, but | 90 // Fortunately, Locations are often created on a single thread and the memory |
| 90 // rather we only need one Births instance for each thread that constructs an | 91 // utilization is actually fairly restrained. |
| 91 // instance at a Location. In many cases, instances are only created on one | |
| 92 // thread, so the memory utilization is actually fairly restrained. | |
| 93 // | 92 // |
| 94 // Lastly, when an instance is deleted, the final tallies of statistics are | 93 // Lastly, when an instance is deleted, the final tallies of statistics are |
| 95 // carefully accumulated. That tallying writes into slots (members) in a | 94 // carefully accumulated. That tallying writes into slots (members) in a |
| 96 // collection of DeathData instances. For each birth place Location that is | 95 // collection of DeathData instances. For each Births / death ThreadData pair, |
| 97 // destroyed on a thread, there is a DeathData instance to record the additional | 96 // there is a DeathData instance to record the additional death count, as well |
| 98 // death count, as well as accumulate the run-time and queue-time durations for | 97 // as accumulate the run-time and queue-time durations for the instance as it is |
|
Nico
2016/11/24 01:42:04
"as well as to accumulate"? (lhs is the same as rh
fdoray
2016/11/29 16:10:33
Done.
| |
| 99 // the instance as it is destroyed (dies). By maintaining a single place to | 98 // destroyed (dies). Since a ThreadData is bound to at most one thread at a |
| 100 // aggregate this running sum *only* for the given thread, we avoid the need to | 99 // time, there is no need to lock such DeathData instances. (i.e., these |
| 101 // lock such DeathData instances. (i.e., these accumulated stats in a DeathData | 100 // accumulated stats in a DeathData instance are exclusively updated by the |
| 102 // instance are exclusively updated by the singular owning thread). | 101 // singular owning thread). |
| 103 // | 102 // |
| 104 // With the above life cycle description complete, the major remaining detail | 103 // With the above life cycle description complete, the major remaining detail is |
| 105 // is explaining how each thread maintains a list of DeathData instances, and | 104 // explaining how existing Births and DeathData instances are found to avoid |
| 106 // of Births instances, and is able to avoid additional (redundant/unnecessary) | 105 // redundant allocations. |
| 107 // allocations. | |
| 108 // | 106 // |
| 109 // Each thread maintains a list of data items specific to that thread in a | 107 // A ThreadData instance maintains maps of Births and DeathData instances. The |
| 110 // ThreadData instance (for that specific thread only). The two critical items | 108 // Births map is indexed by Location and the DeathData map is indexed by |
| 111 // are lists of DeathData and Births instances. These lists are maintained in | 109 // Births*. As noted earlier, we can compare Locations very efficiently as we |
| 112 // STL maps, which are indexed by Location. As noted earlier, we can compare | 110 // consider the underlying data (file, function, line) to be atoms, and hence |
| 113 // locations very efficiently as we consider the underlying data (file, | 111 // pointer comparison is used rather than (slow) string comparisons. |
| 114 // function, line) to be atoms, and hence pointer comparison is used rather than | |
| 115 // (slow) string comparisons. | |
| 116 // | 112 // |
| 117 // To provide a mechanism for iterating over all "known threads," which means | 113 // The first time that a thread calls ThreadData::InitializeThreadContext() or |
| 118 // threads that have recorded a birth or a death, we create a singly linked list | 114 // ThreadData::Get(), a ThreadData instance is bound to it and stored in TLS. If |
| 119 // of ThreadData instances. Each such instance maintains a pointer to the next | 115 // a ThreadData bound to a terminated thread with the same sanitized name (i.e. |
| 120 // one. A static member of ThreadData provides a pointer to the first item on | 116 // name without trailing digits) as the current thread is available, it is |
| 121 // this global list, and access via that all_thread_data_list_head_ item | 117 // reused. Otherwise, a new ThreadData instance is instantiated. Since a |
| 122 // requires the use of the list_lock_. | 118 // ThreadData is bound to at most one thread at a time, there is no need to |
| 119 // acquire a lock to access its maps. Over time, a ThreadData may be bound to | |
| 120 // different threads that share the same sanitized name. | |
| 121 // | |
| 122 // We maintain a list of all ThreadData instances for the current process. Each | |
| 123 // ThreadData instance has a pointer to the next one. A static member of | |
| 124 // ThreadData provides a pointer to the first item on this global list, and | |
| 125 // access via that all_thread_data_list_head_ item requires the use of the | |
| 126 // list_lock_. | |
|
Nico
2016/11/24 01:42:04
Thanks for the comprehensive comment update!
fdoray
2016/11/29 16:10:33
Acknowledged.
| |
| 127 // | |
| 123 // When new ThreadData instances is added to the global list, it is pre-pended, | 128 // When new ThreadData instances is added to the global list, it is pre-pended, |
|
Nico
2016/11/24 01:42:04
(s/is added/are added/. yes, not your code.)
fdoray
2016/11/29 16:10:33
Done.
| |
| 124 // which ensures that any prior acquisition of the list is valid (i.e., the | 129 // which ensures that any prior acquisition of the list is valid (i.e., the |
| 125 // holder can iterate over it without fear of it changing, or the necessity of | 130 // holder can iterate over it without fear of it changing, or the necessity of |
| 126 // using an additional lock. Iterations are actually pretty rare (used | 131 // using an additional lock. Iterations are actually pretty rare (used |
| 127 // primarily for cleanup, or snapshotting data for display), so this lock has | 132 // primarily for cleanup, or snapshotting data for display), so this lock has |
| 128 // very little global performance impact. | 133 // very little global performance impact. |
| 129 // | 134 // |
| 130 // The above description tries to define the high performance (run time) | 135 // The above description tries to define the high performance (run time) |
| 131 // portions of these classes. After gathering statistics, calls instigated | 136 // portions of these classes. After gathering statistics, calls instigated |
| 132 // by visiting about:profiler will assemble and aggregate data for display. The | 137 // by visiting about:profiler will assemble and aggregate data for display. The |
| 133 // following data structures are used for producing such displays. They are | 138 // following data structures are used for producing such displays. They are |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 163 // atomically collecting all data, so we could have count that does not, for | 168 // atomically collecting all data, so we could have count that does not, for |
| 164 // example, match with the number of durations we accumulated). The advantage | 169 // example, match with the number of durations we accumulated). The advantage |
| 165 // to having fast (non-atomic) updates of the data outweighs the minimal risk of | 170 // to having fast (non-atomic) updates of the data outweighs the minimal risk of |
| 166 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, | 171 // a singular corrupt statistic snapshot (only the snapshot could be corrupt, |
| 167 // not the underlying and ongoing statistic). In contrast, pointer data that | 172 // not the underlying and ongoing statistic). In contrast, pointer data that |
| 168 // is accessed during snapshotting is completely invariant, and hence is | 173 // is accessed during snapshotting is completely invariant, and hence is |
| 169 // perfectly acquired (i.e., no potential corruption, and no risk of a bad | 174 // perfectly acquired (i.e., no potential corruption, and no risk of a bad |
| 170 // memory reference). | 175 // memory reference). |
| 171 // | 176 // |
| 172 // TODO(jar): We can implement a Snapshot system that *tries* to grab the | 177 // TODO(jar): We can implement a Snapshot system that *tries* to grab the |
| 173 // snapshots on the source threads *when* they have MessageLoops available | 178 // snapshots on the source threads *when* they have SingleThreadTaskRunners |
| 174 // (worker threads don't have message loops generally, and hence gathering from | 179 // available (worker threads don't have SingleThreadTaskRunners, and hence |
| 175 // them will continue to be asynchronous). We had an implementation of this in | 180 // gathering from them will continue to be asynchronous). We had an |
| 176 // the past, but the difficulty is dealing with message loops being terminated. | 181 // implementation of this in the past, but the difficulty is dealing with |
| 177 // We can *try* to spam the available threads via some task runner to | 182 // threads being terminated. We can *try* to post a task to threads that have a |
| 178 // achieve this feat, and it *might* be valuable when we are collecting data | 183 // SingleThreadTaskRunner and check if that succeeds (will fail if the thread |
| 184 // has been terminated). This *might* be valuable when we are collecting data | |
| 179 // for upload via UMA (where correctness of data may be more significant than | 185 // for upload via UMA (where correctness of data may be more significant than |
| 180 // for a single screen of about:profiler). | 186 // for a single screen of about:profiler). |
| 181 // | 187 // |
| 182 // TODO(jar): We need to store DataCollections, and provide facilities for | 188 // TODO(jar): We need to store DataCollections, and provide facilities for |
| 183 // taking the difference between two gathered DataCollections. For now, we're | 189 // taking the difference between two gathered DataCollections. For now, we're |
| 184 // just adding a hack that Reset()s to zero all counts and stats. This is also | 190 // just adding a hack that Reset()s to zero all counts and stats. This is also |
| 185 // done in a slightly thread-unsafe fashion, as the resetting is done | 191 // done in a slightly thread-unsafe fashion, as the resetting is done |
| 186 // asynchronously relative to ongoing updates (but all data is 32 bit in size). | 192 // asynchronously relative to ongoing updates (but all data is 32 bit in size). |
| 187 // For basic profiling, this will work "most of the time," and should be | 193 // For basic profiling, this will work "most of the time," and should be |
| 188 // sufficient... but storing away DataCollections is the "right way" to do this. | 194 // sufficient... but storing away DataCollections is the "right way" to do this. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 219 | 225 |
| 220 //------------------------------------------------------------------------------ | 226 //------------------------------------------------------------------------------ |
| 221 // A "snapshotted" representation of the BirthOnThread class. | 227 // A "snapshotted" representation of the BirthOnThread class. |
| 222 | 228 |
| 223 struct BASE_EXPORT BirthOnThreadSnapshot { | 229 struct BASE_EXPORT BirthOnThreadSnapshot { |
| 224 BirthOnThreadSnapshot(); | 230 BirthOnThreadSnapshot(); |
| 225 explicit BirthOnThreadSnapshot(const BirthOnThread& birth); | 231 explicit BirthOnThreadSnapshot(const BirthOnThread& birth); |
| 226 ~BirthOnThreadSnapshot(); | 232 ~BirthOnThreadSnapshot(); |
| 227 | 233 |
| 228 LocationSnapshot location; | 234 LocationSnapshot location; |
| 229 std::string thread_name; | 235 std::string thread_name; |
|
Nico
2016/11/24 01:42:04
This should probably now be called sanitized_name
fdoray
2016/11/29 16:10:33
Done.
The receiver of the json generated by task_
| |
| 230 }; | 236 }; |
| 231 | 237 |
| 232 //------------------------------------------------------------------------------ | 238 //------------------------------------------------------------------------------ |
| 233 // A class for accumulating counts of births (without bothering with a map<>). | 239 // A class for accumulating counts of births (without bothering with a map<>). |
| 234 | 240 |
| 235 class BASE_EXPORT Births: public BirthOnThread { | 241 class BASE_EXPORT Births: public BirthOnThread { |
| 236 public: | 242 public: |
| 237 Births(const Location& location, const ThreadData& current); | 243 Births(const Location& location, const ThreadData& current); |
| 238 | 244 |
| 239 int birth_count() const; | 245 int birth_count() const; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 DEACTIVATED, // No longer recording profiling. | 449 DEACTIVATED, // No longer recording profiling. |
| 444 PROFILING_ACTIVE, // Recording profiles. | 450 PROFILING_ACTIVE, // Recording profiles. |
| 445 STATUS_LAST = PROFILING_ACTIVE | 451 STATUS_LAST = PROFILING_ACTIVE |
| 446 }; | 452 }; |
| 447 | 453 |
| 448 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; | 454 typedef base::hash_map<Location, Births*, Location::Hash> BirthMap; |
| 449 typedef std::map<const Births*, DeathData> DeathMap; | 455 typedef std::map<const Births*, DeathData> DeathMap; |
| 450 | 456 |
| 451 // Initialize the current thread context with a new instance of ThreadData. | 457 // Initialize the current thread context with a new instance of ThreadData. |
| 452 // This is used by all threads that have names, and should be explicitly | 458 // This is used by all threads that have names, and should be explicitly |
| 453 // set *before* any births on the threads have taken place. It is generally | 459 // set *before* any births on the threads have taken place. |
| 454 // only used by the message loop, which has a well defined thread name. | 460 static void InitializeThreadContext(const std::string& thread_name); |
| 455 static void InitializeThreadContext(const std::string& suggested_name); | |
| 456 | 461 |
| 457 // Using Thread Local Store, find the current instance for collecting data. | 462 // Using Thread Local Store, find the current instance for collecting data. |
| 458 // If an instance does not exist, construct one (and remember it for use on | 463 // If an instance does not exist, construct one (and remember it for use on |
| 459 // this thread. | 464 // this thread. |
| 460 // This may return NULL if the system is disabled for any reason. | 465 // This may return NULL if the system is disabled for any reason. |
| 461 static ThreadData* Get(); | 466 static ThreadData* Get(); |
| 462 | 467 |
| 463 // Fills |process_data_snapshot| with phased snapshots of all profiling | 468 // Fills |process_data_snapshot| with phased snapshots of all profiling |
| 464 // phases, including the current one, identified by |current_profiling_phase|. | 469 // phases, including the current one, identified by |current_profiling_phase|. |
| 465 // |current_profiling_phase| is necessary because a child process can start | 470 // |current_profiling_phase| is necessary because a child process can start |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 503 // finished). | 508 // finished). |
| 504 static void TallyRunOnWorkerThreadIfTracking(const Births* births, | 509 static void TallyRunOnWorkerThreadIfTracking(const Births* births, |
| 505 const TrackedTime& time_posted, | 510 const TrackedTime& time_posted, |
| 506 const TaskStopwatch& stopwatch); | 511 const TaskStopwatch& stopwatch); |
| 507 | 512 |
| 508 // Record the end of execution in region, generally corresponding to a scope | 513 // Record the end of execution in region, generally corresponding to a scope |
| 509 // being exited. | 514 // being exited. |
| 510 static void TallyRunInAScopedRegionIfTracking(const Births* births, | 515 static void TallyRunInAScopedRegionIfTracking(const Births* births, |
| 511 const TaskStopwatch& stopwatch); | 516 const TaskStopwatch& stopwatch); |
| 512 | 517 |
| 513 const std::string& thread_name() const { return thread_name_; } | 518 const std::string& sanitized_thread_name() const { |
| 519 return sanitized_thread_name_; | |
| 520 } | |
| 514 | 521 |
| 515 // Initializes all statics if needed (this initialization call should be made | 522 // Initializes all statics if needed (this initialization call should be made |
| 516 // while we are single threaded). | 523 // while we are single threaded). |
| 517 static void EnsureTlsInitialization(); | 524 static void EnsureTlsInitialization(); |
| 518 | 525 |
| 519 // Sets internal status_. | 526 // Sets internal status_. |
| 520 // If |status| is false, then status_ is set to DEACTIVATED. | 527 // If |status| is false, then status_ is set to DEACTIVATED. |
| 521 // If |status| is true, then status_ is set to PROFILING_ACTIVE. | 528 // If |status| is true, then status_ is set to PROFILING_ACTIVE. |
| 522 static void InitializeAndSetTrackingStatus(Status status); | 529 static void InitializeAndSetTrackingStatus(Status status); |
| 523 | 530 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 552 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); | 559 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); |
| 553 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); | 560 FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); |
| 554 | 561 |
| 555 // Type for an alternate timer function (testing only). | 562 // Type for an alternate timer function (testing only). |
| 556 typedef unsigned int NowFunction(); | 563 typedef unsigned int NowFunction(); |
| 557 | 564 |
| 558 typedef std::map<const BirthOnThread*, int> BirthCountMap; | 565 typedef std::map<const BirthOnThread*, int> BirthCountMap; |
| 559 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> | 566 typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> |
| 560 DeathsSnapshot; | 567 DeathsSnapshot; |
| 561 | 568 |
| 562 // Worker thread construction creates a name since there is none. | 569 explicit ThreadData(const std::string& sanitized_thread_name); |
| 563 explicit ThreadData(int thread_number); | |
| 564 | |
| 565 // Message loop based construction should provide a name. | |
| 566 explicit ThreadData(const std::string& suggested_name); | |
| 567 | |
| 568 ~ThreadData(); | 570 ~ThreadData(); |
| 569 | 571 |
| 570 // Push this instance to the head of all_thread_data_list_head_, linking it to | 572 // Push this instance to the head of all_thread_data_list_head_, linking it to |
| 571 // the previous head. This is performed after each construction, and leaves | 573 // the previous head. This is performed after each construction, and leaves |
| 572 // the instance permanently on that list. | 574 // the instance permanently on that list. |
| 573 void PushToHeadOfList(); | 575 void PushToHeadOfList(); |
| 574 | 576 |
| 575 // (Thread safe) Get start of list of all ThreadData instances using the lock. | 577 // (Thread safe) Get start of list of all ThreadData instances using the lock. |
| 576 static ThreadData* first(); | 578 static ThreadData* first(); |
| 577 | 579 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 621 // uninitialized) state. If there is any chance that other threads are still | 623 // uninitialized) state. If there is any chance that other threads are still |
| 622 // using the data structures, then the |leak| argument should be passed in as | 624 // using the data structures, then the |leak| argument should be passed in as |
| 623 // true, and the data structures (birth maps, death maps, ThreadData | 625 // true, and the data structures (birth maps, death maps, ThreadData |
| 624 // insntances, etc.) will be leaked and not deleted. If you have joined all | 626 // insntances, etc.) will be leaked and not deleted. If you have joined all |
| 625 // threads since the time that InitializeAndSetTrackingStatus() was called, | 627 // threads since the time that InitializeAndSetTrackingStatus() was called, |
| 626 // then you can pass in a |leak| value of false, and this function will | 628 // then you can pass in a |leak| value of false, and this function will |
| 627 // delete recursively all data structures, starting with the list of | 629 // delete recursively all data structures, starting with the list of |
| 628 // ThreadData instances. | 630 // ThreadData instances. |
| 629 static void ShutdownSingleThreadedCleanup(bool leak); | 631 static void ShutdownSingleThreadedCleanup(bool leak); |
| 630 | 632 |
| 633 // Returns a ThreadData instance for a thread whose sanitized name is | |
| 634 // |sanitized_thread_name|. The returned instance may have been extracted from | |
| 635 // the list of retired ThreadData instances or newly allocated. | |
| 636 static ThreadData* GetRetiredOrCreateThreadData( | |
| 637 const std::string& sanitized_thread_name); | |
| 638 | |
| 631 // When non-null, this specifies an external function that supplies monotone | 639 // When non-null, this specifies an external function that supplies monotone |
| 632 // increasing time functcion. | 640 // increasing time functcion. |
| 633 static NowFunction* now_function_for_testing_; | 641 static NowFunction* now_function_for_testing_; |
| 634 | 642 |
| 635 // We use thread local store to identify which ThreadData to interact with. | 643 // We use thread local store to identify which ThreadData to interact with. |
| 636 static base::ThreadLocalStorage::StaticSlot tls_index_; | 644 static base::ThreadLocalStorage::StaticSlot tls_index_; |
| 637 | 645 |
| 638 // List of ThreadData instances for use with worker threads. When a worker | 646 // Linked list of ThreadData instances that were associated with threads that |
| 639 // thread is done (terminated), we push it onto this list. When a new worker | 647 // have been terminated and that have not been associated with a new thread |
| 640 // thread is created, we first try to re-use a ThreadData instance from the | 648 // since then. This is only accessed while |list_lock_| is held. |
| 641 // list, and if none are available, construct a new one. | 649 static ThreadData* first_retired_thread_data_; |
| 642 // This is only accessed while list_lock_ is held. | |
| 643 static ThreadData* first_retired_worker_; | |
| 644 | 650 |
| 645 // Link to the most recently created instance (starts a null terminated list). | 651 // Link to the most recently created instance (starts a null terminated list). |
| 646 // The list is traversed by about:profiler when it needs to snapshot data. | 652 // The list is traversed by about:profiler when it needs to snapshot data. |
| 647 // This is only accessed while list_lock_ is held. | 653 // This is only accessed while list_lock_ is held. |
| 648 static ThreadData* all_thread_data_list_head_; | 654 static ThreadData* all_thread_data_list_head_; |
| 649 | 655 |
| 650 // The next available worker thread number. This should only be accessed when | |
| 651 // the list_lock_ is held. | |
| 652 static int worker_thread_data_creation_count_; | |
| 653 | |
| 654 // The number of times TLS has called us back to cleanup a ThreadData | 656 // The number of times TLS has called us back to cleanup a ThreadData |
| 655 // instance. This is only accessed while list_lock_ is held. | 657 // instance. This is only accessed while list_lock_ is held. |
| 656 static int cleanup_count_; | 658 static int cleanup_count_; |
| 657 | 659 |
| 658 // Incarnation sequence number, indicating how many times (during unittests) | 660 // Incarnation sequence number, indicating how many times (during unittests) |
| 659 // we've either transitioned out of UNINITIALIZED, or into that state. This | 661 // we've either transitioned out of UNINITIALIZED, or into that state. This |
| 660 // value is only accessed while the list_lock_ is held. | 662 // value is only accessed while the list_lock_ is held. |
| 661 static int incarnation_counter_; | 663 static int incarnation_counter_; |
| 662 | 664 |
| 663 // Protection for access to all_thread_data_list_head_, and to | 665 // Protection for access to all_thread_data_list_head_, and to |
| 664 // unregistered_thread_data_pool_. This lock is leaked at shutdown. | 666 // unregistered_thread_data_pool_. This lock is leaked at shutdown. |
| 665 // The lock is very infrequently used, so we can afford to just make a lazy | 667 // The lock is very infrequently used, so we can afford to just make a lazy |
| 666 // instance and be safe. | 668 // instance and be safe. |
| 667 static base::LazyInstance<base::Lock>::Leaky list_lock_; | 669 static base::LazyInstance<base::Lock>::Leaky list_lock_; |
| 668 | 670 |
| 669 // We set status_ to SHUTDOWN when we shut down the tracking service. | 671 // We set status_ to SHUTDOWN when we shut down the tracking service. |
| 670 static base::subtle::Atomic32 status_; | 672 static base::subtle::Atomic32 status_; |
| 671 | 673 |
| 672 // Link to next instance (null terminated list). Used to globally track all | 674 // Link to next instance (null terminated list). Used to globally track all |
| 673 // registered instances (corresponds to all registered threads where we keep | 675 // registered instances (corresponds to all registered threads where we keep |
| 674 // data). | 676 // data). |
| 675 ThreadData* next_; | 677 ThreadData* next_; |
| 676 | 678 |
| 677 // Pointer to another ThreadData instance for a Worker-Thread that has been | 679 // Pointer to another retired ThreadData instance. This value is nullptr if |
| 678 // retired (its thread was terminated). This value is non-NULL only for a | 680 // this is associated with an active thread. |
| 679 // retired ThreadData associated with a Worker-Thread. | 681 ThreadData* next_retired_thread_data_; |
| 680 ThreadData* next_retired_worker_; | |
| 681 | 682 |
| 682 // The name of the thread that is being recorded. If this thread has no | 683 // The name of the thread that is being recorded, with all trailing digits |
| 683 // message_loop, then this is a worker thread, with a sequence number postfix. | 684 // replaced with a single "*" character. |
| 684 std::string thread_name_; | 685 const std::string sanitized_thread_name_; |
| 685 | |
| 686 // Indicate if this is a worker thread, and the ThreadData contexts should be | |
| 687 // stored in the unregistered_thread_data_pool_ when not in use. | |
| 688 // Value is zero when it is not a worker thread. Value is a positive integer | |
| 689 // corresponding to the created thread name if it is a worker thread. | |
| 690 int worker_thread_number_; | |
| 691 | 686 |
| 692 // A map used on each thread to keep track of Births on this thread. | 687 // A map used on each thread to keep track of Births on this thread. |
| 693 // This map should only be accessed on the thread it was constructed on. | 688 // This map should only be accessed on the thread it was constructed on. |
| 694 // When a snapshot is needed, this structure can be locked in place for the | 689 // When a snapshot is needed, this structure can be locked in place for the |
| 695 // duration of the snapshotting activity. | 690 // duration of the snapshotting activity. |
| 696 BirthMap birth_map_; | 691 BirthMap birth_map_; |
| 697 | 692 |
| 698 // Similar to birth_map_, this records informations about death of tracked | 693 // Similar to birth_map_, this records informations about death of tracked |
| 699 // instances (i.e., when a tracked instance was destroyed on this thread). | 694 // instances (i.e., when a tracked instance was destroyed on this thread). |
| 700 // It is locked before changing, and hence other threads may access it by | 695 // It is locked before changing, and hence other threads may access it by |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 811 ProcessDataSnapshot(const ProcessDataSnapshot& other); | 806 ProcessDataSnapshot(const ProcessDataSnapshot& other); |
| 812 ~ProcessDataSnapshot(); | 807 ~ProcessDataSnapshot(); |
| 813 | 808 |
| 814 PhasedProcessDataSnapshotMap phased_snapshots; | 809 PhasedProcessDataSnapshotMap phased_snapshots; |
| 815 base::ProcessId process_id; | 810 base::ProcessId process_id; |
| 816 }; | 811 }; |
| 817 | 812 |
| 818 } // namespace tracked_objects | 813 } // namespace tracked_objects |
| 819 | 814 |
| 820 #endif // BASE_TRACKED_OBJECTS_H_ | 815 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |