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 |