OLD | NEW |
1 // Copyright (c) 2009, Google Inc. | 1 // Copyright (c) 2009, Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 20 matching lines...) Expand all Loading... |
31 // Author: Sanjay Ghemawat | 31 // Author: Sanjay Ghemawat |
32 // Nabeel Mian | 32 // Nabeel Mian |
33 // | 33 // |
34 // Implements management of profile timers and the corresponding signal handler. | 34 // Implements management of profile timers and the corresponding signal handler. |
35 | 35 |
36 #include "config.h" | 36 #include "config.h" |
37 #include "profile-handler.h" | 37 #include "profile-handler.h" |
38 | 38 |
39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) | 39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__)) |
40 | 40 |
| 41 #include <errno.h> |
41 #include <stdio.h> | 42 #include <stdio.h> |
42 #include <errno.h> | |
43 #include <sys/time.h> | 43 #include <sys/time.h> |
44 | 44 |
45 #include <list> | 45 #include <list> |
| 46 #include <map> |
46 #include <string> | 47 #include <string> |
47 | 48 |
48 #include "base/dynamic_annotations.h" | 49 #include "base/dynamic_annotations.h" |
49 #include "base/googleinit.h" | 50 #include "base/googleinit.h" |
50 #include "base/logging.h" | 51 #include "base/logging.h" |
51 #include "base/spinlock.h" | 52 #include "base/spinlock.h" |
52 #include "maybe_threads.h" | 53 #include "maybe_threads.h" |
53 | 54 |
54 using std::list; | 55 using std::list; |
| 56 using std::map; |
55 using std::string; | 57 using std::string; |
56 | 58 |
57 // This structure is used by ProfileHandlerRegisterCallback and | 59 // This structure is used by ProfileHandlerRegisterCallback and |
58 // ProfileHandlerUnregisterCallback as a handle to a registered callback. | 60 // ProfileHandlerUnregisterCallback as a handle to a registered callback. |
59 struct ProfileHandlerToken { | 61 struct ProfileHandlerToken { |
60 // Sets the callback and associated arg. | 62 // Sets the callback and associated arg. |
61 ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg) | 63 ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg) |
62 : callback(cb), | 64 : callback(cb), |
63 callback_arg(cb_arg) { | 65 callback_arg(cb_arg) { |
64 } | 66 } |
65 | 67 |
66 // Callback function to be invoked on receiving a profile timer interrupt. | 68 // Callback function to be invoked on receiving a profile timer interrupt. |
67 ProfileHandlerCallback callback; | 69 ProfileHandlerCallback callback; |
68 // Argument for the callback function. | 70 // Argument for the callback function. |
69 void* callback_arg; | 71 void* callback_arg; |
70 }; | 72 }; |
71 | 73 |
| 74 // Blocks a signal from being delivered to the current thread while the object |
| 75 // is alive. Restores previous state upon destruction. |
| 76 class ScopedSignalBlocker { |
| 77 public: |
| 78 ScopedSignalBlocker(int signo) { |
| 79 sigemptyset(&sig_set_); |
| 80 sigaddset(&sig_set_, signo); |
| 81 RAW_CHECK(sigprocmask(SIG_BLOCK, &sig_set_, NULL) == 0, |
| 82 "sigprocmask (block)"); |
| 83 } |
| 84 ~ScopedSignalBlocker() { |
| 85 RAW_CHECK(sigprocmask(SIG_UNBLOCK, &sig_set_, NULL) == 0, |
| 86 "sigprocmask (unblock)"); |
| 87 } |
| 88 |
| 89 private: |
| 90 sigset_t sig_set_; |
| 91 }; |
| 92 |
72 // This class manages profile timers and associated signal handler. This is a | 93 // This class manages profile timers and associated signal handler. This is a |
73 // a singleton. | 94 // a singleton. |
74 class ProfileHandler { | 95 class ProfileHandler { |
75 public: | 96 public: |
76 // Registers the current thread with the profile handler. On systems which | 97 // Registers the current thread with the profile handler. |
77 // have a separate interval timer for each thread, this function starts the | |
78 // timer for the current thread. | |
79 // | |
80 // The function also attempts to determine whether or not timers are shared by | |
81 // all threads in the process. (With LinuxThreads, and with NPTL on some | |
82 // Linux kernel versions, each thread has separate timers.) | |
83 // | |
84 // Prior to determining whether timers are shared, this function will | |
85 // unconditionally start the timer. However, if this function determines | |
86 // that timers are shared, then it will stop the timer if no callbacks are | |
87 // currently registered. | |
88 void RegisterThread(); | 98 void RegisterThread(); |
89 | 99 |
| 100 // Unregisters the current thread with the profile handler. |
| 101 void UnregisterThread(); |
| 102 |
90 // Registers a callback routine to receive profile timer ticks. The returned | 103 // Registers a callback routine to receive profile timer ticks. The returned |
91 // token is to be used when unregistering this callback and must not be | 104 // token is to be used when unregistering this callback and must not be |
92 // deleted by the caller. Registration of the first callback enables the | 105 // deleted by the caller. |
93 // SIGPROF handler (or SIGALRM if using ITIMER_REAL). | |
94 ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback, | 106 ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback, |
95 void* callback_arg); | 107 void* callback_arg); |
96 | 108 |
97 // Unregisters a previously registered callback. Expects the token returned | 109 // Unregisters a previously registered callback. Expects the token returned |
98 // by the corresponding RegisterCallback routine. Unregistering the last | 110 // by the corresponding RegisterCallback routine. |
99 // callback disables the SIGPROF handler (or SIGALRM if using ITIMER_REAL). | |
100 void UnregisterCallback(ProfileHandlerToken* token) | 111 void UnregisterCallback(ProfileHandlerToken* token) |
101 NO_THREAD_SAFETY_ANALYSIS; | 112 NO_THREAD_SAFETY_ANALYSIS; |
102 | 113 |
103 // Unregisters all the callbacks, stops the timer if shared, disables the | 114 // Unregisters all the callbacks and stops the timer(s). |
104 // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state. | |
105 void Reset(); | 115 void Reset(); |
106 | 116 |
107 // Gets the current state of profile handler. | 117 // Gets the current state of profile handler. |
108 void GetState(ProfileHandlerState* state); | 118 void GetState(ProfileHandlerState* state); |
109 | 119 |
110 // Initializes and returns the ProfileHandler singleton. | 120 // Initializes and returns the ProfileHandler singleton. |
111 static ProfileHandler* Instance(); | 121 static ProfileHandler* Instance(); |
112 | 122 |
113 private: | 123 private: |
114 ProfileHandler(); | 124 ProfileHandler(); |
115 ~ProfileHandler(); | 125 ~ProfileHandler(); |
116 | 126 |
117 // Largest allowed frequency. | 127 // Largest allowed frequency. |
118 static const int32 kMaxFrequency = 4000; | 128 static const int32 kMaxFrequency = 4000; |
119 // Default frequency. | 129 // Default frequency. |
120 static const int32 kDefaultFrequency = 100; | 130 static const int32 kDefaultFrequency = 100; |
121 | 131 |
122 // ProfileHandler singleton. | 132 // ProfileHandler singleton. |
123 static ProfileHandler* instance_; | 133 static ProfileHandler* instance_; |
124 | 134 |
125 // pthread_once_t for one time initialization of ProfileHandler singleton. | 135 // pthread_once_t for one time initialization of ProfileHandler singleton. |
126 static pthread_once_t once_; | 136 static pthread_once_t once_; |
127 | 137 |
| 138 #if defined(HAVE_TLS) |
| 139 // Timer state as configured previously. This bit is kept in |
| 140 // |registered_threads_| if TLS is not available. |
| 141 static __thread bool timer_running_; |
| 142 #endif |
| 143 |
128 // Initializes the ProfileHandler singleton via GoogleOnceInit. | 144 // Initializes the ProfileHandler singleton via GoogleOnceInit. |
129 static void Init(); | 145 static void Init(); |
130 | 146 |
131 // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received. | 147 // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received. |
132 int64 interrupts_ GUARDED_BY(signal_lock_); | 148 int64 interrupts_ GUARDED_BY(signal_lock_); |
133 | 149 |
134 // SIGPROF/SIGALRM interrupt frequency, read-only after construction. | 150 // SIGPROF/SIGALRM interrupt frequency, read-only after construction. |
135 int32 frequency_; | 151 int32 frequency_; |
136 | 152 |
137 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM) | 153 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM) |
138 int timer_type_; | 154 int timer_type_; |
139 | 155 |
140 // Counts the number of callbacks registered. | 156 // Counts the number of callbacks registered. |
141 int32 callback_count_ GUARDED_BY(control_lock_); | 157 int32 callback_count_ GUARDED_BY(control_lock_); |
142 | 158 |
143 // Is profiling allowed at all? | 159 // Is profiling allowed at all? |
144 bool allowed_; | 160 bool allowed_; |
145 | 161 |
146 // Whether or not the threading system provides interval timers that are | |
147 // shared by all threads in a process. | |
148 enum { | |
149 // No timer initialization attempted yet. | |
150 TIMERS_UNTOUCHED, | |
151 // First thread has registered and set timer. | |
152 TIMERS_ONE_SET, | |
153 // Timers are shared by all threads. | |
154 TIMERS_SHARED, | |
155 // Timers are separate in each thread. | |
156 TIMERS_SEPARATE | |
157 } timer_sharing_ GUARDED_BY(control_lock_); | |
158 | |
159 // This lock serializes the registration of threads and protects the | 162 // This lock serializes the registration of threads and protects the |
160 // callbacks_ list below. | 163 // callbacks_ list below. |
161 // Locking order: | 164 // Locking order: |
162 // In the context of a signal handler, acquire signal_lock_ to walk the | 165 // In the context of a signal handler, acquire signal_lock_ to walk the |
163 // callback list. Otherwise, acquire control_lock_, disable the signal | 166 // callback list. Otherwise, acquire control_lock_, disable the signal |
164 // handler and then acquire signal_lock_. | 167 // handler and then acquire signal_lock_. |
165 SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_); | 168 SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_); |
166 SpinLock signal_lock_; | 169 SpinLock signal_lock_; |
167 | 170 |
| 171 // Set of threads registered through RegisterThread. This is consulted |
| 172 // whenever timers are switched on or off to post a signal to these threads |
| 173 // so they can arm their timers. Locking rules as for |callbacks_| below. If |
| 174 // TLS is not available, this map is also used to keep the thread's timer |
| 175 // state. |
| 176 map<pthread_t, bool> registered_threads_ GUARDED_BY(signal_lock_); |
| 177 |
168 // Holds the list of registered callbacks. We expect the list to be pretty | 178 // Holds the list of registered callbacks. We expect the list to be pretty |
169 // small. Currently, the cpu profiler (base/profiler) and thread module | 179 // small. Currently, the cpu profiler (base/profiler) and thread module |
170 // (base/thread.h) are the only two components registering callbacks. | 180 // (base/thread.h) are the only two components registering callbacks. |
171 // Following are the locking requirements for callbacks_: | 181 // Following are the locking requirements for callbacks_: |
172 // For read-write access outside the SIGPROF handler: | 182 // For read-write access outside the SIGPROF handler: |
173 // - Acquire control_lock_ | 183 // - Acquire control_lock_ |
174 // - Disable SIGPROF handler. | 184 // - Disable SIGPROF handler. |
175 // - Acquire signal_lock_ | 185 // - Acquire signal_lock_ |
176 // For read-only access in the context of SIGPROF handler | 186 // For read-only access in the context of SIGPROF handler |
177 // (Read-write access is *not allowed* in the SIGPROF handler) | 187 // (Read-write access is *not allowed* in the SIGPROF handler) |
178 // - Acquire signal_lock_ | 188 // - Acquire signal_lock_ |
179 // For read-only access outside SIGPROF handler: | 189 // For read-only access outside SIGPROF handler: |
180 // - Acquire control_lock_ | 190 // - Acquire control_lock_ |
181 typedef list<ProfileHandlerToken*> CallbackList; | 191 typedef list<ProfileHandlerToken*> CallbackList; |
182 typedef CallbackList::iterator CallbackIterator; | 192 typedef CallbackList::iterator CallbackIterator; |
183 CallbackList callbacks_ GUARDED_BY(signal_lock_); | 193 CallbackList callbacks_ GUARDED_BY(signal_lock_); |
184 | 194 |
185 // Starts the interval timer. If the thread library shares timers between | 195 // Returns the signal to be used with |timer_type_| (SIGPROF or SIGALARM). |
186 // threads, this function starts the shared timer. Otherwise, this will start | 196 int signal_number() { |
187 // the timer in the current thread. | 197 return (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); |
188 void StartTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); | 198 } |
189 | 199 |
190 // Stops the interval timer. If the thread library shares timers between | 200 // Starts or stops the interval timer(s). In case of non-shared timers, this |
191 // threads, this fucntion stops the shared timer. Otherwise, this will stop | 201 // will post a signal to all registered threads, causing them to arm their |
192 // the timer in the current thread. | 202 // timers. |
193 void StopTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); | 203 void UpdateTimers(bool enable) EXCLUSIVE_LOCKS_REQUIRED(signal_lock_); |
194 | 204 |
195 // Returns true if the profile interval timer is enabled in the current | 205 // Configures the timer. If |frequency| is 0, the timer will be disabled. |
196 // thread. This actually checks the kernel's interval timer setting. (It is | 206 void SetupTimer(int32 frequency) EXCLUSIVE_LOCKS_REQUIRED(signal_lock_); |
197 // used to detect whether timers are shared or separate.) | |
198 bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); | |
199 | |
200 // Sets the timer interrupt signal handler. | |
201 void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); | |
202 | |
203 // Disables (ignores) the timer interrupt signal. | |
204 void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_); | |
205 | 207 |
206 // Returns true if the handler is not being used by something else. | 208 // Returns true if the handler is not being used by something else. |
207 // This checks the kernel's signal handler table. | 209 // This checks the kernel's signal handler table. |
208 bool IsSignalHandlerAvailable(); | 210 bool IsSignalHandlerAvailable(); |
209 | 211 |
210 // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks
. | 212 // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks
. |
211 static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext); | 213 static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext); |
212 | 214 |
213 DISALLOW_COPY_AND_ASSIGN(ProfileHandler); | 215 DISALLOW_COPY_AND_ASSIGN(ProfileHandler); |
214 }; | 216 }; |
215 | 217 |
216 ProfileHandler* ProfileHandler::instance_ = NULL; | 218 ProfileHandler* ProfileHandler::instance_ = NULL; |
217 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT; | 219 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT; |
218 | 220 |
| 221 #if defined(HAVE_TLS) |
| 222 bool __thread ProfileHandler::timer_running_ = false; |
| 223 #endif |
| 224 |
219 const int32 ProfileHandler::kMaxFrequency; | 225 const int32 ProfileHandler::kMaxFrequency; |
220 const int32 ProfileHandler::kDefaultFrequency; | 226 const int32 ProfileHandler::kDefaultFrequency; |
221 | 227 |
222 // If we are LD_PRELOAD-ed against a non-pthreads app, then | 228 // If we are LD_PRELOAD-ed against a non-pthreads app, then pthread_* functions |
223 // pthread_once won't be defined. We declare it here, for that | 229 // won't be defined. We declare them here, for that case (with weak linkage) |
224 // case (with weak linkage) which will cause the non-definition to | 230 // which will cause the non-definition to resolve to NULL. We can then check |
225 // resolve to NULL. We can then check for NULL or not in Instance. | 231 // for NULL or not in Instance. |
226 extern "C" int pthread_once(pthread_once_t *, void (*)(void)) | 232 extern "C" int pthread_once(pthread_once_t *, void (*)(void)) |
227 ATTRIBUTE_WEAK; | 233 ATTRIBUTE_WEAK; |
| 234 extern "C" int pthread_kill(pthread_t thread_id, int signo) |
| 235 ATTRIBUTE_WEAK; |
228 | 236 |
229 void ProfileHandler::Init() { | 237 void ProfileHandler::Init() { |
230 instance_ = new ProfileHandler(); | 238 instance_ = new ProfileHandler(); |
231 } | 239 } |
232 | 240 |
233 ProfileHandler* ProfileHandler::Instance() { | 241 ProfileHandler* ProfileHandler::Instance() { |
234 if (pthread_once) { | 242 if (pthread_once) { |
235 pthread_once(&once_, Init); | 243 pthread_once(&once_, Init); |
236 } | 244 } |
237 if (instance_ == NULL) { | 245 if (instance_ == NULL) { |
238 // This will be true on systems that don't link in pthreads, | 246 // This will be true on systems that don't link in pthreads, |
239 // including on FreeBSD where pthread_once has a non-zero address | 247 // including on FreeBSD where pthread_once has a non-zero address |
240 // (but doesn't do anything) even when pthreads isn't linked in. | 248 // (but doesn't do anything) even when pthreads isn't linked in. |
241 Init(); | 249 Init(); |
242 assert(instance_ != NULL); | 250 assert(instance_ != NULL); |
243 } | 251 } |
244 return instance_; | 252 return instance_; |
245 } | 253 } |
246 | 254 |
247 ProfileHandler::ProfileHandler() | 255 ProfileHandler::ProfileHandler() |
248 : interrupts_(0), | 256 : interrupts_(0), |
249 callback_count_(0), | 257 callback_count_(0), |
250 allowed_(true), | 258 allowed_(true) { |
251 timer_sharing_(TIMERS_UNTOUCHED) { | |
252 SpinLockHolder cl(&control_lock_); | 259 SpinLockHolder cl(&control_lock_); |
253 | 260 |
254 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); | 261 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF); |
255 | 262 |
256 // Get frequency of interrupts (if specified) | 263 // Get frequency of interrupts (if specified) |
257 char junk; | 264 char junk; |
258 const char* fr = getenv("CPUPROFILE_FREQUENCY"); | 265 const char* fr = getenv("CPUPROFILE_FREQUENCY"); |
259 if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) && | 266 if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) && |
260 (frequency_ > 0)) { | 267 (frequency_ > 0)) { |
261 // Limit to kMaxFrequency | 268 // Limit to kMaxFrequency |
262 frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_; | 269 frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_; |
263 } else { | 270 } else { |
264 frequency_ = kDefaultFrequency; | 271 frequency_ = kDefaultFrequency; |
265 } | 272 } |
266 | 273 |
267 if (!allowed_) { | 274 if (!allowed_) { |
268 return; | 275 return; |
269 } | 276 } |
270 | 277 |
271 // If something else is using the signal handler, | 278 // If something else is using the signal handler, |
272 // assume it has priority over us and stop. | 279 // assume it has priority over us and stop. |
273 if (!IsSignalHandlerAvailable()) { | 280 if (!IsSignalHandlerAvailable()) { |
274 RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.", | 281 RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.", |
275 timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF"); | 282 signal_number()); |
276 allowed_ = false; | 283 allowed_ = false; |
277 return; | 284 return; |
278 } | 285 } |
279 | 286 |
280 // Ignore signals until we decide to turn profiling on. (Paranoia; | 287 // Install the signal handler. |
281 // should already be ignored.) | 288 struct sigaction sa; |
282 DisableHandler(); | 289 sa.sa_sigaction = SignalHandler; |
| 290 sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| 291 sigemptyset(&sa.sa_mask); |
| 292 RAW_CHECK(sigaction(signal_number(), &sa, NULL) == 0, "sigprof (enable)"); |
283 } | 293 } |
284 | 294 |
285 ProfileHandler::~ProfileHandler() { | 295 ProfileHandler::~ProfileHandler() { |
286 Reset(); | 296 Reset(); |
287 } | 297 } |
288 | 298 |
289 void ProfileHandler::RegisterThread() { | 299 void ProfileHandler::RegisterThread() { |
290 SpinLockHolder cl(&control_lock_); | 300 SpinLockHolder cl(&control_lock_); |
291 | 301 |
292 if (!allowed_) { | 302 if (!allowed_) { |
293 return; | 303 return; |
294 } | 304 } |
295 | 305 |
296 // We try to detect whether timers are being shared by setting a | 306 // Record the thread identifier and start the timer if profiling is on. |
297 // timer in the first call to this function, then checking whether | 307 ScopedSignalBlocker block(signal_number()); |
298 // it's set in the second call. | 308 SpinLockHolder sl(&signal_lock_); |
299 // | 309 registered_threads_[pthread_self()] = false; |
300 // Note that this detection method requires that the first two calls | 310 SetupTimer(callback_count_ > 0 ? frequency_ : 0); |
301 // to RegisterThread must be made from different threads. (Subsequent | 311 } |
302 // calls will see timer_sharing_ set to either TIMERS_SEPARATE or | 312 |
303 // TIMERS_SHARED, and won't try to detect the timer sharing type.) | 313 void ProfileHandler::UnregisterThread() { |
304 // | 314 ScopedSignalBlocker block(signal_number()); |
305 // Also note that if timer settings were inherited across new thread | 315 SpinLockHolder sl(&signal_lock_); |
306 // creation but *not* shared, this approach wouldn't work. That's | 316 registered_threads_.erase(pthread_self()); |
307 // not an issue for any Linux threading implementation, and should | |
308 // not be a problem for a POSIX-compliant threads implementation. | |
309 switch (timer_sharing_) { | |
310 case TIMERS_UNTOUCHED: | |
311 StartTimer(); | |
312 timer_sharing_ = TIMERS_ONE_SET; | |
313 break; | |
314 case TIMERS_ONE_SET: | |
315 // If the timer is running, that means that the main thread's | |
316 // timer setup is seen in this (second) thread -- and therefore | |
317 // that timers are shared. | |
318 if (IsTimerRunning()) { | |
319 timer_sharing_ = TIMERS_SHARED; | |
320 // If callback is already registered, we have to keep the timer | |
321 // running. If not, we disable the timer here. | |
322 if (callback_count_ == 0) { | |
323 StopTimer(); | |
324 } | |
325 } else { | |
326 timer_sharing_ = TIMERS_SEPARATE; | |
327 StartTimer(); | |
328 } | |
329 break; | |
330 case TIMERS_SHARED: | |
331 // Nothing needed. | |
332 break; | |
333 case TIMERS_SEPARATE: | |
334 StartTimer(); | |
335 break; | |
336 } | |
337 } | 317 } |
338 | 318 |
339 ProfileHandlerToken* ProfileHandler::RegisterCallback( | 319 ProfileHandlerToken* ProfileHandler::RegisterCallback( |
340 ProfileHandlerCallback callback, void* callback_arg) { | 320 ProfileHandlerCallback callback, void* callback_arg) { |
341 | 321 |
342 ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg); | 322 ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg); |
343 | 323 |
344 SpinLockHolder cl(&control_lock_); | 324 SpinLockHolder cl(&control_lock_); |
345 DisableHandler(); | |
346 { | 325 { |
| 326 ScopedSignalBlocker block(signal_number()); |
347 SpinLockHolder sl(&signal_lock_); | 327 SpinLockHolder sl(&signal_lock_); |
348 callbacks_.push_back(token); | 328 callbacks_.push_back(token); |
| 329 ++callback_count_; |
| 330 UpdateTimers(true); |
349 } | 331 } |
350 // Start the timer if timer is shared and this is a first callback. | |
351 if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) { | |
352 StartTimer(); | |
353 } | |
354 ++callback_count_; | |
355 EnableHandler(); | |
356 return token; | 332 return token; |
357 } | 333 } |
358 | 334 |
359 void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) { | 335 void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) { |
360 SpinLockHolder cl(&control_lock_); | 336 SpinLockHolder cl(&control_lock_); |
361 for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end(); | 337 for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end(); |
362 ++it) { | 338 ++it) { |
363 if ((*it) == token) { | 339 if ((*it) == token) { |
364 RAW_CHECK(callback_count_ > 0, "Invalid callback count"); | 340 RAW_CHECK(callback_count_ > 0, "Invalid callback count"); |
365 DisableHandler(); | |
366 { | 341 { |
| 342 ScopedSignalBlocker block(signal_number()); |
367 SpinLockHolder sl(&signal_lock_); | 343 SpinLockHolder sl(&signal_lock_); |
368 delete *it; | 344 delete *it; |
369 callbacks_.erase(it); | 345 callbacks_.erase(it); |
370 } | 346 --callback_count_; |
371 --callback_count_; | 347 if (callback_count_ == 0) |
372 if (callback_count_ > 0) { | 348 UpdateTimers(false); |
373 EnableHandler(); | |
374 } else if (timer_sharing_ == TIMERS_SHARED) { | |
375 StopTimer(); | |
376 } | 349 } |
377 return; | 350 return; |
378 } | 351 } |
379 } | 352 } |
380 // Unknown token. | 353 // Unknown token. |
381 RAW_LOG(FATAL, "Invalid token"); | 354 RAW_LOG(FATAL, "Invalid token"); |
382 } | 355 } |
383 | 356 |
384 void ProfileHandler::Reset() { | 357 void ProfileHandler::Reset() { |
385 SpinLockHolder cl(&control_lock_); | 358 SpinLockHolder cl(&control_lock_); |
386 DisableHandler(); | |
387 { | 359 { |
| 360 ScopedSignalBlocker block(signal_number()); |
388 SpinLockHolder sl(&signal_lock_); | 361 SpinLockHolder sl(&signal_lock_); |
389 CallbackIterator it = callbacks_.begin(); | 362 CallbackIterator it = callbacks_.begin(); |
390 while (it != callbacks_.end()) { | 363 while (it != callbacks_.end()) { |
391 CallbackIterator tmp = it; | 364 CallbackIterator tmp = it; |
392 ++it; | 365 ++it; |
393 delete *tmp; | 366 delete *tmp; |
394 callbacks_.erase(tmp); | 367 callbacks_.erase(tmp); |
395 } | 368 } |
| 369 callback_count_ = 0; |
| 370 UpdateTimers(false); |
396 } | 371 } |
397 callback_count_ = 0; | |
398 if (timer_sharing_ == TIMERS_SHARED) { | |
399 StopTimer(); | |
400 } | |
401 timer_sharing_ = TIMERS_UNTOUCHED; | |
402 } | 372 } |
403 | 373 |
404 void ProfileHandler::GetState(ProfileHandlerState* state) { | 374 void ProfileHandler::GetState(ProfileHandlerState* state) { |
405 SpinLockHolder cl(&control_lock_); | 375 SpinLockHolder cl(&control_lock_); |
406 DisableHandler(); | |
407 { | 376 { |
| 377 ScopedSignalBlocker block(signal_number()); |
408 SpinLockHolder sl(&signal_lock_); // Protects interrupts_. | 378 SpinLockHolder sl(&signal_lock_); // Protects interrupts_. |
409 state->interrupts = interrupts_; | 379 state->interrupts = interrupts_; |
410 } | 380 } |
411 if (callback_count_ > 0) { | |
412 EnableHandler(); | |
413 } | |
414 state->frequency = frequency_; | 381 state->frequency = frequency_; |
415 state->callback_count = callback_count_; | 382 state->callback_count = callback_count_; |
416 state->allowed = allowed_; | 383 state->allowed = allowed_; |
417 } | 384 } |
418 | 385 |
419 void ProfileHandler::StartTimer() { | 386 void ProfileHandler::UpdateTimers(bool enabled) { |
420 if (!allowed_) { | 387 if (!allowed_) { |
421 return; | 388 return; |
422 } | 389 } |
| 390 SetupTimer(enabled ? frequency_ : 0); |
| 391 |
| 392 // Tell other threads to start their timers. |
| 393 for (map<pthread_t, bool>::const_iterator thread(registered_threads_.begin()); |
| 394 thread != registered_threads_.end(); |
| 395 ++thread) { |
| 396 if (thread->first != pthread_self() && pthread_kill) { |
| 397 int err = pthread_kill(thread->first, signal_number()); |
| 398 if (err == ESRCH) { |
| 399 // Thread exited. |
| 400 registered_threads_.erase(thread->first); |
| 401 } else { |
| 402 RAW_CHECK(err == 0, "pthread_kill"); |
| 403 } |
| 404 } |
| 405 } |
| 406 } |
| 407 |
| 408 void ProfileHandler::SetupTimer(int32 frequency) { |
| 409 bool enable = (frequency > 0); |
| 410 #if defined(HAVE_TLS) |
| 411 bool& timer_running = timer_running_; |
| 412 #else |
| 413 bool& timer_running = registered_threads_[pthread_self()]; |
| 414 #endif |
| 415 if (enable == timer_running) |
| 416 return; |
423 struct itimerval timer; | 417 struct itimerval timer; |
424 timer.it_interval.tv_sec = 0; | 418 timer.it_interval.tv_sec = 0; |
425 timer.it_interval.tv_usec = 1000000 / frequency_; | 419 timer.it_interval.tv_usec = (enable ? (1000000 / frequency) : 0); |
426 timer.it_value = timer.it_interval; | 420 timer.it_value = timer.it_interval; |
427 setitimer(timer_type_, &timer, 0); | 421 setitimer(timer_type_, &timer, 0); |
428 } | 422 timer_running = enable; |
429 | |
430 void ProfileHandler::StopTimer() { | |
431 if (!allowed_) { | |
432 return; | |
433 } | |
434 struct itimerval timer; | |
435 memset(&timer, 0, sizeof timer); | |
436 setitimer(timer_type_, &timer, 0); | |
437 } | |
438 | |
439 bool ProfileHandler::IsTimerRunning() { | |
440 if (!allowed_) { | |
441 return false; | |
442 } | |
443 struct itimerval current_timer; | |
444 RAW_CHECK(0 == getitimer(timer_type_, ¤t_timer), "getitimer"); | |
445 return (current_timer.it_value.tv_sec != 0 || | |
446 current_timer.it_value.tv_usec != 0); | |
447 } | |
448 | |
449 void ProfileHandler::EnableHandler() { | |
450 if (!allowed_) { | |
451 return; | |
452 } | |
453 struct sigaction sa; | |
454 sa.sa_sigaction = SignalHandler; | |
455 sa.sa_flags = SA_RESTART | SA_SIGINFO; | |
456 sigemptyset(&sa.sa_mask); | |
457 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); | |
458 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)"); | |
459 } | |
460 | |
461 void ProfileHandler::DisableHandler() { | |
462 if (!allowed_) { | |
463 return; | |
464 } | |
465 struct sigaction sa; | |
466 sa.sa_handler = SIG_IGN; | |
467 sa.sa_flags = SA_RESTART; | |
468 sigemptyset(&sa.sa_mask); | |
469 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); | |
470 RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)"); | |
471 } | 423 } |
472 | 424 |
473 bool ProfileHandler::IsSignalHandlerAvailable() { | 425 bool ProfileHandler::IsSignalHandlerAvailable() { |
474 struct sigaction sa; | 426 struct sigaction sa; |
475 const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM); | 427 RAW_CHECK(sigaction(signal_number(), NULL, &sa) == 0, |
476 RAW_CHECK(sigaction(signal_number, NULL, &sa) == 0, "is-signal-handler avail")
; | 428 "is-signal-handler avail"); |
477 | 429 |
478 // We only take over the handler if the current one is unset. | 430 // We only take over the handler if the current one is unset. |
479 // It must be SIG_IGN or SIG_DFL, not some other function. | 431 // It must be SIG_IGN or SIG_DFL, not some other function. |
480 // SIG_IGN must be allowed because when profiling is allowed but | 432 // SIG_IGN must be allowed because when profiling is allowed but |
481 // not actively in use, this code keeps the handler set to SIG_IGN. | 433 // not actively in use, this code keeps the handler set to SIG_IGN. |
482 // That setting will be inherited across fork+exec. In order for | 434 // That setting will be inherited across fork+exec. In order for |
483 // any child to be able to use profiling, SIG_IGN must be treated | 435 // any child to be able to use profiling, SIG_IGN must be treated |
484 // as available. | 436 // as available. |
485 return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL; | 437 return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL; |
486 } | 438 } |
487 | 439 |
488 void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) { | 440 void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) { |
489 int saved_errno = errno; | 441 int saved_errno = errno; |
490 // At this moment, instance_ must be initialized because the handler is | 442 // At this moment, instance_ must be initialized because the handler is |
491 // enabled in RegisterThread or RegisterCallback only after | 443 // enabled in RegisterThread or RegisterCallback only after |
492 // ProfileHandler::Instance runs. | 444 // ProfileHandler::Instance runs. |
493 ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_); | 445 ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_); |
494 RAW_CHECK(instance != NULL, "ProfileHandler is not initialized"); | 446 RAW_CHECK(instance != NULL, "ProfileHandler is not initialized"); |
495 { | 447 { |
496 SpinLockHolder sl(&instance->signal_lock_); | 448 SpinLockHolder sl(&instance->signal_lock_); |
497 ++instance->interrupts_; | 449 ++instance->interrupts_; |
| 450 // Enable/Disable the timer if necessary. |
| 451 instance->SetupTimer( |
| 452 instance->callbacks_.empty() ? 0 : instance->frequency_); |
498 for (CallbackIterator it = instance->callbacks_.begin(); | 453 for (CallbackIterator it = instance->callbacks_.begin(); |
499 it != instance->callbacks_.end(); | 454 it != instance->callbacks_.end(); |
500 ++it) { | 455 ++it) { |
501 (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg); | 456 (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg); |
502 } | 457 } |
503 } | 458 } |
504 errno = saved_errno; | 459 errno = saved_errno; |
505 } | 460 } |
506 | 461 |
507 // This module initializer registers the main thread, so it must be | 462 // This module initializer registers the main thread, so it must be |
508 // executed in the context of the main thread. | 463 // executed in the context of the main thread. |
509 REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread()); | 464 REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread()); |
510 | 465 |
511 extern "C" void ProfileHandlerRegisterThread() { | 466 extern "C" void ProfileHandlerRegisterThread() { |
512 ProfileHandler::Instance()->RegisterThread(); | 467 ProfileHandler::Instance()->RegisterThread(); |
513 } | 468 } |
514 | 469 |
| 470 extern "C" void ProfileHandlerUnregisterThread() { |
| 471 ProfileHandler::Instance()->UnregisterThread(); |
| 472 } |
| 473 |
515 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback( | 474 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback( |
516 ProfileHandlerCallback callback, void* callback_arg) { | 475 ProfileHandlerCallback callback, void* callback_arg) { |
517 return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg); | 476 return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg); |
518 } | 477 } |
519 | 478 |
520 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { | 479 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { |
521 ProfileHandler::Instance()->UnregisterCallback(token); | 480 ProfileHandler::Instance()->UnregisterCallback(token); |
522 } | 481 } |
523 | 482 |
524 extern "C" void ProfileHandlerReset() { | 483 extern "C" void ProfileHandlerReset() { |
525 return ProfileHandler::Instance()->Reset(); | 484 return ProfileHandler::Instance()->Reset(); |
526 } | 485 } |
527 | 486 |
528 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { | 487 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { |
529 ProfileHandler::Instance()->GetState(state); | 488 ProfileHandler::Instance()->GetState(state); |
530 } | 489 } |
531 | 490 |
532 #else // OS_CYGWIN | 491 #else // OS_CYGWIN |
533 | 492 |
534 // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't | 493 // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't |
535 // work as well for profiling, and also interferes with alarm(). Because of | 494 // work as well for profiling, and also interferes with alarm(). Because of |
536 // these issues, unless a specific need is identified, profiler support is | 495 // these issues, unless a specific need is identified, profiler support is |
537 // disabled under Cygwin. | 496 // disabled under Cygwin. |
538 extern "C" void ProfileHandlerRegisterThread() { | 497 extern "C" void ProfileHandlerRegisterThread() { |
539 } | 498 } |
540 | 499 |
| 500 extern "C" void ProfileHandlerUnregisterThread() { |
| 501 } |
| 502 |
541 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback( | 503 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback( |
542 ProfileHandlerCallback callback, void* callback_arg) { | 504 ProfileHandlerCallback callback, void* callback_arg) { |
543 return NULL; | 505 return NULL; |
544 } | 506 } |
545 | 507 |
546 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { | 508 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) { |
547 } | 509 } |
548 | 510 |
549 extern "C" void ProfileHandlerReset() { | 511 extern "C" void ProfileHandlerReset() { |
550 } | 512 } |
551 | 513 |
552 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { | 514 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) { |
553 } | 515 } |
554 | 516 |
555 #endif // OS_CYGWIN | 517 #endif // OS_CYGWIN |
OLD | NEW |