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.
7 #ifndef __MONO_PROFILER_H__
8 #define __MONO_PROFILER_H__
10 #include <mono/metadata/appdomain.h>
11 #include <mono/metadata/mono-gc.h>
12 #include <mono/metadata/object.h>
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.
21 #define MONO_PROFILER_API_VERSION 2
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.
30 * A module called foo should declare an entry point like so:
32 * void mono_profiler_init_foo (const char *desc)
36 * This function is not async safe.
38 MONO_API void mono_profiler_load (const char *desc);
40 typedef struct _MonoProfiler MonoProfiler;
41 typedef struct _MonoProfilerDesc *MonoProfilerHandle;
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). The
46 * given structure pointer will be passed to all callbacks from the profiler
47 * API. It can be NULL.
49 * This function may only be called from your profiler's init function.
53 * struct _MonoProfiler {
58 * MonoProfiler *prof = calloc (1, sizeof (MonoProfiler));
59 * MonoProfilerHandle handle = mono_profiler_create (prof);
60 * mono_profiler_set_shutdown_callback (handle, my_shutdown_cb);
62 * This function is not async safe.
64 MONO_API MonoProfilerHandle mono_profiler_create (MonoProfiler *prof);
67 * Enables support for code coverage instrumentation. At the moment, this means
68 * enabling the debug info subsystem. If you do not call this function, you
69 * will not be able to use mono_profiler_get_coverage_data. Returns TRUE if
70 * code coverage support was enabled, or FALSE if the function was called too
71 * late for this to be possible.
73 * This function may only be called from your profiler's init function.
75 * This function is not async safe.
77 MONO_API mono_bool mono_profiler_enable_coverage (void);
79 typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
82 * Sets a code coverage filter function. The profiler API will invoke filter
83 * functions from all installed profilers. If any of them return TRUE, then the
84 * given method will be instrumented for coverage analysis. All filters are
85 * guaranteed to be called at least once per method, even if an earlier filter
86 * has already returned TRUE.
88 * Note that filter functions must be installed before a method is compiled in
89 * order to have any effect, i.e. you should register your filter function in
90 * your profiler's init function.
92 * This function is async safe.
94 MONO_API void mono_profiler_set_coverage_filter_callback (MonoProfilerHandle handle, MonoProfilerCoverageFilterCallback cb);
100 const char *file_name;
103 } MonoProfilerCoverageData;
105 typedef void (*MonoProfilerCoverageCallback) (MonoProfiler *prof, const MonoProfilerCoverageData *data);
108 * Retrieves all coverage data for the specified method and invokes the given
109 * callback for each entry. Source location information will only be filled out
110 * if the given method has debug info available. Returns TRUE if the given
111 * method was instrumented for code coverage; otherwise, FALSE.
113 * Please note that the structure passed to the callback is only valid for the
114 * duration of the callback.
116 * This function is not async safe.
118 MONO_API mono_bool mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
122 * Do not perform sampling. Will make the sampling thread sleep until the
123 * sampling mode is changed to one of the below modes.
125 MONO_PROFILER_SAMPLE_MODE_NONE = 0,
127 * Try to base sampling frequency on process activity. Falls back to
128 * MONO_PROFILER_SAMPLE_MODE_REAL if such a clock is not available.
130 MONO_PROFILER_SAMPLE_MODE_PROCESS = 1,
132 * Base sampling frequency on wall clock time. Uses a monotonic clock when
133 * available (all major platforms).
135 MONO_PROFILER_SAMPLE_MODE_REAL = 2,
136 } MonoProfilerSampleMode;
139 * Enables the sampling thread. You must call this function if you intend to use
140 * statistical sampling; mono_profiler_set_sample_mode will have no effect if
141 * this function has not been called. The first profiler to call this function
142 * will get ownership over sampling settings (mode and frequency) so that no
143 * other profiler can change those settings. Returns TRUE if the sampling
144 * thread was enabled, or FALSE if the function was called too late for this
147 * Note that you still need to call mono_profiler_set_sample_mode with a mode
148 * other than MONO_PROFILER_SAMPLE_MODE_NONE to actually start sampling.
150 * This function may only be called from your profiler's init function.
152 * This function is not async safe.
154 MONO_API mono_bool mono_profiler_enable_sampling (MonoProfilerHandle handle);
157 * Sets the sampling mode and frequency (in Hz). The frequency must be a
158 * positive number. If the calling profiler has ownership over sampling
159 * settings, the settings will be changed and this function will return TRUE;
160 * otherwise, it returns FALSE without changing any settings.
162 * This function is async safe.
164 MONO_API mono_bool mono_profiler_set_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode mode, uint32_t freq);
167 * Retrieves the current sampling mode and/or frequency (in Hz). Returns TRUE if
168 * the calling profiler is allowed to change the sampling settings; otherwise,
171 * This function is async safe.
173 MONO_API mono_bool mono_profiler_get_sample_mode (MonoProfilerHandle handle, MonoProfilerSampleMode *mode, uint32_t *freq);
176 * Enables instrumentation of GC allocations. This is necessary so that managed
177 * allocators can be instrumented with a call into the profiler API. Allocations
178 * will not be reported unless this function is called. Returns TRUE if
179 * allocation instrumentation was enabled, or FALSE if the function was called
180 * too late for this to be possible.
182 * This function may only be called from your profiler's init function.
184 * This function is not async safe.
186 MONO_API mono_bool mono_profiler_enable_allocations (void);
189 /* Do not instrument calls. */
190 MONO_PROFILER_CALL_INSTRUMENTATION_NONE = 0,
191 /* Instrument method prologues. */
192 MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE = 1 << 1,
193 /* Also capture a call context for prologues. */
194 MONO_PROFILER_CALL_INSTRUMENTATION_PROLOGUE_CONTEXT = 1 << 2,
195 /* Instrument method epilogues. */
196 MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE = 1 << 3,
197 /* Also capture a call context for epilogues. */
198 MONO_PROFILER_CALL_INSTRUMENTATION_EPILOGUE_CONTEXT = 1 << 4,
199 } MonoProfilerCallInstrumentationFlags;
201 typedef MonoProfilerCallInstrumentationFlags (*MonoProfilerCallInstrumentationFilterCallback) (MonoProfiler *prof, MonoMethod *method);
204 * Sets a call instrumentation filter function. The profiler API will invoke
205 * filter functions from all installed profilers. If any of them return flags
206 * other than MONO_PROFILER_CALL_INSTRUMENTATION_NONE, then the given method
207 * will be instrumented as requested. All filters are guaranteed to be called
208 * exactly once per method, even if earlier filters have already specified all
211 * Note that filter functions must be installed before a method is compiled in
212 * order to have any effect, i.e. you should register your filter function in
213 * your profiler's init function. Also, if you want to instrument a method
214 * that's going to be AOT-compiled, you must attach your profiler and install a
215 * call instrumentation filter function at AOT time. This can be done in
216 * exactly the same way as you would normally, i.e. by passing the --profile
217 * option on the command line, by calling mono_profiler_load, or simply by
218 * using the profiler API as an embedder.
220 * Keep in mind that indiscriminate method instrumentation is extremely heavy
221 * and will slow down most applications to a crawl. Consider using sampling
222 * instead if it would work for your use case.
224 * This function is async safe.
226 MONO_API void mono_profiler_set_call_instrumentation_filter_callback (MonoProfilerHandle handle, MonoProfilerCallInstrumentationFilterCallback cb);
229 * Enables support for retrieving stack frame data from a call context. At the
230 * moment, this means enabling the debug info subsystem. If you do not call
231 * this function, you will not be able to use the call context introspection
232 * functions (they will simply return NULL). Returns TRUE if call context
233 * introspection was enabled, or FALSE if the function was called too late for
234 * this to be possible.
236 * Please note: Mono's LLVM backend does not support this feature. This means
237 * that methods with call context instrumentation will be handled by Mono's
238 * JIT even in LLVM mode. There is also a special case when Mono is compiling
239 * in LLVM-only mode: Since LLVM does not provide a way to implement call
240 * contexts, a NULL context will always be passed to enter/leave events even
241 * though this method returns TRUE.
243 * This function may only be called from your profiler's init function.
245 * This function is not async safe.
247 MONO_API mono_bool mono_profiler_enable_call_context_introspection (void);
249 typedef struct _MonoProfilerCallContext MonoProfilerCallContext;
252 * Given a valid call context from an enter/leave event, retrieves a pointer to
253 * the this reference for the method. Returns NULL if none exists (i.e. it's a
254 * static method) or if call context introspection was not enabled.
256 * The buffer returned by this function must be freed with
257 * mono_profiler_call_context_free_buffer.
259 * Please note that a call context is only valid for the duration of the
260 * enter/leave callback it was passed to.
262 * This function is not async safe.
264 MONO_API void *mono_profiler_call_context_get_this (MonoProfilerCallContext *context);
267 * Given a valid call context from an enter/leave event, retrieves a pointer to
268 * the method argument at the given position. Returns NULL if position is out
269 * of bounds or if call context introspection was not enabled.
271 * The buffer returned by this function must be freed with
272 * mono_profiler_call_context_free_buffer.
274 * Please note that a call context is only valid for the duration of the
275 * enter/leave callback it was passed to.
277 * This function is not async safe.
279 MONO_API void *mono_profiler_call_context_get_argument (MonoProfilerCallContext *context, uint32_t position);
282 * Given a valid call context from an enter/leave event, retrieves a pointer to
283 * the local variable at the given position. Returns NULL if position is out of
284 * bounds or if call context introspection was not enabled.
286 * The buffer returned by this function must be freed with
287 * mono_profiler_call_context_free_buffer.
289 * Please note that a call context is only valid for the duration of the
290 * enter/leave callback it was passed to.
292 * This function is not async safe.
294 MONO_API void *mono_profiler_call_context_get_local (MonoProfilerCallContext *context, uint32_t position);
297 * Given a valid call context from an enter/leave event, retrieves a pointer to
298 * return value of a method. Returns NULL if the method has no return value
299 * (i.e. it returns void), if the leave event was the result of a tail call, if
300 * the function is called on a context from an enter event, or if call context
301 * introspection was not enabled.
303 * The buffer returned by this function must be freed with
304 * mono_profiler_call_context_free_buffer.
306 * Please note that a call context is only valid for the duration of the
307 * enter/leave callback it was passed to.
309 * This function is not async safe.
311 MONO_API void *mono_profiler_call_context_get_result (MonoProfilerCallContext *context);
314 * Frees a buffer returned by one of the call context introspection functions.
315 * Passing a NULL buffer is allowed, which makes this function a no-op.
317 * This function is not async safe.
319 MONO_API void mono_profiler_call_context_free_buffer (void *buffer);
321 #ifdef MONO_PROFILER_UNSTABLE_GC_ROOTS
324 MONO_PROFILER_GC_ROOT_PINNING = 1 << 8,
325 MONO_PROFILER_GC_ROOT_WEAKREF = 2 << 8,
326 MONO_PROFILER_GC_ROOT_INTERIOR = 4 << 8,
328 /* Lower 2 bytes (flags). */
329 MONO_PROFILER_GC_ROOT_STACK = 1 << 0,
330 MONO_PROFILER_GC_ROOT_FINALIZER = 1 << 1,
331 MONO_PROFILER_GC_ROOT_HANDLE = 1 << 2,
332 MONO_PROFILER_GC_ROOT_OTHER = 1 << 3,
333 MONO_PROFILER_GC_ROOT_MISC = 1 << 4,
335 MONO_PROFILER_GC_ROOT_TYPEMASK = 0xff,
336 } MonoProfilerGCRootType;
340 /* data = MonoMethod *method */
341 MONO_PROFILER_CODE_BUFFER_METHOD = 0,
342 MONO_PROFILER_CODE_BUFFER_METHOD_TRAMPOLINE = 1,
343 MONO_PROFILER_CODE_BUFFER_UNBOX_TRAMPOLINE = 2,
344 MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE = 3,
345 MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE = 4,
346 /* data = const char *name */
347 MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE = 5,
348 MONO_PROFILER_CODE_BUFFER_HELPER = 6,
349 MONO_PROFILER_CODE_BUFFER_MONITOR = 7,
350 MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE = 8,
351 MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING = 9,
352 } MonoProfilerCodeBufferType;
355 MONO_GC_EVENT_PRE_STOP_WORLD = 6,
356 /* When this event arrives, the GC and suspend locks are acquired. */
357 MONO_GC_EVENT_PRE_STOP_WORLD_LOCKED = 10,
358 MONO_GC_EVENT_POST_STOP_WORLD = 7,
359 MONO_GC_EVENT_START = 0,
360 MONO_GC_EVENT_END = 5,
361 MONO_GC_EVENT_PRE_START_WORLD = 8,
362 /* When this event arrives, the GC and suspend locks are released. */
363 MONO_GC_EVENT_POST_START_WORLD_UNLOCKED = 11,
364 MONO_GC_EVENT_POST_START_WORLD = 9,
365 } MonoProfilerGCEvent;
368 * The macros below will generate the majority of the callback API. Refer to
369 * mono/metadata/profiler-events.h for a list of callbacks. They are expanded
372 * typedef void (*MonoProfilerRuntimeInitializedCallback (MonoProfiler *prof);
373 * MONO_API void mono_profiler_set_runtime_initialized_callback (MonoProfiler *prof, MonoProfilerRuntimeInitializedCallback cb);
375 * typedef void (*MonoProfilerRuntimeShutdownCallback (MonoProfiler *prof);
376 * MONO_API void mono_profiler_set_runtime_shutdown_callback (MonoProfiler *prof, MonoProfilerRuntimeShutdownCallback cb);
378 * typedef void (*MonoProfilerContextLoadedCallback (MonoProfiler *prof);
379 * MONO_API void mono_profiler_set_context_loaded_callback (MonoProfiler *prof, MonoProfilerContextLoadedCallback cb);
381 * typedef void (*MonoProfilerContextUnloadedCallback (MonoProfiler *prof);
382 * MONO_API void mono_profiler_set_context_unloaded_callback (MonoProfiler *prof, MonoProfilerContextUnloadedCallback cb);
386 * To remove a callback, pass NULL instead of a valid function pointer.
387 * Callbacks can be changed at any point, but note that doing so is inherently
388 * racy with respect to threads that aren't suspended, i.e. you may still see a
389 * call from another thread right after you change a callback.
391 * These functions are async safe.
394 #define _MONO_PROFILER_EVENT(type, ...) \
395 typedef void (*MonoProfiler ## type ## Callback) (__VA_ARGS__);
396 #define MONO_PROFILER_EVENT_0(name, type) \
397 _MONO_PROFILER_EVENT(type, MonoProfiler *prof)
398 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
399 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name)
400 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
401 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name)
402 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
403 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
404 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
405 _MONO_PROFILER_EVENT(type, MonoProfiler *prof, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
406 #include <mono/metadata/profiler-events.h>
407 #undef MONO_PROFILER_EVENT_0
408 #undef MONO_PROFILER_EVENT_1
409 #undef MONO_PROFILER_EVENT_2
410 #undef MONO_PROFILER_EVENT_3
411 #undef MONO_PROFILER_EVENT_4
412 #undef _MONO_PROFILER_EVENT
414 #define _MONO_PROFILER_EVENT(name, type) \
415 MONO_API void mono_profiler_set_ ## name ## _callback (MonoProfilerHandle handle, MonoProfiler ## type ## Callback cb);
416 #define MONO_PROFILER_EVENT_0(name, type) \
417 _MONO_PROFILER_EVENT(name, type)
418 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
419 _MONO_PROFILER_EVENT(name, type)
420 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
421 _MONO_PROFILER_EVENT(name, type)
422 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
423 _MONO_PROFILER_EVENT(name, type)
424 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
425 _MONO_PROFILER_EVENT(name, type)
426 #include <mono/metadata/profiler-events.h>
427 #undef MONO_PROFILER_EVENT_0
428 #undef MONO_PROFILER_EVENT_1
429 #undef MONO_PROFILER_EVENT_2
430 #undef MONO_PROFILER_EVENT_3
431 #undef MONO_PROFILER_EVENT_4
432 #undef _MONO_PROFILER_EVENT
436 #endif // __MONO_PROFILER_H__