summaryrefslogtreecommitdiff
path: root/src/profile-handler.h
blob: 4f96a18bc113ad61e23fd177efccf9640093bc33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
/* Copyright (c) 2009, Google Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ---
 * Author: Nabeel Mian
 *
 * This module manages the cpu profile timers and the associated interrupt
 * handler. When enabled, all registered threads in the program are profiled.
 * (Note: if using linux 2.4 or earlier, you must use the Thread class, in
 * google3/thread, to ensure all threads are profiled.)
 *
 * Any component interested in receiving a profile timer interrupt can do so by
 * registering a callback. All registered callbacks must be async-signal-safe.
 *
 * Note: This module requires the sole ownership of ITIMER_PROF timer and the
 * SIGPROF signal.
 */

#ifndef BASE_PROFILE_HANDLER_H_
#define BASE_PROFILE_HANDLER_H_

#include "config.h"
#include <signal.h>
#ifdef COMPILER_MSVC
#include "conflict-signal.h"
#endif
#include "base/basictypes.h"

/* All this code should be usable from within C apps. */
#ifdef __cplusplus
extern "C" {
#endif

/* Forward declaration. */
struct ProfileHandlerToken;

/*
 * Callback function to be used with ProfilefHandlerRegisterCallback. This
 * function will be called in the context of SIGPROF signal handler and must
 * be async-signal-safe. The first three arguments are the values provided by
 * the SIGPROF signal handler. We use void* to avoid using ucontext_t on
 * non-POSIX systems.
 *
 * Requirements:
 * - Callback must be async-signal-safe.
 * - None of the functions in ProfileHandler are async-signal-safe. Therefore,
 *   callback function *must* not call any of the ProfileHandler functions.
 * - Callback is not required to be re-entrant. At most one instance of
 *   callback can run at a time.
 *
 * Notes:
 * - The SIGPROF signal handler saves and restores errno, so the callback
 *   doesn't need to.
 * - Callback code *must* not acquire lock(s) to serialize access to data shared
 *   with the code outside the signal handler (callback must be
 *   async-signal-safe). If such a serialization is needed, follow the model
 *   used by profiler.cc:
 *
 *   When code other than the signal handler modifies the shared data it must:
 *   - Acquire lock.
 *   - Unregister the callback with the ProfileHandler.
 *   - Modify shared data.
 *   - Re-register the callback.
 *   - Release lock.
 *   and the callback code gets a lockless, read-write access to the data.
 */
typedef void (*ProfileHandlerCallback)(int sig, siginfo_t* sig_info,
                                       void* ucontext, void* callback_arg);

/*
 * Registers a new thread with profile handler and should be called only once
 * per thread. The main thread is registered at program startup. This routine
 * is called by the Thread module in google3/thread whenever a new thread is
 * created. This function is not async-signal-safe.
 */
void ProfileHandlerRegisterThread();

/*
 * Registers a callback routine. This callback function will be called in the
 * context of SIGPROF handler, so must be async-signal-safe. The returned token
 * is to be used when unregistering this callback via
 * ProfileHandlerUnregisterCallback. Registering the first callback enables
 * the SIGPROF signal handler. Caller must not free the returned token. This
 * function is not async-signal-safe.
 */
ProfileHandlerToken* ProfileHandlerRegisterCallback(
    ProfileHandlerCallback callback, void* callback_arg);

/*
 * Unregisters a previously registered callback. Expects the token returned
 * by the corresponding ProfileHandlerRegisterCallback and asserts that the
 * passed token is valid. Unregistering the last callback disables the SIGPROF
 * signal handler. It waits for the currently running callback to
 * complete before returning. This function is not async-signal-safe.
 */
void ProfileHandlerUnregisterCallback(ProfileHandlerToken* token);

/*
 * FOR TESTING ONLY
 * Unregisters all the callbacks, stops the timers (if shared) and disables the
 * SIGPROF handler. All the threads, including the main thread, need to be
 * re-registered after this call. This function is not async-signal-safe.
 */
void ProfileHandlerReset();

/*
 * Stores profile handler's current state. This function is not
 * async-signal-safe.
 */
struct ProfileHandlerState {
  int32 frequency;  /* Profiling frequency */
  int32 callback_count;  /* Number of callbacks registered */
  int64 interrupts;  /* Number of interrupts received */
  bool allowed; /* Profiling is allowed */
};
void ProfileHandlerGetState(struct ProfileHandlerState* state);

#ifdef __cplusplus
}  /* extern "C" */
#endif

#endif  /* BASE_PROFILE_HANDLER_H_ */