[profiler] Properly clean up the resources used by the profiler API on shutdown.
[mono.git] / mono / metadata / profiler-private.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_PRIVATE_H__
8 #define __MONO_PROFILER_PRIVATE_H__
9
10 #define MONO_PROFILER_UNSTABLE_GC_ROOTS
11 #include <mono/metadata/profiler.h>
12 #include <mono/utils/mono-context.h>
13 #include <mono/utils/mono-os-mutex.h>
14 #include <mono/utils/mono-os-semaphore.h>
15
16 struct _MonoProfilerDesc {
17         MonoProfilerHandle next;
18         MonoProfiler *prof;
19         volatile gpointer cleanup_callback;
20         volatile gpointer coverage_filter;
21         volatile gpointer call_instrumentation_filter;
22
23 #define _MONO_PROFILER_EVENT(name) \
24         volatile gpointer name ## _cb;
25 #define MONO_PROFILER_EVENT_0(name, type) \
26         _MONO_PROFILER_EVENT(name)
27 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
28         _MONO_PROFILER_EVENT(name)
29 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
30         _MONO_PROFILER_EVENT(name)
31 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
32         _MONO_PROFILER_EVENT(name)
33 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
34         _MONO_PROFILER_EVENT(name)
35 #include <mono/metadata/profiler-events.h>
36 #undef MONO_PROFILER_EVENT_0
37 #undef MONO_PROFILER_EVENT_1
38 #undef MONO_PROFILER_EVENT_2
39 #undef MONO_PROFILER_EVENT_3
40 #undef MONO_PROFILER_EVENT_4
41 #undef _MONO_PROFILER_EVENT
42 };
43
44 typedef struct {
45         gboolean startup_done;
46
47         MonoProfilerHandle profilers;
48
49         gboolean code_coverage;
50         mono_mutex_t coverage_mutex;
51         GHashTable *coverage_hash;
52
53         MonoProfilerHandle sampling_owner;
54         MonoSemType sampling_semaphore;
55         MonoProfilerSampleMode sample_mode;
56         guint32 sample_freq;
57
58         gboolean allocations;
59
60         gboolean call_contexts;
61         void (*context_enable) (void);
62         gpointer (*context_get_this) (MonoProfilerCallContext *);
63         gpointer (*context_get_argument) (MonoProfilerCallContext *, guint32);
64         gpointer (*context_get_local) (MonoProfilerCallContext *, guint32);
65         gpointer (*context_get_result) (MonoProfilerCallContext *);
66         void (*context_free_buffer) (gpointer);
67
68 #define _MONO_PROFILER_EVENT(name) \
69         volatile gint32 name ## _count;
70 #define MONO_PROFILER_EVENT_0(name, type) \
71         _MONO_PROFILER_EVENT(name)
72 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
73         _MONO_PROFILER_EVENT(name)
74 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
75         _MONO_PROFILER_EVENT(name)
76 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
77         _MONO_PROFILER_EVENT(name)
78 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
79         _MONO_PROFILER_EVENT(name)
80 #include <mono/metadata/profiler-events.h>
81 #undef MONO_PROFILER_EVENT_0
82 #undef MONO_PROFILER_EVENT_1
83 #undef MONO_PROFILER_EVENT_2
84 #undef MONO_PROFILER_EVENT_3
85 #undef MONO_PROFILER_EVENT_4
86 #undef _MONO_PROFILER_EVENT
87 } MonoProfilerState;
88
89 extern MonoProfilerState mono_profiler_state;
90
91 typedef struct {
92         guint32 entries;
93         struct {
94                 guchar *cil_code;
95                 guint32 count;
96         } data [1];
97 } MonoProfilerCoverageInfo;
98
99 void mono_profiler_started (void);
100 void mono_profiler_cleanup (void);
101
102 static inline gboolean
103 mono_profiler_installed (void)
104 {
105         return !!mono_profiler_state.profilers;
106 }
107
108 MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
109
110 struct _MonoProfilerCallContext {
111         /*
112          * Must be the first field (the JIT relies on it). Only filled out if this
113          * is a JIT frame; otherwise, zeroed.
114          */
115         MonoContext context;
116         /*
117          * A non-NULL MonoInterpFrameHandle if this is an interpreter frame.
118          */
119         gpointer interp_frame;
120         MonoMethod *method;
121         /*
122          * Points to the return value for an epilogue context. For a prologue, this
123          * is set to NULL.
124          */
125         gpointer return_value;
126 };
127
128 MonoProfilerCallInstrumentationFlags mono_profiler_get_call_instrumentation_flags (MonoMethod *method);
129
130 gboolean mono_profiler_sampling_enabled (void);
131 void mono_profiler_sampling_thread_post (void);
132 void mono_profiler_sampling_thread_wait (void);
133
134 static inline gboolean
135 mono_profiler_allocations_enabled (void)
136 {
137         return mono_profiler_state.allocations;
138 }
139
140 #define _MONO_PROFILER_EVENT(name, ...) \
141         void mono_profiler_raise_ ## name (__VA_ARGS__);
142 #define MONO_PROFILER_EVENT_0(name, type) \
143         _MONO_PROFILER_EVENT(name, void)
144 #define MONO_PROFILER_EVENT_1(name, type, arg1_type, arg1_name) \
145         _MONO_PROFILER_EVENT(name, arg1_type arg1_name)
146 #define MONO_PROFILER_EVENT_2(name, type, arg1_type, arg1_name, arg2_type, arg2_name) \
147         _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name)
148 #define MONO_PROFILER_EVENT_3(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name) \
149         _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name)
150 #define MONO_PROFILER_EVENT_4(name, type, arg1_type, arg1_name, arg2_type, arg2_name, arg3_type, arg3_name, arg4_type, arg4_name) \
151         _MONO_PROFILER_EVENT(name, arg1_type arg1_name, arg2_type arg2_name, arg3_type arg3_name, arg4_type arg4_name)
152 #include <mono/metadata/profiler-events.h>
153 #undef MONO_PROFILER_EVENT_0
154 #undef MONO_PROFILER_EVENT_1
155 #undef MONO_PROFILER_EVENT_2
156 #undef MONO_PROFILER_EVENT_3
157 #undef MONO_PROFILER_EVENT_4
158 #undef _MONO_PROFILER_EVENT
159
160 // These are the macros the rest of the runtime should use.
161
162 #define MONO_PROFILER_ENABLED(name) \
163         G_UNLIKELY (mono_profiler_state.name ## _count)
164
165 #define MONO_PROFILER_RAISE(name, args) \
166         do { \
167                 if (MONO_PROFILER_ENABLED (name)) \
168                         mono_profiler_raise_ ## name args; \
169         } while (0)
170
171 #endif // __MONO_PROFILER_PRIVATE_H__