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: Nabeel Mian 32 * 33 * This module manages the cpu profile timers and the associated interrupt 34 * handler. When enabled, all registered threads in the program are profiled. 35 * (Note: if using linux 2.4 or earlier, you must use the Thread class, in 36 * google3/thread, to ensure all threads are profiled.) 37 * 38 * Any component interested in receiving a profile timer interrupt can do so by 39 * registering a callback. All registered callbacks must be async-signal-safe. 40 * 41 * Note: This module requires the sole ownership of ITIMER_PROF timer and the 42 * SIGPROF signal. 43 */ 44 45 #ifndef BASE_PROFILE_HANDLER_H_ 46 #define BASE_PROFILE_HANDLER_H_ 47 48 #include "config.h" 49 #include <signal.h> 50 #ifdef COMPILER_MSVC 51 #include "conflict-signal.h" 52 #endif 53 #include "base/basictypes.h" 54 55 /* All this code should be usable from within C apps. */ 56 #ifdef __cplusplus 57 extern "C" { 58 #endif 59 60 /* Forward declaration. */ 61 struct ProfileHandlerToken; 62 63 /* 64 * Callback function to be used with ProfilefHandlerRegisterCallback. This 65 * function will be called in the context of SIGPROF signal handler and must 66 * be async-signal-safe. The first three arguments are the values provided by 67 * the SIGPROF signal handler. We use void* to avoid using ucontext_t on 68 * non-POSIX systems. 69 * 70 * Requirements: 71 * - Callback must be async-signal-safe. 72 * - None of the functions in ProfileHandler are async-signal-safe. Therefore, 73 * callback function *must* not call any of the ProfileHandler functions. 74 * - Callback is not required to be re-entrant. At most one instance of 75 * callback can run at a time. 76 * 77 * Notes: 78 * - The SIGPROF signal handler saves and restores errno, so the callback 79 * doesn't need to. 80 * - Callback code *must* not acquire lock(s) to serialize access to data shared 81 * with the code outside the signal handler (callback must be 82 * async-signal-safe). If such a serialization is needed, follow the model 83 * used by profiler.cc: 84 * 85 * When code other than the signal handler modifies the shared data it must: 86 * - Acquire lock. 87 * - Unregister the callback with the ProfileHandler. 88 * - Modify shared data. 89 * - Re-register the callback. 90 * - Release lock. 91 * and the callback code gets a lockless, read-write access to the data. 92 */ 93 typedef void (*ProfileHandlerCallback)(int sig, siginfo_t* sig_info, 94 void* ucontext, void* callback_arg); 95 96 /* 97 * Registers a new thread with profile handler and should be called only once 98 * per thread. The main thread is registered at program startup. This routine 99 * is called by the Thread module in google3/thread whenever a new thread is 100 * created. This function is not async-signal-safe. 101 */ 102 void ProfileHandlerRegisterThread(); 103 104 /* 105 * Registers a callback routine. This callback function will be called in the 106 * context of SIGPROF handler, so must be async-signal-safe. The returned token 107 * is to be used when unregistering this callback via 108 * ProfileHandlerUnregisterCallback. Registering the first callback enables 109 * the SIGPROF signal handler. Caller must not free the returned token. This 110 * function is not async-signal-safe. 111 */ 112 ProfileHandlerToken* ProfileHandlerRegisterCallback( 113 ProfileHandlerCallback callback, void* callback_arg); 114 115 /* 116 * Unregisters a previously registered callback. Expects the token returned 117 * by the corresponding ProfileHandlerRegisterCallback and asserts that the 118 * passed token is valid. Unregistering the last callback disables the SIGPROF 119 * signal handler. It waits for the currently running callback to 120 * complete before returning. This function is not async-signal-safe. 121 */ 122 void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token); 123 124 /* 125 * FOR TESTING ONLY 126 * Unregisters all the callbacks, stops the timers (if shared) and disables the 127 * SIGPROF handler. All the threads, including the main thread, need to be 128 * re-registered after this call. This function is not async-signal-safe. 129 */ 130 void ProfileHandlerReset(); 131 132 /* 133 * Stores profile handler's current state. This function is not 134 * async-signal-safe. 135 */ 136 struct ProfileHandlerState { 137 int32 frequency; /* Profiling frequency */ 138 int32 callback_count; /* Number of callbacks registered */ 139 int64 interrupts; /* Number of interrupts received */ 140 bool allowed; /* Profiling is allowed */ 141 }; 142 void ProfileHandlerGetState(struct ProfileHandlerState* state); 143 144 #ifdef __cplusplus 145 } /* extern "C" */ 146 #endif 147 148 #endif /* BASE_PROFILE_HANDLER_H_ */ 149