15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009, Google Inc.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met:
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions of source code must retain the above copyright
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Redistributions in binary form must reproduce the above
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     * Neither the name of Google Inc. nor the names of its
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission.
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Sanjay Ghemawat
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//         Nabeel Mian
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements management of profile timers and the corresponding signal handler.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "profile-handler.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h>
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/dynamic_annotations.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/spinlock.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "maybe_threads.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::list;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This structure is used by ProfileHandlerRegisterCallback and
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProfileHandlerUnregisterCallback as a handle to a registered callback.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ProfileHandlerToken {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the callback and associated arg.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandlerToken(ProfileHandlerCallback cb, void* cb_arg)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : callback(cb),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callback_arg(cb_arg) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback function to be invoked on receiving a profile timer interrupt.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandlerCallback callback;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Argument for the callback function.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* callback_arg;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class manages profile timers and associated signal handler. This is a
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a singleton.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProfileHandler {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers the current thread with the profile handler. On systems which
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // have a separate interval timer for each thread, this function starts the
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timer for the current thread.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The function also attempts to determine whether or not timers are shared by
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // all threads in the process.  (With LinuxThreads, and with NPTL on some
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Linux kernel versions, each thread has separate timers.)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prior to determining whether timers are shared, this function will
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unconditionally start the timer.  However, if this function determines
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that timers are shared, then it will stop the timer if no callbacks are
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // currently registered.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RegisterThread();
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Registers a callback routine to receive profile timer ticks. The returned
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // token is to be used when unregistering this callback and must not be
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // deleted by the caller. Registration of the first callback enables the
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SIGPROF handler (or SIGALRM if using ITIMER_REAL).
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandlerToken* RegisterCallback(ProfileHandlerCallback callback,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        void* callback_arg);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unregisters a previously registered callback. Expects the token returned
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by the corresponding RegisterCallback routine. Unregistering the last
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback disables the SIGPROF handler (or SIGALRM if using ITIMER_REAL).
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UnregisterCallback(ProfileHandlerToken* token)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NO_THREAD_SAFETY_ANALYSIS;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unregisters all the callbacks, stops the timer if shared, disables the
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SIGPROF (or SIGALRM) handler and clears the timer_sharing_ state.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reset();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the current state of profile handler.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetState(ProfileHandlerState* state);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes and returns the ProfileHandler singleton.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ProfileHandler* Instance();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandler();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~ProfileHandler();
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Largest allowed frequency.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int32 kMaxFrequency = 4000;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Default frequency.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int32 kDefaultFrequency = 100;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileHandler singleton.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ProfileHandler* instance_;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pthread_once_t for one time initialization of ProfileHandler singleton.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static pthread_once_t once_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initializes the ProfileHandler singleton via GoogleOnceInit.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Init();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The number of SIGPROF (or SIGALRM for ITIMER_REAL) interrupts received.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 interrupts_ GUARDED_BY(signal_lock_);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SIGPROF/SIGALRM interrupt frequency, read-only after construction.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 frequency_;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ITIMER_PROF (which uses SIGPROF), or ITIMER_REAL (which uses SIGALRM)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int timer_type_;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Counts the number of callbacks registered.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 callback_count_ GUARDED_BY(control_lock_);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Is profiling allowed at all?
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allowed_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether or not the threading system provides interval timers that are
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shared by all threads in a process.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No timer initialization attempted yet.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TIMERS_UNTOUCHED,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // First thread has registered and set timer.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TIMERS_ONE_SET,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Timers are shared by all threads.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TIMERS_SHARED,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Timers are separate in each thread.
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TIMERS_SEPARATE
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } timer_sharing_ GUARDED_BY(control_lock_);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This lock serializes the registration of threads and protects the
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks_ list below.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Locking order:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the context of a signal handler, acquire signal_lock_ to walk the
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callback list. Otherwise, acquire control_lock_, disable the signal
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handler and then acquire signal_lock_.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLock control_lock_ ACQUIRED_BEFORE(signal_lock_);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLock signal_lock_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Holds the list of registered callbacks. We expect the list to be pretty
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // small. Currently, the cpu profiler (base/profiler) and thread module
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (base/thread.h) are the only two components registering callbacks.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Following are the locking requirements for callbacks_:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For read-write access outside the SIGPROF handler:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - Acquire control_lock_
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - Disable SIGPROF handler.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - Acquire signal_lock_
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For read-only access in the context of SIGPROF handler
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Read-write access is *not allowed* in the SIGPROF handler)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - Acquire signal_lock_
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For read-only access outside SIGPROF handler:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  - Acquire control_lock_
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef list<ProfileHandlerToken*> CallbackList;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef CallbackList::iterator CallbackIterator;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CallbackList callbacks_ GUARDED_BY(signal_lock_);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Starts the interval timer.  If the thread library shares timers between
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads, this function starts the shared timer. Otherwise, this will start
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the timer in the current thread.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StartTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stops the interval timer. If the thread library shares timers between
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads, this fucntion stops the shared timer. Otherwise, this will stop
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the timer in the current thread.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void StopTimer() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the profile interval timer is enabled in the current
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // thread.  This actually checks the kernel's interval timer setting.  (It is
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used to detect whether timers are shared or separate.)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsTimerRunning() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sets the timer interrupt signal handler.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EnableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disables (ignores) the timer interrupt signal.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DisableHandler() EXCLUSIVE_LOCKS_REQUIRED(control_lock_);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if the handler is not being used by something else.
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This checks the kernel's signal handler table.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool IsSignalHandlerAvailable();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SIGPROF/SIGALRM handler. Iterate over and call all the registered callbacks.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void SignalHandler(int sig, siginfo_t* sinfo, void* ucontext);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ProfileHandler);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileHandler* ProfileHandler::instance_ = NULL;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)pthread_once_t ProfileHandler::once_ = PTHREAD_ONCE_INIT;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32 ProfileHandler::kMaxFrequency;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int32 ProfileHandler::kDefaultFrequency;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we are LD_PRELOAD-ed against a non-pthreads app, then
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pthread_once won't be defined.  We declare it here, for that
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// case (with weak linkage) which will cause the non-definition to
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// resolve to NULL.  We can then check for NULL or not in Instance.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int pthread_once(pthread_once_t *, void (*)(void))
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ATTRIBUTE_WEAK;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::Init() {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  instance_ = new ProfileHandler();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileHandler* ProfileHandler::Instance() {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pthread_once) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pthread_once(&once_, Init);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (instance_ == NULL) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will be true on systems that don't link in pthreads,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // including on FreeBSD where pthread_once has a non-zero address
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (but doesn't do anything) even when pthreads isn't linked in.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Init();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(instance_ != NULL);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return instance_;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileHandler::ProfileHandler()
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : interrupts_(0),
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_count_(0),
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allowed_(true),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timer_sharing_(TIMERS_UNTOUCHED) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_type_ = (getenv("CPUPROFILE_REALTIME") ? ITIMER_REAL : ITIMER_PROF);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get frequency of interrupts (if specified)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char junk;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* fr = getenv("CPUPROFILE_FREQUENCY");
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fr != NULL && (sscanf(fr, "%u%c", &frequency_, &junk) == 1) &&
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (frequency_ > 0)) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Limit to kMaxFrequency
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frequency_ = (frequency_ > kMaxFrequency) ? kMaxFrequency : frequency_;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    frequency_ = kDefaultFrequency;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If something else is using the signal handler,
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // assume it has priority over us and stop.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsSignalHandlerAvailable()) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(INFO, "Disabling profiler because %s handler is already in use.",
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    timer_type_ == ITIMER_REAL ? "SIGALRM" : "SIGPROF");
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allowed_ = false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore signals until we decide to turn profiling on.  (Paranoia;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should already be ignored.)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DisableHandler();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileHandler::~ProfileHandler() {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset();
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::RegisterThread() {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We try to detect whether timers are being shared by setting a
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timer in the first call to this function, then checking whether
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it's set in the second call.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that this detection method requires that the first two calls
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to RegisterThread must be made from different threads.  (Subsequent
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // calls will see timer_sharing_ set to either TIMERS_SEPARATE or
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TIMERS_SHARED, and won't try to detect the timer sharing type.)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also note that if timer settings were inherited across new thread
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // creation but *not* shared, this approach wouldn't work.  That's
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not an issue for any Linux threading implementation, and should
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be a problem for a POSIX-compliant threads implementation.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (timer_sharing_) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TIMERS_UNTOUCHED:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartTimer();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      timer_sharing_ = TIMERS_ONE_SET;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TIMERS_ONE_SET:
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If the timer is running, that means that the main thread's
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // timer setup is seen in this (second) thread -- and therefore
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // that timers are shared.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsTimerRunning()) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timer_sharing_ = TIMERS_SHARED;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If callback is already registered, we have to keep the timer
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // running.  If not, we disable the timer here.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (callback_count_ == 0) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          StopTimer();
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        timer_sharing_ = TIMERS_SEPARATE;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StartTimer();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TIMERS_SHARED:
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Nothing needed.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TIMERS_SEPARATE:
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartTimer();
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileHandlerToken* ProfileHandler::RegisterCallback(
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileHandlerCallback callback, void* callback_arg) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandlerToken* token = new ProfileHandlerToken(callback, callback_arg);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DisableHandler();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder sl(&signal_lock_);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callbacks_.push_back(token);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the timer if timer is shared and this is a first callback.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((callback_count_ == 0) && (timer_sharing_ == TIMERS_SHARED)) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartTimer();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++callback_count_;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnableHandler();
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return token;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::UnregisterCallback(ProfileHandlerToken* token) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CallbackIterator it = callbacks_.begin(); it != callbacks_.end();
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*it) == token) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RAW_CHECK(callback_count_ > 0, "Invalid callback count");
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DisableHandler();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SpinLockHolder sl(&signal_lock_);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delete *it;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        callbacks_.erase(it);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --callback_count_;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (callback_count_ > 0) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EnableHandler();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (timer_sharing_ == TIMERS_SHARED) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        StopTimer();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unknown token.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_LOG(FATAL, "Invalid token");
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::Reset() {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DisableHandler();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder sl(&signal_lock_);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallbackIterator it = callbacks_.begin();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (it != callbacks_.end()) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CallbackIterator tmp = it;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++it;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete *tmp;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callbacks_.erase(tmp);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_count_ = 0;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (timer_sharing_ == TIMERS_SHARED) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopTimer();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer_sharing_ = TIMERS_UNTOUCHED;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::GetState(ProfileHandlerState* state) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder cl(&control_lock_);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DisableHandler();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder sl(&signal_lock_);  // Protects interrupts_.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state->interrupts = interrupts_;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (callback_count_ > 0) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnableHandler();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->frequency = frequency_;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->callback_count = callback_count_;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state->allowed = allowed_;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::StartTimer() {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct itimerval timer;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer.it_interval.tv_sec = 0;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer.it_interval.tv_usec = 1000000 / frequency_;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timer.it_value = timer.it_interval;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setitimer(timer_type_, &timer, 0);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::StopTimer() {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct itimerval timer;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&timer, 0, sizeof timer);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  setitimer(timer_type_, &timer, 0);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileHandler::IsTimerRunning() {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct itimerval current_timer;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(0 == getitimer(timer_type_, &current_timer), "getitimer");
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (current_timer.it_value.tv_sec != 0 ||
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          current_timer.it_value.tv_usec != 0);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::EnableHandler() {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction sa;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sa.sa_sigaction = SignalHandler;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sa.sa_flags = SA_RESTART | SA_SIGINFO;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sigemptyset(&sa.sa_mask);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (enable)");
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::DisableHandler() {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!allowed_) {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction sa;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sa.sa_handler = SIG_IGN;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sa.sa_flags = SA_RESTART;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sigemptyset(&sa.sa_mask);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(sigaction(signal_number, &sa, NULL) == 0, "sigprof (disable)");
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfileHandler::IsSignalHandlerAvailable() {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction sa;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int signal_number = (timer_type_ == ITIMER_PROF ? SIGPROF : SIGALRM);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(sigaction(signal_number, NULL, &sa) == 0, "is-signal-handler avail");
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only take over the handler if the current one is unset.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It must be SIG_IGN or SIG_DFL, not some other function.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SIG_IGN must be allowed because when profiling is allowed but
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not actively in use, this code keeps the handler set to SIG_IGN.
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // That setting will be inherited across fork+exec.  In order for
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // any child to be able to use profiling, SIG_IGN must be treated
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as available.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sa.sa_handler == SIG_IGN || sa.sa_handler == SIG_DFL;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProfileHandler::SignalHandler(int sig, siginfo_t* sinfo, void* ucontext) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int saved_errno = errno;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this moment, instance_ must be initialized because the handler is
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // enabled in RegisterThread or RegisterCallback only after
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ProfileHandler::Instance runs.
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandler* instance = ANNOTATE_UNPROTECTED_READ(instance_);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(instance != NULL, "ProfileHandler is not initialized");
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SpinLockHolder sl(&instance->signal_lock_);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++instance->interrupts_;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (CallbackIterator it = instance->callbacks_.begin();
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         it != instance->callbacks_.end();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ++it) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (*it)->callback(sig, sinfo, ucontext, (*it)->callback_arg);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  errno = saved_errno;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This module initializer registers the main thread, so it must be
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// executed in the context of the main thread.
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_MODULE_INITIALIZER(profile_main, ProfileHandlerRegisterThread());
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerRegisterThread() {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandler::Instance()->RegisterThread();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileHandlerCallback callback, void* callback_arg) {
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProfileHandler::Instance()->RegisterCallback(callback, callback_arg);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandler::Instance()->UnregisterCallback(token);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerReset() {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProfileHandler::Instance()->Reset();
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileHandler::Instance()->GetState(state);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // OS_CYGWIN
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ITIMER_PROF doesn't work under cygwin.  ITIMER_REAL is available, but doesn't
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// work as well for profiling, and also interferes with alarm().  Because of
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these issues, unless a specific need is identified, profiler support is
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// disabled under Cygwin.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerRegisterThread() {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" ProfileHandlerToken* ProfileHandlerRegisterCallback(
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileHandlerCallback callback, void* callback_arg) {
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerReset() {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void ProfileHandlerGetState(ProfileHandlerState* state) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // OS_CYGWIN
556