1 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2 // Copyright (c) 2009, Google Inc.
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // ---
32 // Author: Sanjay Ghemawat
33 // Nabeel Mian
34 //
35 // Implements management of profile timers and the corresponding signal handler.
36
37 #include "config.h"
38 #include "profile-handler.h"
39
40 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
41
42 #include <stdio.h>
43 #include <errno.h>
44 #include <sys/time.h>
45
46 #include <list>
47 #include <string>
48
49 #if HAVE_LINUX_SIGEV_THREAD_ID
50 // for timer_{create,settime} and associated typedefs & constants
51 #include <time.h>
52 // for sys_gettid
53 #include "base/linux_syscall_support.h"
54 // for perftools_pthread_key_create
55 #include "maybe_threads.h"
56 #endif
57
58 #include "base/dynamic_annotations.h"
59 #include "base/googleinit.h"
60 #include "base/logging.h"
61 #include "base/spinlock.h"
62 #include "maybe_threads.h"
63
64 using std::list;
65 using std::string;
66
67 // This structure is used by ProfileHandlerRegisterCallback and
68 // ProfileHandlerUnregisterCallback as a handle to a registered callback.
69 struct ProfileHandlerToken {
70 // Sets the callback and associated arg.
ProfileHandlerTokenProfileHandlerToken71 ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg)
72 : callback(cb),
73 callback_arg(cb_arg) {
74 }
75
76 // Callback function to be invoked on receiving a profile timer interrupt.
77 ProfileHandlerCallback callback;
78 // Argument for the callback function.
79 void* callback_arg;
80 };
81
82 // Blocks a signal from being delivered to the current thread while the object
83 // is alive. Unblocks it upon destruction.
84 class ScopedSignalBlocker {
85 public:
ScopedSignalBlocker(int signo)86 ScopedSignalBlocker(int signo) {
87 sigemptyset(&sig_set_);
88 sigaddset(&sig_set_, signo);
89 RAW_CHECK(sigprocmask(SIG_BLOCK, &sig_set_, NULL) == 0,
90 "sigprocmask (block)");
91 }
~ScopedSignalBlocker()92 ~ScopedSignalBlocker() {
93 RAW_CHECK(sigprocmask(SIG_UNBLOCK, &sig_set_, NULL) == 0,
94 "sigprocmask (unblock)");
95 }
96
97 private:
98 sigset_t sig_set_;
99 };
100
101 // This class manages profile timers and associated signal handler. This is a
102 // a singleton.
103 class ProfileHandler {
104 public:
105 // Registers the current thread with the profile handler.
106 void RegisterThread();
107
108 // Registers a callback routine to receive profile timer ticks. The returned
109 // token is to be used when unregistering this callback and must not be
110 // deleted by the caller.
111 ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback,
112 void* callback_arg);
113
114 // Unregisters a previously registered callback. Expects the token returned
115 // by the corresponding RegisterCallback routine.
116 void UnregisterCallback(ProfileHandlerToken* token)
117 NO_THREAD_SAFETY_ANALYSIS;
118
119 // Unregisters all the callbacks and stops the timer(s).
120 void Reset();
121
122 // Gets the current state of profile handler.
123 void GetState(ProfileHandlerState* state);
124
125 // Initializes and returns the ProfileHandler singleton.
126 static ProfileHandler* Instance();
127
128 private:
129 ProfileHandler();
130 ~ProfileHandler();
131
132 // Largest allowed frequency.
133 static const int32 kMaxFrequency = 4000;
134 // Default frequency.
135 static const int32 kDefaultFrequency = 100;
136
137 // ProfileHandler singleton.
138 static ProfileHandler* instance_;
139
140 // pthread_once_t for one time initialization of ProfileHandler singleton.
141 static pthread_once_t once_;
142
143 // Initializes the ProfileHandler singleton via GoogleOnceInit.
144 static void Init();
145
146 // Timer state as configured previously.
147 bool timer_running_;
148
149 // The number of profiling signal interrupts received.
150 int64 interrupts_ GUARDED_BY(signal_lock_);
151
152 // Profiling signal interrupt frequency, read-only after construction.
153 int32 frequency_;
154
155 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM).
156 // Translated into an equivalent choice of clock if per_thread_timer_enabled_
157 // is true.
158 int timer_type_;
159
160 // Signal number for timer signal.
161 int signal_number_;
162
163 // Counts the number of callbacks registered.
164 int32 callback_count_ GUARDED_BY(control_lock_);
165
166 // Is profiling allowed at all?
167 bool allowed_;
168
169 // Must be false if HAVE_LINUX_SIGEV_THREAD_ID is not defined.
170 bool per_thread_timer_enabled_;
171
172 #ifdef HAVE_LINUX_SIGEV_THREAD_ID
173 // this is used to destroy per-thread profiling timers on thread
174 // termination
175 pthread_key_t thread_timer_key;
176 #endif
177
178 // This lock serializes the registration of threads and protects the
179 // callbacks_ list below.
180 // Locking order:
181 // In the context of a signal handler, acquire signal_lock_ to walk the
182 // callback list. Otherwise, acquire control_lock_, disable the signal
183 // handler and then acquire signal_lock_.
184 SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_);
185 SpinLock signal_lock_;
186
187 // Holds the list of registered callbacks. We expect the list to be pretty
188 // small. Currently, the cpu profiler (base/profiler) and thread module
189 // (base/thread.h) are the only two components registering callbacks.
190 // Following are the locking requirements for callbacks_:
191 // For read-write access outside the SIGPROF handler:
192 // - Acquire control_lock_
193 // - Disable SIGPROF handler.
194 // - Acquire signal_lock_
195 // For read-only access in the context of SIGPROF handler
196 // (Read-write access is *not allowed* in the SIGPROF handler)
197 // - Acquire signal_lock_
198 // For read-only access outside SIGPROF handler:
199 // - Acquire control_lock_
200 typedef list<ProfileHandlerToken*> CallbackList;
201 typedef CallbackList::iterator CallbackIterator;
202 CallbackList callbacks_ GUARDED_BY(signal_lock_);
203
204 // Starts or stops the interval timer.
205 // Will ignore any requests to enable or disable when
206 // per_thread_timer_enabled_ is true.
207 void UpdateTimer(bool enable) EXCLUSIVE_LOCKS_REQUIRED(signal_lock_);
208
209 // Returns true if the handler is not being used by something else.
210 // This checks the kernel's signal handler table.
211 bool IsSignalHandlerAvailable();
212
213 // Signal handler. Iterates over and calls all the registered callbacks.
214 static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
215
216 DISALLOW_COPY_AND_ASSIGN(ProfileHandler);
217 };
218
219 ProfileHandler* ProfileHandler::instance_ = NULL;
220 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT;
221
222 const int32 ProfileHandler::kMaxFrequency;
223 const int32 ProfileHandler::kDefaultFrequency;
224
225 // If we are LD_PRELOAD-ed against a non-pthreads app, then these functions
226 // won't be defined. We declare them here, for that case (with weak linkage)
227 // which will cause the non-definition to resolve to NULL. We can then check
228 // for NULL or not in Instance.
229 extern "C" {
230 int pthread_once(pthread_once_t *, void (*)(void)) ATTRIBUTE_WEAK;
231 int pthread_kill(pthread_t thread_id, int signo) ATTRIBUTE_WEAK;
232
233 #if HAVE_LINUX_SIGEV_THREAD_ID
234 int timer_create(clockid_t clockid, struct sigevent* evp,
235 timer_t* timerid) ATTRIBUTE_WEAK;
236 int timer_delete(timer_t timerid) ATTRIBUTE_WEAK;
237 int timer_settime(timer_t timerid, int flags, const struct itimerspec* value,
238 struct itimerspec* ovalue) ATTRIBUTE_WEAK;
239 #endif
240 }
241
242 #if HAVE_LINUX_SIGEV_THREAD_ID
243
244 struct timer_id_holder {
245 timer_t timerid;
timer_id_holdertimer_id_holder246 timer_id_holder(timer_t _timerid) : timerid(_timerid) {}
247 };
248
249 extern "C" {
ThreadTimerDestructor(void * arg)250 static void ThreadTimerDestructor(void *arg) {
251 if (!arg) {
252 return;
253 }
254 timer_id_holder *holder = static_cast<timer_id_holder *>(arg);
255 timer_delete(holder->timerid);
256 delete holder;
257 }
258 }
259
CreateThreadTimerKey(pthread_key_t * pkey)260 static void CreateThreadTimerKey(pthread_key_t *pkey) {
261 int rv = perftools_pthread_key_create(pkey, ThreadTimerDestructor);
262 if (rv) {
263 RAW_LOG(FATAL, "aborting due to pthread_key_create error: %s", strerror(rv));
264 }
265 }
266
StartLinuxThreadTimer(int timer_type,int signal_number,int32 frequency,pthread_key_t timer_key)267 static void StartLinuxThreadTimer(int timer_type, int signal_number,
268 int32 frequency, pthread_key_t timer_key) {
269 int rv;
270 struct sigevent sevp;
271 timer_t timerid;
272 struct itimerspec its;
273 memset(&sevp, 0, sizeof(sevp));
274 sevp.sigev_notify = SIGEV_THREAD_ID;
275 sevp._sigev_un._tid = sys_gettid();
276 sevp.sigev_signo = signal_number;
277 clockid_t clock = CLOCK_THREAD_CPUTIME_ID;
278 if (timer_type == ITIMER_REAL) {
279 clock = CLOCK_MONOTONIC;
280 }
281 rv = timer_create(clock, &sevp, &timerid);
282 if (rv) {
283 RAW_LOG(FATAL, "aborting due to timer_create error: %s", strerror(errno));
284 }
285
286 timer_id_holder *holder = new timer_id_holder(timerid);
287 rv = perftools_pthread_setspecific(timer_key, holder);
288 if (rv) {
289 RAW_LOG(FATAL, "aborting due to pthread_setspecific error: %s", strerror(rv));
290 }
291
292 its.it_interval.tv_sec = 0;
293 its.it_interval.tv_nsec = 1000000000 / frequency;
294 its.it_value = its.it_interval;
295 rv = timer_settime(timerid, 0, &its, 0);
296 if (rv) {
297 RAW_LOG(FATAL, "aborting due to timer_settime error: %s", strerror(errno));
298 }
299 }
300 #endif
301
Init()302 void ProfileHandler::Init() {
303 instance_ = new ProfileHandler();
304 }
305
Instance()306 ProfileHandler* ProfileHandler::Instance() {
307 if (pthread_once) {
308 pthread_once(&once_, Init);
309 }
310 if (instance_ == NULL) {
311 // This will be true on systems that don't link in pthreads,
312 // including on FreeBSD where pthread_once has a non-zero address
313 // (but doesn't do anything) even when pthreads isn't linked in.
314 Init();
315 assert(instance_ != NULL);
316 }
317 return instance_;
318 }
319
ProfileHandler()320 ProfileHandler::ProfileHandler()
321 : timer_running_(false),
322 interrupts_(0),
323 callback_count_(0),
324 allowed_(true),
325 per_thread_timer_enabled_(false) {
326 SpinLockHolder cl(&control_lock_);
327
328 timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
329 signal_number_ = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
330
331 // Get frequency of interrupts (if specified)
332 char junk;
333 const char* fr = getenv("CPUPROFILE_FREQUENCY");
334 if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) &&
335 (frequency_ > 0)) {
336 // Limit to kMaxFrequency
337 frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_;
338 } else {
339 frequency_ = kDefaultFrequency;
340 }
341
342 if (!allowed_) {
343 return;
344 }
345
346 #if HAVE_LINUX_SIGEV_THREAD_ID
347 // Do this early because we might be overriding signal number.
348
349 const char *per_thread = getenv("CPUPROFILE_PER_THREAD_TIMERS");
350 const char *signal_number = getenv("CPUPROFILE_TIMER_SIGNAL");
351
352 if (per_thread || signal_number) {
353 if (timer_create && pthread_once) {
354 CreateThreadTimerKey(&thread_timer_key);
355 per_thread_timer_enabled_ = true;
356 // Override signal number if requested.
357 if (signal_number) {
358 signal_number_ = strtol(signal_number, NULL, 0);
359 }
360 } else {
361 RAW_LOG(INFO,
362 "Ignoring CPUPROFILE_PER_THREAD_TIMERS and\n"
363 " CPUPROFILE_TIMER_SIGNAL due to lack of timer_create().\n"
364 " Preload or link to librt.so for this to work");
365 }
366 }
367 #endif
368
369 // If something else is using the signal handler,
370 // assume it has priority over us and stop.
371 if (!IsSignalHandlerAvailable()) {
372 RAW_LOG(INFO, "Disabling profiler because signal %d handler is already in use.",
373 signal_number_);
374 allowed_ = false;
375 return;
376 }
377
378 // Install the signal handler.
379 struct sigaction sa;
380 sa.sa_sigaction = SignalHandler;
381 sa.sa_flags = SA_RESTART | SA_SIGINFO;
382 sigemptyset(&sa.sa_mask);
383 RAW_CHECK(sigaction(signal_number_, &sa, NULL) == 0, "sigprof (enable)");
384 }
385
~ProfileHandler()386 ProfileHandler::~ProfileHandler() {
387 Reset();
388 #ifdef HAVE_LINUX_SIGEV_THREAD_ID
389 if (per_thread_timer_enabled_) {
390 perftools_pthread_key_delete(thread_timer_key);
391 }
392 #endif
393 }
394
RegisterThread()395 void ProfileHandler::RegisterThread() {
396 SpinLockHolder cl(&control_lock_);
397
398 if (!allowed_) {
399 return;
400 }
401
402 // Record the thread identifier and start the timer if profiling is on.
403 ScopedSignalBlocker block(signal_number_);
404 SpinLockHolder sl(&signal_lock_);
405 #if HAVE_LINUX_SIGEV_THREAD_ID
406 if (per_thread_timer_enabled_) {
407 StartLinuxThreadTimer(timer_type_, signal_number_, frequency_,
408 thread_timer_key);
409 return;
410 }
411 #endif
412 UpdateTimer(callback_count_ > 0);
413 }
414
RegisterCallback(ProfileHandlerCallback callback,void * callback_arg)415 ProfileHandlerToken* ProfileHandler::RegisterCallback(
416 ProfileHandlerCallback callback, void* callback_arg) {
417
418 ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
419
420 SpinLockHolder cl(&control_lock_);
421 {
422 ScopedSignalBlocker block(signal_number_);
423 SpinLockHolder sl(&signal_lock_);
424 callbacks_.push_back(token);
425 ++callback_count_;
426 UpdateTimer(true);
427 }
428 return token;
429 }
430
UnregisterCallback(ProfileHandlerToken * token)431 void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) {
432 SpinLockHolder cl(&control_lock_);
433 for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end();
434 ++it) {
435 if ((*it) == token) {
436 RAW_CHECK(callback_count_ > 0, "Invalid callback count");
437 {
438 ScopedSignalBlocker block(signal_number_);
439 SpinLockHolder sl(&signal_lock_);
440 delete *it;
441 callbacks_.erase(it);
442 --callback_count_;
443 if (callback_count_ == 0)
444 UpdateTimer(false);
445 }
446 return;
447 }
448 }
449 // Unknown token.
450 RAW_LOG(FATAL, "Invalid token");
451 }
452
Reset()453 void ProfileHandler::Reset() {
454 SpinLockHolder cl(&control_lock_);
455 {
456 ScopedSignalBlocker block(signal_number_);
457 SpinLockHolder sl(&signal_lock_);
458 CallbackIterator it = callbacks_.begin();
459 while (it != callbacks_.end()) {
460 CallbackIterator tmp = it;
461 ++it;
462 delete *tmp;
463 callbacks_.erase(tmp);
464 }
465 callback_count_ = 0;
466 UpdateTimer(false);
467 }
468 }
469
GetState(ProfileHandlerState * state)470 void ProfileHandler::GetState(ProfileHandlerState* state) {
471 SpinLockHolder cl(&control_lock_);
472 {
473 ScopedSignalBlocker block(signal_number_);
474 SpinLockHolder sl(&signal_lock_); // Protects interrupts_.
475 state->interrupts = interrupts_;
476 }
477 state->frequency = frequency_;
478 state->callback_count = callback_count_;
479 state->allowed = allowed_;
480 }
481
UpdateTimer(bool enable)482 void ProfileHandler::UpdateTimer(bool enable) {
483 if (per_thread_timer_enabled_) {
484 // Ignore any attempts to disable it because that's not supported, and it's
485 // always enabled so enabling is always a NOP.
486 return;
487 }
488
489 if (enable == timer_running_) {
490 return;
491 }
492 timer_running_ = enable;
493
494 struct itimerval timer;
495 static const int kMillion = 1000000;
496 int interval_usec = enable ? kMillion / frequency_ : 0;
497 timer.it_interval.tv_sec = interval_usec / kMillion;
498 timer.it_interval.tv_usec = interval_usec % kMillion;
499 timer.it_value = timer.it_interval;
500 setitimer(timer_type_, &timer, 0);
501 }
502
IsSignalHandlerAvailable()503 bool ProfileHandler::IsSignalHandlerAvailable() {
504 struct sigaction sa;
505 RAW_CHECK(sigaction(signal_number_, NULL, &sa) == 0, "is-signal-handler avail");
506
507 // We only take over the handler if the current one is unset.
508 // It must be SIG_IGN or SIG_DFL, not some other function.
509 // SIG_IGN must be allowed because when profiling is allowed but
510 // not actively in use, this code keeps the handler set to SIG_IGN.
511 // That setting will be inherited across fork+exec. In order for
512 // any child to be able to use profiling, SIG_IGN must be treated
513 // as available.
514 return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
515 }
516
SignalHandler(int sig,siginfo_t * sinfo,void * ucontext)517 void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
518 int saved_errno = errno;
519 // At this moment, instance_ must be initialized because the handler is
520 // enabled in RegisterThread or RegisterCallback only after
521 // ProfileHandler::Instance runs.
522 ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_);
523 RAW_CHECK(instance != NULL, "ProfileHandler is not initialized");
524 {
525 SpinLockHolder sl(&instance->signal_lock_);
526 ++instance->interrupts_;
527 for (CallbackIterator it = instance->callbacks_.begin();
528 it != instance->callbacks_.end();
529 ++it) {
530 (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
531 }
532 }
533 errno = saved_errno;
534 }
535
536 // This module initializer registers the main thread, so it must be
537 // executed in the context of the main thread.
538 REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread());
539
ProfileHandlerRegisterThread()540 void ProfileHandlerRegisterThread() {
541 ProfileHandler::Instance()->RegisterThread();
542 }
543
ProfileHandlerRegisterCallback(ProfileHandlerCallback callback,void * callback_arg)544 ProfileHandlerToken* ProfileHandlerRegisterCallback(
545 ProfileHandlerCallback callback, void* callback_arg) {
546 return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
547 }
548
ProfileHandlerUnregisterCallback(ProfileHandlerToken * token)549 void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
550 ProfileHandler::Instance()->UnregisterCallback(token);
551 }
552
ProfileHandlerReset()553 void ProfileHandlerReset() {
554 return ProfileHandler::Instance()->Reset();
555 }
556
ProfileHandlerGetState(ProfileHandlerState * state)557 void ProfileHandlerGetState(ProfileHandlerState* state) {
558 ProfileHandler::Instance()->GetState(state);
559 }
560
561 #else // OS_CYGWIN
562
563 // ITIMER_PROF doesn't work under cygwin. ITIMER_REAL is available, but doesn't
564 // work as well for profiling, and also interferes with alarm(). Because of
565 // these issues, unless a specific need is identified, profiler support is
566 // disabled under Cygwin.
ProfileHandlerRegisterThread()567 void ProfileHandlerRegisterThread() {
568 }
569
ProfileHandlerRegisterCallback(ProfileHandlerCallback callback,void * callback_arg)570 ProfileHandlerToken* ProfileHandlerRegisterCallback(
571 ProfileHandlerCallback callback, void* callback_arg) {
572 return NULL;
573 }
574
ProfileHandlerUnregisterCallback(ProfileHandlerToken * token)575 void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
576 }
577
ProfileHandlerReset()578 void ProfileHandlerReset() {
579 }
580
ProfileHandlerGetState(ProfileHandlerState * state)581 void ProfileHandlerGetState(ProfileHandlerState* state) {
582 }
583
584 #endif // OS_CYGWIN
585