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

Side by Side Diff: base/debug/activity_tracker.h

Issue 1980743002: Track thread activities in order to diagnose hangs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@readwrite-mmf
Patch Set: rebased Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_METRICS_ACTIVITY_TRACKER_H_
6 #define BASE_METRICS_ACTIVITY_TRACKER_H_
7
8 #include <atomic>
9 #include <memory>
10
11 #include "base/base_export.h"
12 #include "base/feature_list.h"
13 #include "base/files/file_path.h"
14 #include "base/metrics/persistent_memory_allocator.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread_checker.h"
17 #include "base/threading/thread_local_storage.h"
18
19 namespace base {
20
21 struct PendingTask;
22
23 class Lock;
24 class MemoryMappedFile;
25
26 namespace debug {
Sigurður Ásgeirsson 2016/05/20 13:12:05 A general comment on thread identity here. First i
manzagop (departed) 2016/05/20 13:55:42 +1 There's also some system wide info that would
bcwhite 2016/05/20 19:19:19 My understanding is that the thread-local-storage,
bcwhite 2016/05/20 19:19:19 That's outside of the scope of this module but I'v
manzagop (departed) 2016/05/20 20:24:21 Great!
27
28 // Enables the global activity tracker according to a field trial setting.
29 BASE_EXPORT void SetupGlobalActivityTrackerFieldTrial();
30
31
32 // This class manages tracking a stack of activities for a single thread in
33 // a persistent manner. However, in order to support an operational mode where
34 // another thread is analyzing this data in real-time, atomic operations are
35 // used where necessary to guarantee a consistent view from the outside.
36 class BASE_EXPORT ThreadActivityTracker {
Sigurður Ásgeirsson 2016/05/20 13:12:05 I assume each instance of this class has thread af
bcwhite 2016/05/20 19:19:19 Correct. A ThreadChecker ensures this.
37 public:
38 enum ActivityType : uint8_t {
39 ACT_TASK,
40 ACT_LOCK,
41 ACT_EVENT,
42 };
43
44 struct StackEntry {
Sigurður Ásgeirsson 2016/05/20 13:12:05 nit: the fields warrant a little bit of documentat
bcwhite 2016/05/20 19:19:19 Yup. Documentation is definitely unfinished. It'
45 int64_t time_ticks;
46 uint8_t activity_type;
Sigurður Ásgeirsson 2016/05/20 13:12:05 I think what we need is an easily extensible tagge
bcwhite 2016/05/20 19:19:19 I agree. That'll simplify some other places, too,
47 intptr_t source_address;
48 intptr_t method_address;
49 uint64_t sequence_id;
50 };
51
52 class BASE_EXPORT ScopedActivity {
53 public:
54 ScopedActivity(ThreadActivityTracker* tracker,
55 const void* source,
56 ActivityType activity,
57 intptr_t method,
58 uint64_t sequence)
59 : tracker_(tracker), source_(source) {
60 if (tracker_)
61 tracker_->RecordStart(source, activity, method, sequence);
62 }
63 ~ScopedActivity() {
64 if (tracker_)
65 tracker_->RecordFinish(source_);
66 }
67
68 private:
69 ThreadActivityTracker* const tracker_;
70 const void* const source_;
71 };
72
73 // A ThreadActivityTracker runs on top of memory that is managed externally.
manzagop (departed) 2016/05/20 18:19:30 Mention the precondition on the size (large enough
bcwhite 2016/05/20 19:19:19 Done.
74 ThreadActivityTracker(void* base, size_t size);
75 virtual ~ThreadActivityTracker();
76
77 // Indicate that a method of the given (arbitrary) identifier has started.
78 void RecordStart(const void* source,
Sigurður Ásgeirsson 2016/05/20 13:12:04 RecordXXX implies tracing, but here we're maintain
bcwhite 2016/05/20 19:19:19 Done.
79 ActivityType activity,
80 intptr_t method,
81 uint64_t sequence);
82
83 // Indicate that a method of the given (arbitrary) identifier has finished.
84 void RecordFinish(const void* source);
85
86 // Gets a copy of the current stack contents. The return value is the current
87 // depth of the stack which may be greater than the number of StackEntry
88 // records returned. If so, the returned stack has the "base" of the stack
89 // with later entries omitted.
90 uint32_t CopyStack(std::vector<StackEntry>* stack);
Sigurður Ásgeirsson 2016/05/20 13:12:05 is this ForTesting, or do you foresee this being a
bcwhite 2016/05/20 19:19:19 It's not for testing. It's the primary interface
91
92 // Returns whether the current data is valid or not. Fetching a copy of the
manzagop (departed) 2016/05/20 18:19:30 When can the data be not valid? Is it only for a
bcwhite 2016/05/20 19:19:19 Done.
93 // stack will return nothing if the data is not valid.
94 bool is_valid() { return valid_; }
95
96 // Calculates the memory size required for a given stack depth.
manzagop (departed) 2016/05/20 18:19:30 nit: clarify this includes the header, eg "require
bcwhite 2016/05/20 19:19:19 Done.
97 static size_t SizeForStackDepth(int stack_depth);
98
99 private:
100 friend class Iterator;
manzagop (departed) 2016/05/20 18:19:30 Is this needed?
bcwhite 2016/05/20 19:19:19 No. The iterator went away in favor of CopyStack(
101
102 struct Header;
103
104 Header* const header_;
105 StackEntry* const stack_;
106 const uint32_t slots_;
manzagop (departed) 2016/05/20 18:19:30 nit: max_stack_depth_ or stack_slots_ clearer?
bcwhite 2016/05/20 19:19:19 Done. The "depth" can actually be greater; it's j
107
108 bool valid_ = false;
109
110 base::ThreadChecker thread_checker_;
111
112 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker);
113 };
114
115 class BASE_EXPORT GlobalActivityTracker {
Sigurður Ásgeirsson 2016/05/20 13:12:05 so one of these guys manages one per thread of the
bcwhite 2016/05/20 19:19:19 Correct.
116 public:
117 class BASE_EXPORT ScopedThreadActivity
118 : public ThreadActivityTracker::ScopedActivity {
119 public:
120 ScopedThreadActivity(const void* source,
121 ThreadActivityTracker::ActivityType activity,
122 intptr_t method,
123 uint64_t sequence)
124 : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(),
125 source,
126 activity,
127 method,
128 sequence) {}
129
130 private:
131 static ThreadActivityTracker* GetOrCreateTracker() {
132 GlobalActivityTracker* global_tracker = Get();
133 if (!global_tracker)
134 return nullptr;
135 return global_tracker->GetOrCreateTrackerForCurrentThread();
136 }
137 };
138
139 ~GlobalActivityTracker();
140
141 static void CreateWithAllocator(
142 std::unique_ptr<PersistentMemoryAllocator> allocator,
143 int stack_depth);
144
145 static void CreateWithLocalMemory(size_t size,
146 uint64_t id,
147 StringPiece name,
148 int stack_depth);
149
150 static void CreateWithFile(const FilePath& file_path,
151 size_t size,
152 uint64_t id,
153 StringPiece name,
154 int stack_depth);
155
156 // Gets the global activity-tracker or null if none exists.
157 static GlobalActivityTracker* Get() { return g_tracker_; }
158
159 // Gets the thread's activity-tracker, assuming it already exists. This
160 // is inline for performance reasons. Ownership remains with the global
161 // tracker.
162 ThreadActivityTracker* GetTrackerForCurrentThread() {
163 void* tracker = this_thread_tracker_.Get();
164 DCHECK(tracker);
165 return reinterpret_cast<ThreadActivityTracker*>(tracker);
166 }
167
168 // Gets the thread's activity-tracker or creates one if none exists. This
169 // is inline for performance reasons. Ownership remains with the global
170 // tracker.
171 ThreadActivityTracker* GetOrCreateTrackerForCurrentThread() {
Sigurður Ásgeirsson 2016/05/20 13:12:04 I dunno about Chromium coding guidelines, but I li
bcwhite 2016/05/20 19:19:19 I've seen it done both ways. It was defined inlin
Sigurður Ásgeirsson 2016/05/24 14:11:50 Right - I'm saying you can have your cake and eat
bcwhite 2016/05/26 15:35:39 Understood. I'm saying that I've seen Chromium co
172 void* tracker = this_thread_tracker_.Get();
173 if (tracker)
174 return reinterpret_cast<ThreadActivityTracker*>(tracker);
175 return CreateTrackerForCurrentThread();
176 }
177
178 // Creates an activity-tracker for the current thread.
179 ThreadActivityTracker* CreateTrackerForCurrentThread();
180
181 // Releases the activity-tracker for the current thread (for testing only).
182 void ReleaseTrackerForCurrentThreadForTesting();
183
184 private:
185 class ManagedActivityTracker : public ThreadActivityTracker {
186 public:
187 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference,
188 void* base,
189 size_t size);
190 ~ManagedActivityTracker() override;
191
192 private:
193 const PersistentMemoryAllocator::Reference mem_reference_;
194 void* const mem_base_;
195 };
196
197 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator,
198 int stack_depth);
199
200 // Returns the memory used by an activity-tracker managed by this class.
201 void ReturnTrackerMemory(ManagedActivityTracker* tracker,
202 PersistentMemoryAllocator::Reference mem_reference,
203 void* mem_base);
204
205 static void OnTLSDestroy(void* value);
206
207 std::unique_ptr<PersistentMemoryAllocator> allocator_;
208 const size_t stack_memory_;
manzagop (departed) 2016/05/20 20:24:22 nit: stack_memory_size_?
bcwhite 2016/05/26 15:35:39 Done.
209
210 base::ThreadLocalStorage::Slot this_thread_tracker_;
211
212 Lock lock_;
213 std::set<ManagedActivityTracker*> thread_trackers_;
214 std::vector<PersistentMemoryAllocator::Reference> available_memories_;
215
216 static GlobalActivityTracker* g_tracker_;
217 };
218
219 class BASE_EXPORT ScopedTaskActivity
Sigurður Ásgeirsson 2016/05/20 13:12:04 it looks like this class is the interface to the m
bcwhite 2016/05/20 19:19:19 Acknowledged.
220 : public GlobalActivityTracker::ScopedThreadActivity {
221 public:
222 ScopedTaskActivity(const base::PendingTask& task);
223 };
224
225 } // namespace debug
226 } // namespace base
227
228 #endif // BASE_METRICS_ACTIVITY_TRACKER_H_
OLDNEW
« no previous file with comments | « base/base.gypi ('k') | base/debug/activity_tracker.cc » ('j') | base/debug/activity_tracker.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698