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