- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tcmalloc / vendor / src / profile-handler.cc
1 // Copyright (c) 2009, Google Inc.
2 // All rights reserved.
3 // 
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 // 
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
13 // distribution.
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.
17 // 
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.
29
30 // ---
31 // Author: Sanjay Ghemawat
32 //         Nabeel Mian
33 //
34 // Implements management of profile timers and the corresponding signal handler.
35
36 #include "config.h"
37 #include "profile-handler.h"
38
39 #if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
40
41 #include <stdio.h>
42 #include <errno.h>
43 #include <sys/time.h>
44
45 #include <list>
46 #include <string>
47
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"
53
54 using std::list;
55 using std::string;
56
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)
62       : callback(cb),
63         callback_arg(cb_arg) {
64   }
65
66   // Callback function to be invoked on receiving a profile timer interrupt.
67   ProfileHandlerCallback callback;
68   // Argument for the callback function.
69   void* callback_arg;
70 };
71
72 // This class manages profile timers and associated signal handler. This is a
73 // a singleton.
74 class ProfileHandler {
75  public:
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.
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();
89
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,
95                                         void* callback_arg);
96
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;
102
103   // Unregisters all the callbacks, stops the timer if shared, disables the
104   // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state.
105   void Reset();
106
107   // Gets the current state of profile handler.
108   void GetState(ProfileHandlerState* state);
109
110   // Initializes and returns the ProfileHandler singleton.
111   static ProfileHandler* Instance();
112
113  private:
114   ProfileHandler();
115   ~ProfileHandler();
116
117   // Largest allowed frequency.
118   static const int32 kMaxFrequency = 4000;
119   // Default frequency.
120   static const int32 kDefaultFrequency = 100;
121
122   // ProfileHandler singleton.
123   static ProfileHandler* instance_;
124
125   // pthread_once_t for one time initialization of ProfileHandler singleton.
126   static pthread_once_t once_;
127
128   // Initializes the ProfileHandler singleton via GoogleOnceInit.
129   static void Init();
130
131   // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received.
132   int64 interrupts_ GUARDED_BY(signal_lock_);
133
134   // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
135   int32 frequency_;
136
137   // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
138   int timer_type_;
139
140   // Counts the number of callbacks registered.
141   int32 callback_count_ GUARDED_BY(control_lock_);
142
143   // Is profiling allowed at all?
144   bool allowed_;
145
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
160   // callbacks_ list below.
161   // Locking order:
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_;
167
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_);
184
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_);
189
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_);
194
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_);
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
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();
209
210   // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks.
211   static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
212
213   DISALLOW_COPY_AND_ASSIGN(ProfileHandler);
214 };
215
216 ProfileHandler* ProfileHandler::instance_ = NULL;
217 pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT;
218
219 const int32 ProfileHandler::kMaxFrequency;
220 const int32 ProfileHandler::kDefaultFrequency;
221
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))
227     ATTRIBUTE_WEAK;
228
229 void ProfileHandler::Init() {
230   instance_ = new ProfileHandler();
231 }
232
233 ProfileHandler* ProfileHandler::Instance() {
234   if (pthread_once) {
235     pthread_once(&once_, Init);
236   }
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.
241     Init();
242     assert(instance_ != NULL);
243   }
244   return instance_;
245 }
246
247 ProfileHandler::ProfileHandler()
248     : interrupts_(0),
249       callback_count_(0),
250       allowed_(true),
251       timer_sharing_(TIMERS_UNTOUCHED) {
252   SpinLockHolder cl(&control_lock_);
253
254   timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
255
256   // Get frequency of interrupts (if specified)
257   char junk;
258   const char* fr = getenv("CPUPROFILE_FREQUENCY");
259   if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) &&
260       (frequency_ > 0)) {
261     // Limit to kMaxFrequency
262     frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_;
263   } else {
264     frequency_ = kDefaultFrequency;
265   }
266
267   if (!allowed_) {
268     return;
269   }
270
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");
276     allowed_ = false;
277     return;
278   }
279
280   // Ignore signals until we decide to turn profiling on.  (Paranoia;
281   // should already be ignored.)
282   DisableHandler();
283 }
284
285 ProfileHandler::~ProfileHandler() {
286   Reset();
287 }
288
289 void ProfileHandler::RegisterThread() {
290   SpinLockHolder cl(&control_lock_);
291
292   if (!allowed_) {
293     return;
294   }
295
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.
299   //
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.)
304   //
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:
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 }
338
339 ProfileHandlerToken* ProfileHandler::RegisterCallback(
340     ProfileHandlerCallback callback, void* callback_arg) {
341
342   ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
343
344   SpinLockHolder cl(&control_lock_);
345   DisableHandler();
346   {
347     SpinLockHolder sl(&signal_lock_);
348     callbacks_.push_back(token);
349   }
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;
357 }
358
359 void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) {
360   SpinLockHolder cl(&control_lock_);
361   for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end();
362        ++it) {
363     if ((*it) == token) {
364       RAW_CHECK(callback_count_ > 0, "Invalid callback count");
365       DisableHandler();
366       {
367         SpinLockHolder sl(&signal_lock_);
368         delete *it;
369         callbacks_.erase(it);
370       }
371       --callback_count_;
372       if (callback_count_ > 0) {
373         EnableHandler();
374       } else if (timer_sharing_ == TIMERS_SHARED) {
375         StopTimer();
376       }
377       return;
378     }
379   }
380   // Unknown token.
381   RAW_LOG(FATAL, "Invalid token");
382 }
383
384 void ProfileHandler::Reset() {
385   SpinLockHolder cl(&control_lock_);
386   DisableHandler();
387   {
388     SpinLockHolder sl(&signal_lock_);
389     CallbackIterator it = callbacks_.begin();
390     while (it != callbacks_.end()) {
391       CallbackIterator tmp = it;
392       ++it;
393       delete *tmp;
394       callbacks_.erase(tmp);
395     }
396   }
397   callback_count_ = 0;
398   if (timer_sharing_ == TIMERS_SHARED) {
399     StopTimer();
400   }
401   timer_sharing_ = TIMERS_UNTOUCHED;
402 }
403
404 void ProfileHandler::GetState(ProfileHandlerState* state) {
405   SpinLockHolder cl(&control_lock_);
406   DisableHandler();
407   {
408     SpinLockHolder sl(&signal_lock_);  // Protects interrupts_.
409     state->interrupts = interrupts_;
410   }
411   if (callback_count_ > 0) {
412     EnableHandler();
413   }
414   state->frequency = frequency_;
415   state->callback_count = callback_count_;
416   state->allowed = allowed_;
417 }
418
419 void ProfileHandler::StartTimer() {
420   if (!allowed_) {
421     return;
422   }
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);
428 }
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_, &current_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 }
472
473 bool ProfileHandler::IsSignalHandlerAvailable() {
474   struct sigaction sa;
475   const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
476   RAW_CHECK(sigaction(signal_number, NULL, &sa) == 0, "is-signal-handler avail");
477
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
484   // as available.
485   return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
486 }
487
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");
495   {
496     SpinLockHolder sl(&instance->signal_lock_);
497     ++instance->interrupts_;
498     for (CallbackIterator it = instance->callbacks_.begin();
499          it != instance->callbacks_.end();
500          ++it) {
501       (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
502     }
503   }
504   errno = saved_errno;
505 }
506
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());
510
511 extern "C" void ProfileHandlerRegisterThread() {
512   ProfileHandler::Instance()->RegisterThread();
513 }
514
515 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
516     ProfileHandlerCallback callback, void* callback_arg) {
517   return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
518 }
519
520 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
521   ProfileHandler::Instance()->UnregisterCallback(token);
522 }
523
524 extern "C" void ProfileHandlerReset() {
525   return ProfileHandler::Instance()->Reset();
526 }
527
528 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
529   ProfileHandler::Instance()->GetState(state);
530 }
531
532 #else  // OS_CYGWIN
533
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() {
539 }
540
541 extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
542     ProfileHandlerCallback callback, void* callback_arg) {
543   return NULL;
544 }
545
546 extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
547 }
548
549 extern "C" void ProfileHandlerReset() {
550 }
551
552 extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
553 }
554
555 #endif  // OS_CYGWIN