cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / tools / cygprofile / cygprofile.h
blob4ff13766bfd42ba1bac966af9694eada4a8539e8
1 // Copyright 2014 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 // Tool to log the execution of the process (Chrome). Writes logs containing
6 // time and address of the callback being called for the first time.
7 //
8 // For performance reasons logs are buffered. Every thread has its own buffer
9 // and log file so the contention between threads is minimal. As a side-effect,
10 // functions called might be mentioned in many thread logs.
12 // A special thread is created in the process to periodically flush logs for all
13 // threads in case the thread had stopped before flushing its logs.
15 // Also note that the instrumentation code is self-activated. It begins to
16 // record the log data when it is called first, including the run-time startup.
17 // Have it in mind when modifying it, in particular do not use global objects
18 // with constructors as they are called during startup (too late for us).
20 #ifndef TOOLS_CYGPROFILE_CYGPROFILE_H_
21 #define TOOLS_CYGPROFILE_CYGPROFILE_H_
23 #include <vector>
25 #include <sys/time.h>
26 #include <sys/types.h>
28 #include "base/callback.h"
29 #include "base/containers/hash_tables.h"
30 #include "base/macros.h"
31 #include "base/memory/scoped_ptr.h"
32 #include "base/synchronization/lock.h"
33 #include "build/build_config.h"
35 #if !defined(OS_ANDROID)
36 // This is only supported on Android thanks to the fact that on Android
37 // processes (other than the system's zygote) don't fork.
39 // To make cygprofile truly work (i.e. without any deadlock) on Chrome
40 // platforms that use fork(), cygprofile.cc should be written in a way that
41 // guarantees that:
42 // - No lock is acquired by a foreign thread during fork(). In particular this
43 // means that cygprofile.cc should not perform any heap allocation (since heap
44 // allocators, including TCMalloc generally use locks).
45 // - Only cygprofile.cc uses pthread_atfork() in the whole process. Unlike POSIX
46 // signals, pthread_atfork() doesn't provide a way to install multiple handlers.
47 // Calling pthread_atfork() in cygprofile.cc would override any handler that
48 // could have been installed previously.
50 // Chrome happens to violate the first requirement at least once by having its
51 // process launcher thread fork. However the child process in that case, when
52 // it's not instrumented with cygprofile, directly calls exec(). This is safe
53 // since the child process doesn't try to release a lock acquired by another
54 // thread in the parent process which would lead to a deadlock. This problem was
55 // actually observed by trying to port the current version of cygprofile.cc to
56 // Linux.
57 #error This is only supported on Android.
58 #endif
60 // The following is only exposed for testing.
61 namespace cygprofile {
63 class Thread;
65 // Single log entry recorded for each function call.
66 struct LogEntry {
67 LogEntry(const void* address);
69 const timespec time;
70 const pid_t pid;
71 const pid_t tid;
72 const void* const address;
75 // Per-thread function calls log.
76 class ThreadLog {
77 public:
78 // Callback invoked for flushing that can be provided for testing.
79 typedef base::Callback<void (std::vector<LogEntry>*)> FlushCallback;
81 ThreadLog();
83 // Used for testing.
84 ThreadLog(const FlushCallback& flush_callback);
86 ~ThreadLog();
88 // Must only be called from the thread this ThreadLog instance is watching.
89 void AddEntry(void* address);
91 // Can be called from any thread.
92 void TakeEntries(std::vector<LogEntry>* output);
94 // Flushes the provided vector of entries to a file and clears it. Note that
95 // this can be called from any thread.
96 void Flush(std::vector<LogEntry>* entries) const;
98 private:
99 // Default implementation (that can be overridden for testing) of the method
100 // above.
101 void FlushInternal(std::vector<LogEntry>* entries) const;
103 // Thread identifier as Linux kernel shows it. LWP (light-weight process) is
104 // a unique ID of the thread in the system, unlike pthread_self() which is the
105 // same for fork()-ed threads.
106 const pid_t tid_;
108 // Current thread is inside the instrumentation routine.
109 bool in_use_;
111 // Callback used to flush entries.
112 const FlushCallback flush_callback_;
114 // Keeps track of all functions that have been logged on this thread so we do
115 // not record duplicates.
116 base::hash_set<void*> called_functions_;
118 // A lock that guards |entries_| usage between per-thread instrumentation
119 // routine and timer flush callback. So the contention could happen only
120 // during the flush, every 15 secs.
121 base::Lock lock_;
123 std::vector<LogEntry> entries_;
125 DISALLOW_COPY_AND_ASSIGN(ThreadLog);
128 // Manages a list of per-thread logs.
129 class ThreadLogsManager {
130 public:
131 ThreadLogsManager();
133 // Used for testing. The provided callbacks are used for testing to
134 // synchronize the internal thread with the unit test running on the main
135 // thread.
136 ThreadLogsManager(const base::Closure& wait_callback,
137 const base::Closure& notify_callback);
139 ~ThreadLogsManager();
141 // Can be called from any thread.
142 void AddLog(scoped_ptr<ThreadLog> new_log);
144 private:
145 void StartInternalFlushThread_Locked();
147 // Flush thread's entry point.
148 void FlushAllLogsOnFlushThread();
150 // Used to make the internal thread sleep before each flush iteration.
151 const base::Closure wait_callback_;
152 // Used to trigger a notification when a flush happened on the internal
153 // thread.
154 const base::Closure notify_callback_;
156 // Protects the state below.
157 base::Lock lock_;
158 scoped_ptr<Thread> flush_thread_;
159 std::vector<ThreadLog*> logs_;
161 DISALLOW_COPY_AND_ASSIGN(ThreadLogsManager);
164 } // namespace cygprofile
166 #endif // TOOLS_CYGPROFILE_CYGPROFILE_H_