0bbc0fe00612d7200d00f1516d5eb847827ce883
[mono.git] / mono / metadata / profiler.h
1 /*
2  * Licensed to the .NET Foundation under one or more agreements.
3  * The .NET Foundation licenses this file to you under the MIT license.
4  * See the LICENSE file in the project root for more information.
5  */
6
7 #ifndef __MONO_PROFILER_H__
8 #define __MONO_PROFILER_H__
9
10 #include <mono/metadata/appdomain.h>
11 #include <mono/metadata/mono-gc.h>
12 #include <mono/metadata/object.h>
13
14 MONO_BEGIN_DECLS
15
16 /*
17  * This value will be incremented whenever breaking changes to the profiler API
18  * are made. This macro is intended for use in profiler modules that wish to
19  * support older versions of the profiler API.
20  */
21 #define MONO_PROFILER_API_VERSION 2
22
23 /*
24  * Loads a profiler module based on the specified description. The description
25  * can be of the form "name:args" or just "name". For example, "log:sample" and
26  * "log" will both load "libmono-profiler-log.so". The description is passed to
27  * the module after it has been loaded. If the specified module has already
28  * been loaded, this function has no effect.
29  *
30  * A module called foo should declare an entry point like so:
31  *
32  * void mono_profiler_init_foo (const char *desc)
33  * {
34  * }
35  *
36  * This function is not async safe.
37  */
38 MONO_API void mono_profiler_load (const char *desc);
39
40 typedef struct _MonoProfiler MonoProfiler;
41 typedef struct _MonoProfilerDesc *MonoProfilerHandle;
42
43 /*
44  * Installs a profiler and returns a handle for it. The handle is used with the
45  * other functions in the profiler API (e.g. for setting up callbacks).
46  *
47  * This function may only be called from your profiler's init function.
48  *
49  * Example usage:
50  *
51  * struct _MonoProfiler {
52  *      int my_stuff;
53  *      // ...
54  * };
55  *
56  * MonoProfiler *prof = calloc (1, sizeof (MonoProfiler));
57  * MonoProfilerHandle handle = mono_profiler_create (prof);
58  * mono_profiler_set_shutdown_callback (handle, my_shutdown_cb);
59  *
60  * This function is not async safe.
61  */
62 MONO_API MonoProfilerHandle mono_profiler_create (MonoProfiler *prof);
63
64 typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
65
66 /*
67  * Sets a code coverage filter function. The profiler API will invoke filter
68  * functions from all installed profilers. If any of them return TRUE, then the
69  * given method will be instrumented for coverage analysis. All filters are
70  * guaranteed to be called exactly once per method, even if an earlier filter
71  * has already returned TRUE.
72  *
73  * Note that filter functions must be installed before a method is compiled in
74  * order to have any effect, i.e. you should register your filter function in
75  * your profiler's init function.
76  *
77  * This function is async safe.
78  */
79 MONO_API void mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb);
80
81 typedef struct {
82         MonoMethod *method;
83         uint32_t il_offset;
84         uint32_t counter;
85         const char *file_name;
86         uint32_t line;
87         uint32_t column;
88 } MonoProfilerCoverageData;
89
90 typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProfilerCoverageData *data);
91
92 /*
93  * Retrieves all coverage data for the specified method and invokes the given
94  * callback for each entry.
95  *
96  * This function is not async safe.
97  */
98 MONO_API void mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
99
100 typedef enum {
101         /*
102          * Do not perform sampling. Will make the sampling thread sleep until the
103          * sampling mode is changed to one of the below modes.
104          */
105         MONO_PROFILER_SAMPLE_MODE_NONE = 0,
106         /*
107          * Try to base sampling frequency on process activity. Falls back to
108          * MONO_PROFILER_SAMPLE_MODE_REAL if such a clock is not available.
109          */
110         MONO_PROFILER_SAMPLE_MODE_PROCESS = 1,
111         /*
112          * Base sampling frequency on wall clock time. Uses a monotonic clock when
113          * available (all major platforms).
114          */
115         MONO_PROFILER_SAMPLE_MODE_REAL = 2,
116 } MonoProfilerSampleMode;
117
118 /*
119  * Enables the sampling thread. You must call this function if you intend to use
120  * statistical sampling; mono_profiler_set_sample_mode will have no effect if
121  * this function has not been called. The first profiler to call this function
122  * will get ownership over sampling settings (mode and frequency) so that no
123  * other profiler can change those settings. Returns TRUE if the sampling
124  * thread was enabled, or FALSE if the function was called too late for this
125  * to be possible.
126  *
127  * Note that you still need to call mono_profiler_set_sample_mode with a mode
128  * other than MONO_PROFILER_SAMPLE_MODE_NONE to actually start sampling.
129  *
130  * This function may only be called from your profiler's init function.
131  *
132  * This function is not async safe.
133  */
134 MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
135
136 /*
137  * Sets the sampling mode and frequency (in Hz). The frequency must be a
138  * positive number. If the calling profiler has ownership over sampling
139  * settings, the settings will be changed and this function will return TRUE;
140  * otherwise, it returns FALSE without changing any settings.
141  *
142  * This function is async safe.
143  */
144 MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq);
145
146 /*
147  * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
148  * the calling profiler is allowed to change the sampling settings; otherwise,
149  * FALSE.
150  *
151  * This function is async safe.
152  */
153 MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);
154
155 /*
156  * Enables instrumentation of GC allocations. This is necessary so that managed
157  * allocators can be instrumented with a call into the profiler API. Allocations
158  * will not be reported unless this function is called. Returns TRUE if
159  * allocation instrumentation was enabled, or FALSE if the function was called
160  * too late for this to be possible.
161  *
162  * This function may only be called from your profiler's init function.
163  *
164  * This function is not async safe.
165  */
166 MONO_API mono_bool mono_profiler_enable_allocations (void);
167
168 typedef enum {
169         /* Do not instrument calls. */
170         MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 1 << 0,
171         /* Instrument method prologues. */
172         MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
173         /* Instrument method epilogues. */
174         MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 2,
175 } MonoProfilerCallInstrumentationFlags;
176
177 typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
178
179 /*
180  * Sets a call instrumentation filter function. The profiler API will invoke
181  * filter functions from all installed profilers. If any of them return flags
182  * other than MONO_PROFILER_CALL_INSTRUMENTATION_NONE, then the given method
183  * will be instrumented as requested. All filters are guaranteed to be called
184  * at least once (possibly more) per method entry and exit, even if earlier
185  * filters have already specified all flags.
186  *
187  * Note that filter functions must be installed before a method is compiled in
188  * order to have any effect, i.e. you should register your filter function in
189  * your profiler's init function.
190  *
191  * Keep in mind that method instrumentation is extremely heavy and will slow
192  * down most applications to a crawl. Consider using sampling instead if it
193  * would work for your use case.
194  *
195  * This function is async safe.
196  */
197 MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
198
199 #ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
200 typedef enum {
201         /* Upper 2 bytes. */
202         MONO_PROFILER_GC_ROOT_PINNING = 1 << 8,
203         MONO_PROFILER_GC_ROOT_WEAKREF = 2 << 8,
204         MONO_PROFILER_GC_ROOT_INTERIOR = 4 << 8,
205
206         /* Lower 2 bytes (flags). */
207         MONO_PROFILER_GC_ROOT_STACK = 1 << 0,
208         MONO_PROFILER_GC_ROOT_FINALIZER = 1 << 1,
209         MONO_PROFILER_GC_ROOT_HANDLE = 1 << 2,
210         MONO_PROFILER_GC_ROOT_OTHER = 1 << 3,
211         MONO_PROFILER_GC_ROOT_MISC = 1 << 4,
212
213         MONO_PROFILER_GC_ROOT_TYPEMASK = 0xff,
214 } MonoProfilerGCRootType;
215 #endif
216
217 typedef enum {
218         /* data = MonoMethod *method */
219         MONO_PROFILER_CODE_BUFFER_METHOD = 0,
220         MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE = 1,
221         MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE = 2,
222         MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE = 3,
223         MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE = 4,
224         /* data = const char *name */
225         MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE = 5,
226         MONO_PROFILER_CODE_BUFFER_HELPER = 6,
227         MONO_PROFILER_CODE_BUFFER_MONITOR = 7,
228         MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE = 8,
229         MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
230 } MonoProfilerCodeBufferType;
231
232 typedef enum {
233         MONO_GC_EVENT_PRE_STOP_WORLD = 6,
234         /* When this event arrives, the GC and suspend locks are acquired. */
235         MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED = 10,
236         MONO_GC_EVENT_POST_STOP_WORLD = 7,
237         MONO_GC_EVENT_START = 0,
238         MONO_GC_EVENT_END = 5,
239         MONO_GC_EVENT_PRE_START_WORLD = 8,
240         /* When this event arrives, the GC and suspend locks are released. */
241         MONO_GC_EVENT_POST_START_WORLD_UNLOCKED = 11,
242         MONO_GC_EVENT_POST_START_WORLD = 9,
243 } MonoProfilerGCEvent;
244
245 /*
246  * The macros below will generate the majority of the callback API. Refer to
247  * mono/metadata/profiler-events.h for a list of callbacks. They are expanded
248  * like so:
249  *
250  * typedef void (*MonoProfilerRuntimeInitializedCallback (MonoProfiler *prof);
251  * MONO_API void mono_profiler_set_runtime_initialized_callback (MonoProfiler *prof, MonoProfilerRuntimeInitializedCallback cb);
252  *
253  * typedef void (*MonoProfilerRuntimeShutdownCallback (MonoProfiler *prof);
254  * MONO_API void mono_profiler_set_runtime_shutdown_callback (MonoProfiler *prof, MonoProfilerRuntimeShutdownCallback cb);
255  *
256  * typedef void (*MonoProfilerContextLoadedCallback (MonoProfiler *prof);
257  * MONO_API void mono_profiler_set_context_loaded_callback (MonoProfiler *prof, MonoProfilerContextLoadedCallback cb);
258  *
259  * typedef void (*MonoProfilerContextUnloadedCallback (MonoProfiler *prof);
260  * MONO_API void mono_profiler_set_context_unloaded_callback (MonoProfiler *prof, MonoProfilerContextUnloadedCallback cb);
261  *
262  * Etc.
263  *
264  * To remove a callback, pass NULL instead of a valid function pointer.
265  * Callbacks can be changed at any point, but note that doing so is inherently
266  * racy with respect to threads that aren't suspended, i.e. you may still see a
267  * call from another thread right after you change a callback.
268  *
269  * These functions are async safe.
270  */
271
272 #define _MONO_PROFILER_EVENT(type, ...) \
273         typedef void (*MonoProfiler ## type ## Callback) (__VA_ARGS__);
274 #define MONO_PROFILER_EVENT_0(name, type) \
275                 _MONO_PROFILER_EVENT(type, MonoProfiler *prof)
276 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
277                 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name)
278 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
279                 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name)
280 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
281                 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
282 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
283                 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
284 #include <mono/metadata/profiler-events.h>
285 #undef MONO_PROFILER_EVENT_0
286 #undef MONO_PROFILER_EVENT_1
287 #undef MONO_PROFILER_EVENT_2
288 #undef MONO_PROFILER_EVENT_3
289 #undef MONO_PROFILER_EVENT_4
290 #undef _MONO_PROFILER_EVENT
291
292 #define _MONO_PROFILER_EVENT(name, type) \
293         MONO_API void mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb);
294 #define MONO_PROFILER_EVENT_0(name, type) \
295         _MONO_PROFILER_EVENT(name, type)
296 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
297         _MONO_PROFILER_EVENT(name, type)
298 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
299         _MONO_PROFILER_EVENT(name, type)
300 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
301         _MONO_PROFILER_EVENT(name, type)
302 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
303         _MONO_PROFILER_EVENT(name, type)
304 #include <mono/metadata/profiler-events.h>
305 #undef MONO_PROFILER_EVENT_0
306 #undef MONO_PROFILER_EVENT_1
307 #undef MONO_PROFILER_EVENT_2
308 #undef MONO_PROFILER_EVENT_3
309 #undef MONO_PROFILER_EVENT_4
310 #undef _MONO_PROFILER_EVENT
311
312 MONO_END_DECLS
313
314 #endif // __MONO_PROFILER_H__