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

Side by Side Diff: base/metrics/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: general improvements and scoped activities 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
« no previous file with comments | « base/debug/task_annotator.cc ('k') | base/metrics/activity_tracker.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Feature definition for enabling persistent activity tracking.
27 BASE_EXPORT extern const Feature kPersistentActivityTrackingFeature;
28
29 // This class manages tracking a stack of activities for a single thread in
30 // a persistent manner. However, in order to support an operational mode where
31 // another thread is analyzing this data in real-time, atomic operations are
32 // used where necessary to guarantee a consistent view from the outside.
33 class BASE_EXPORT ThreadActivityTracker {
manzagop (departed) 2016/05/20 13:55:42 If this is a stack, then does the interface need a
34 public:
35 enum ActivityType : uint8_t {
36 ACT_TASK,
37 ACT_LOCK,
38 ACT_EVENT,
39 };
40
41 struct StackEntry {
42 int64_t time_ticks;
43 uint8_t activity_type;
44 intptr_t source_address;
45 intptr_t method_address;
46 uint64_t sequence_id;
47 };
48
49 class BASE_EXPORT ScopedActivity {
50 public:
51 ScopedActivity(ThreadActivityTracker* tracker,
52 const void* source,
53 ActivityType activity,
54 intptr_t method,
55 uint64_t sequence)
56 : tracker_(tracker), source_(source) {
57 if (tracker_)
58 tracker_->RecordStart(source, activity, method, sequence);
59 }
60 ~ScopedActivity() {
61 if (tracker_)
62 tracker_->RecordFinish(source_);
63 }
64
65 private:
66 ThreadActivityTracker* const tracker_;
67 const void* const source_;
68 };
69
70 // A ThreadActivityTracker runs on top of memory that is managed externally.
71 ThreadActivityTracker(void* base, size_t size);
72 virtual ~ThreadActivityTracker();
73
74 // Indicate that a method of the given (arbitrary) identifier has started.
75 void RecordStart(const void* source,
76 ActivityType activity,
77 intptr_t method,
78 uint64_t sequence);
79
80 // Indicate that a method of the given (arbitrary) identifier has finished.
81 void RecordFinish(const void* source);
82
83 // Gets a copy of the current stack contents. The return value is the current
84 // depth of the stack which may be greater than the number of StackEntry
85 // records returned. If so, the returned stack has the "base" of the stack
86 // with later entries omitted.
87 uint32_t CopyStack(std::vector<StackEntry>* stack);
88
89 // Returns whether the current data is valid or not. Fetching a copy of the
90 // stack will return nothing if the data is not valid.
91 bool is_valid() { return valid_; }
92
93 private:
94 friend class Iterator;
95
96 struct Header;
97
98 Header* const header_;
99 StackEntry* const stack_;
100 const uint32_t slots_;
101
102 bool valid_ = false;
103
104 base::ThreadChecker thread_checker_;
105
106 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker);
107 };
108
109 class BASE_EXPORT GlobalActivityTracker {
manzagop (departed) 2016/05/20 13:55:42 TrackerManager or some such to make it clearer thi
110 public:
111 class BASE_EXPORT ScopedThreadActivity
112 : public ThreadActivityTracker::ScopedActivity {
113 public:
114 ScopedThreadActivity(const void* source,
115 ThreadActivityTracker::ActivityType activity,
116 intptr_t method,
117 uint64_t sequence)
118 : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(),
119 source,
120 activity,
121 method,
122 sequence) {}
123
124 private:
125 static ThreadActivityTracker* GetOrCreateTracker() {
126 GlobalActivityTracker* global_tracker = Get();
127 if (!global_tracker)
128 return nullptr;
129 return global_tracker->GetOrCreateTrackerForCurrentThread();
130 }
131 };
132
133 ~GlobalActivityTracker();
134
135 static void CreateWithAllocator(
136 std::unique_ptr<PersistentMemoryAllocator> allocator,
137 size_t stack_memory);
138
139 static void CreateWithLocalMemory(size_t size,
140 uint64_t id,
141 StringPiece name,
142 size_t stack_memory);
143
144 static void CreateWithFile(const FilePath& file_path,
145 size_t size,
146 uint64_t id,
147 StringPiece name,
148 size_t stack_memory);
149
150 // Gets the global activity-tracker or null if none exists.
151 static GlobalActivityTracker* Get() { return g_tracker_; }
152
153 // Gets the thread's activity-tracker, assuming it already exists. This
154 // is inline for performance reasons. Ownership remains with the global
155 // tracker.
156 ThreadActivityTracker* GetTrackerForCurrentThread() {
157 void* tracker = this_thread_tracker_.Get();
158 DCHECK(tracker);
159 return reinterpret_cast<ThreadActivityTracker*>(tracker);
160 }
161
162 // Gets the thread's activity-tracker or creates one if none exists. This
163 // is inline for performance reasons. Ownership remains with the global
164 // tracker.
165 ThreadActivityTracker* GetOrCreateTrackerForCurrentThread() {
166 void* tracker = this_thread_tracker_.Get();
167 if (tracker)
168 return reinterpret_cast<ThreadActivityTracker*>(tracker);
169 return CreateTrackerForCurrentThread();
170 }
171
172 // Creates an activity-tracker for the current thread.
173 ThreadActivityTracker* CreateTrackerForCurrentThread();
174
175 // Releases the activity-tracker for the current thread (for testing only).
176 void ReleaseTrackerForCurrentThreadForTesting();
177
178 private:
179 class ManagedActivityTracker : public ThreadActivityTracker {
180 public:
181 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference,
182 void* base,
183 size_t size);
184 ~ManagedActivityTracker() override;
185
186 private:
187 const PersistentMemoryAllocator::Reference mem_reference_;
188 void* const mem_base_;
189 };
190
191 GlobalActivityTracker(std::unique_ptr<PersistentMemoryAllocator> allocator,
192 size_t stack_memory);
193
194 // Returns the memory used by an activity-tracker managed by this class.
195 void ReturnTrackerMemory(ManagedActivityTracker* tracker,
196 PersistentMemoryAllocator::Reference mem_reference,
197 void* mem_base);
198
199 static void OnTLSDestroy(void* value);
200
201 std::unique_ptr<PersistentMemoryAllocator> allocator_;
202 const size_t stack_memory_;
203
204 base::ThreadLocalStorage::Slot this_thread_tracker_;
205
206 Lock lock_;
207 std::set<ManagedActivityTracker*> thread_trackers_;
208 std::vector<PersistentMemoryAllocator::Reference> available_memories_;
209
210 static GlobalActivityTracker* g_tracker_;
211 };
212
213 class BASE_EXPORT ScopedTaskActivity
214 : public GlobalActivityTracker::ScopedThreadActivity {
215 public:
216 ScopedTaskActivity(const PendingTask& task);
217 };
218
219 } // namespace base
220
221 #endif // BASE_METRICS_ACTIVITY_TRACKER_H_
OLDNEW
« no previous file with comments | « base/debug/task_annotator.cc ('k') | base/metrics/activity_tracker.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698