1 // Copyright (c) 2009, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 // Author: Sanjay Ghemawat
34 // Implements management of profile timers and the corresponding signal handler.
37 #include "profile-handler.h"
39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
48 #include "base/dynamic_annotations.h"
49 #include "base/googleinit.h"
50 #include "base/logging.h"
51 #include "base/spinlock.h"
52 #include "maybe_threads.h"
57 // This structure is used by ProfileHandlerRegisterCallback and
58 // ProfileHandlerUnregisterCallback as a handle to a registered callback.
59 struct ProfileHandlerToken
{
60 // Sets the callback and associated arg.
61 ProfileHandlerToken(ProfileHandlerCallback cb
, void* cb_arg
)
63 callback_arg(cb_arg
) {
66 // Callback function to be invoked on receiving a profile timer interrupt.
67 ProfileHandlerCallback callback
;
68 // Argument for the callback function.
72 // This class manages profile timers and associated signal handler. This is a
74 class ProfileHandler
{
76 // Registers the current thread with the profile handler. On systems which
77 // have a separate interval timer for each thread, this function starts the
78 // timer for the current thread.
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.)
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();
90 // 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
92 // deleted by the caller. Registration of the first callback enables the
93 // SIGPROF handler (or SIGALRM if using ITIMER_REAL).
94 ProfileHandlerToken
* RegisterCallback(ProfileHandlerCallback callback
,
97 // Unregisters a previously registered callback. Expects the token returned
98 // by the corresponding RegisterCallback routine. Unregistering the last
99 // callback disables the SIGPROF handler (or SIGALRM if using ITIMER_REAL).
100 void UnregisterCallback(ProfileHandlerToken
* token
)
101 NO_THREAD_SAFETY_ANALYSIS
;
103 // Unregisters all the callbacks, stops the timer if shared, disables the
104 // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state.
107 // Gets the current state of profile handler.
108 void GetState(ProfileHandlerState
* state
);
110 // Initializes and returns the ProfileHandler singleton.
111 static ProfileHandler
* Instance();
117 // Largest allowed frequency.
118 static const int32 kMaxFrequency
= 4000;
119 // Default frequency.
120 static const int32 kDefaultFrequency
= 100;
122 // ProfileHandler singleton.
123 static ProfileHandler
* instance_
;
125 // pthread_once_t for one time initialization of ProfileHandler singleton.
126 static pthread_once_t once_
;
128 // Initializes the ProfileHandler singleton via GoogleOnceInit.
131 // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received.
132 int64 interrupts_
GUARDED_BY(signal_lock_
);
134 // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
137 // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
140 // Counts the number of callbacks registered.
141 int32 callback_count_
GUARDED_BY(control_lock_
);
143 // Is profiling allowed at all?
146 // Whether or not the threading system provides interval timers that are
147 // shared by all threads in a process.
149 // No timer initialization attempted yet.
151 // First thread has registered and set timer.
153 // Timers are shared by all threads.
155 // Timers are separate in each thread.
157 } timer_sharing_
GUARDED_BY(control_lock_
);
159 // This lock serializes the registration of threads and protects the
160 // callbacks_ list below.
162 // In the context of a signal handler, acquire signal_lock_ to walk the
163 // callback list. Otherwise, acquire control_lock_, disable the signal
164 // handler and then acquire signal_lock_.
165 SpinLock control_lock_
ACQUIRED_BEFORE(signal_lock_
);
166 SpinLock signal_lock_
;
168 // Holds the list of registered callbacks. We expect the list to be pretty
169 // small. Currently, the cpu profiler (base/profiler) and thread module
170 // (base/thread.h) are the only two components registering callbacks.
171 // Following are the locking requirements for callbacks_:
172 // For read-write access outside the SIGPROF handler:
173 // - Acquire control_lock_
174 // - Disable SIGPROF handler.
175 // - Acquire signal_lock_
176 // For read-only access in the context of SIGPROF handler
177 // (Read-write access is *not allowed* in the SIGPROF handler)
178 // - Acquire signal_lock_
179 // For read-only access outside SIGPROF handler:
180 // - Acquire control_lock_
181 typedef list
<ProfileHandlerToken
*> CallbackList
;
182 typedef CallbackList::iterator CallbackIterator
;
183 CallbackList callbacks_
GUARDED_BY(signal_lock_
);
185 // Starts the interval timer. If the thread library shares timers between
186 // threads, this function starts the shared timer. Otherwise, this will start
187 // the timer in the current thread.
188 void StartTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_
);
190 // Stops the interval timer. If the thread library shares timers between
191 // threads, this fucntion stops the shared timer. Otherwise, this will stop
192 // the timer in the current thread.
193 void StopTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_
);
195 // Returns true if the profile interval timer is enabled in the current
196 // thread. This actually checks the kernel's interval timer setting. (It is
197 // used to detect whether timers are shared or separate.)
198 bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_
);
200 // Sets the timer interrupt signal handler.
201 void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_
);
203 // Disables (ignores) the timer interrupt signal.
204 void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_
);
206 // Returns true if the handler is not being used by something else.
207 // This checks the kernel's signal handler table.
208 bool IsSignalHandlerAvailable();
210 // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks.
211 static void SignalHandler(int sig
, siginfo_t
* sinfo
, void* ucontext
);
213 DISALLOW_COPY_AND_ASSIGN(ProfileHandler
);
216 ProfileHandler
* ProfileHandler::instance_
= NULL
;
217 pthread_once_t
ProfileHandler::once_
= PTHREAD_ONCE_INIT
;
219 const int32
ProfileHandler::kMaxFrequency
;
220 const int32
ProfileHandler::kDefaultFrequency
;
222 // If we are LD_PRELOAD-ed against a non-pthreads app, then
223 // pthread_once won't be defined. We declare it here, for that
224 // case (with weak linkage) which will cause the non-definition to
225 // resolve to NULL. We can then check for NULL or not in Instance.
226 extern "C" int pthread_once(pthread_once_t
*, void (*)(void))
229 void ProfileHandler::Init() {
230 instance_
= new ProfileHandler();
233 ProfileHandler
* ProfileHandler::Instance() {
235 pthread_once(&once_
, Init
);
237 if (instance_
== NULL
) {
238 // This will be true on systems that don't link in pthreads,
239 // including on FreeBSD where pthread_once has a non-zero address
240 // (but doesn't do anything) even when pthreads isn't linked in.
242 assert(instance_
!= NULL
);
247 ProfileHandler::ProfileHandler()
251 timer_sharing_(TIMERS_UNTOUCHED
) {
252 SpinLockHolder
cl(&control_lock_
);
254 timer_type_
= (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL
: ITIMER_PROF
);
256 // Get frequency of interrupts (if specified)
258 const char* fr
= getenv("CPUPROFILE_FREQUENCY");
259 if (fr
!= NULL
&& (sscanf(fr
, "%u%c", &frequency_
, &junk
) == 1) &&
261 // Limit to kMaxFrequency
262 frequency_
= (frequency_
> kMaxFrequency
) ? kMaxFrequency
: frequency_
;
264 frequency_
= kDefaultFrequency
;
271 // If something else is using the signal handler,
272 // assume it has priority over us and stop.
273 if (!IsSignalHandlerAvailable()) {
274 RAW_LOG(INFO
, "Disabling profiler because %s handler is already in use.",
275 timer_type_
== ITIMER_REAL
? "SIGALRM" : "SIGPROF");
280 // Ignore signals until we decide to turn profiling on. (Paranoia;
281 // should already be ignored.)
285 ProfileHandler::~ProfileHandler() {
289 void ProfileHandler::RegisterThread() {
290 SpinLockHolder
cl(&control_lock_
);
296 // We try to detect whether timers are being shared by setting a
297 // timer in the first call to this function, then checking whether
298 // it's set in the second call.
300 // Note that this detection method requires that the first two calls
301 // to RegisterThread must be made from different threads. (Subsequent
302 // calls will see timer_sharing_ set to either TIMERS_SEPARATE or
303 // TIMERS_SHARED, and won't try to detect the timer sharing type.)
305 // Also note that if timer settings were inherited across new thread
306 // creation but *not* shared, this approach wouldn't work. That's
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
:
312 timer_sharing_
= 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) {
326 timer_sharing_
= TIMERS_SEPARATE
;
333 case TIMERS_SEPARATE
:
339 ProfileHandlerToken
* ProfileHandler::RegisterCallback(
340 ProfileHandlerCallback callback
, void* callback_arg
) {
342 ProfileHandlerToken
* token
= new ProfileHandlerToken(callback
, callback_arg
);
344 SpinLockHolder
cl(&control_lock_
);
347 SpinLockHolder
sl(&signal_lock_
);
348 callbacks_
.push_back(token
);
350 // Start the timer if timer is shared and this is a first callback.
351 if ((callback_count_
== 0) && (timer_sharing_
== TIMERS_SHARED
)) {
359 void ProfileHandler::UnregisterCallback(ProfileHandlerToken
* token
) {
360 SpinLockHolder
cl(&control_lock_
);
361 for (CallbackIterator it
= callbacks_
.begin(); it
!= callbacks_
.end();
363 if ((*it
) == token
) {
364 RAW_CHECK(callback_count_
> 0, "Invalid callback count");
367 SpinLockHolder
sl(&signal_lock_
);
369 callbacks_
.erase(it
);
372 if (callback_count_
> 0) {
374 } else if (timer_sharing_
== TIMERS_SHARED
) {
381 RAW_LOG(FATAL
, "Invalid token");
384 void ProfileHandler::Reset() {
385 SpinLockHolder
cl(&control_lock_
);
388 SpinLockHolder
sl(&signal_lock_
);
389 CallbackIterator it
= callbacks_
.begin();
390 while (it
!= callbacks_
.end()) {
391 CallbackIterator tmp
= it
;
394 callbacks_
.erase(tmp
);
398 if (timer_sharing_
== TIMERS_SHARED
) {
401 timer_sharing_
= TIMERS_UNTOUCHED
;
404 void ProfileHandler::GetState(ProfileHandlerState
* state
) {
405 SpinLockHolder
cl(&control_lock_
);
408 SpinLockHolder
sl(&signal_lock_
); // Protects interrupts_.
409 state
->interrupts
= interrupts_
;
411 if (callback_count_
> 0) {
414 state
->frequency
= frequency_
;
415 state
->callback_count
= callback_count_
;
416 state
->allowed
= allowed_
;
419 void ProfileHandler::StartTimer() {
423 struct itimerval timer
;
424 timer
.it_interval
.tv_sec
= 0;
425 timer
.it_interval
.tv_usec
= 1000000 / frequency_
;
426 timer
.it_value
= timer
.it_interval
;
427 setitimer(timer_type_
, &timer
, 0);
430 void ProfileHandler::StopTimer() {
434 struct itimerval timer
;
435 memset(&timer
, 0, sizeof timer
);
436 setitimer(timer_type_
, &timer
, 0);
439 bool ProfileHandler::IsTimerRunning() {
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);
449 void ProfileHandler::EnableHandler() {
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)");
461 void ProfileHandler::DisableHandler() {
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)");
473 bool ProfileHandler::IsSignalHandlerAvailable() {
475 const int signal_number
= (timer_type_
== ITIMER_PROF
? SIGPROF
: SIGALRM
);
476 RAW_CHECK(sigaction(signal_number
, NULL
, &sa
) == 0, "is-signal-handler avail");
478 // 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.
480 // 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.
482 // 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
485 return sa
.sa_handler
== SIG_IGN
|| sa
.sa_handler
== SIG_DFL
;
488 void ProfileHandler::SignalHandler(int sig
, siginfo_t
* sinfo
, void* ucontext
) {
489 int saved_errno
= errno
;
490 // At this moment, instance_ must be initialized because the handler is
491 // enabled in RegisterThread or RegisterCallback only after
492 // ProfileHandler::Instance runs.
493 ProfileHandler
* instance
= ANNOTATE_UNPROTECTED_READ(instance_
);
494 RAW_CHECK(instance
!= NULL
, "ProfileHandler is not initialized");
496 SpinLockHolder
sl(&instance
->signal_lock_
);
497 ++instance
->interrupts_
;
498 for (CallbackIterator it
= instance
->callbacks_
.begin();
499 it
!= instance
->callbacks_
.end();
501 (*it
)->callback(sig
, sinfo
, ucontext
, (*it
)->callback_arg
);
507 // This module initializer registers the main thread, so it must be
508 // executed in the context of the main thread.
509 REGISTER_MODULE_INITIALIZER(profile_main
, ProfileHandlerRegisterThread());
511 extern "C" void ProfileHandlerRegisterThread() {
512 ProfileHandler::Instance()->RegisterThread();
515 extern "C" ProfileHandlerToken
* ProfileHandlerRegisterCallback(
516 ProfileHandlerCallback callback
, void* callback_arg
) {
517 return ProfileHandler::Instance()->RegisterCallback(callback
, callback_arg
);
520 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken
* token
) {
521 ProfileHandler::Instance()->UnregisterCallback(token
);
524 extern "C" void ProfileHandlerReset() {
525 return ProfileHandler::Instance()->Reset();
528 extern "C" void ProfileHandlerGetState(ProfileHandlerState
* state
) {
529 ProfileHandler::Instance()->GetState(state
);
534 // 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
536 // these issues, unless a specific need is identified, profiler support is
537 // disabled under Cygwin.
538 extern "C" void ProfileHandlerRegisterThread() {
541 extern "C" ProfileHandlerToken
* ProfileHandlerRegisterCallback(
542 ProfileHandlerCallback callback
, void* callback_arg
) {
546 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken
* token
) {
549 extern "C" void ProfileHandlerReset() {
552 extern "C" void ProfileHandlerGetState(ProfileHandlerState
* state
) {