#define MONO_PROFILER_UNSTABLE_GC_ROOTS
#include <mono/metadata/profiler.h>
#include <mono/utils/mono-context.h>
-#include <mono/utils/mono-lazy-init.h>
#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-os-semaphore.h>
MonoProfilerHandle profilers;
- mono_lazy_init_t coverage_status;
+ gboolean code_coverage;
mono_mutex_t coverage_mutex;
GHashTable *coverage_hash;
}
MonoProfilerCoverageInfo *mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries);
-void mono_profiler_coverage_free (MonoMethod *method);
struct _MonoProfilerCallContext {
/*
InterlockedWritePointer (&handle->coverage_filter, (gpointer) cb);
}
-static void
-initialize_coverage (void)
+mono_bool
+mono_profiler_enable_coverage (void)
{
+ if (mono_profiler_state.startup_done)
+ return FALSE;
+
mono_os_mutex_init (&mono_profiler_state.coverage_mutex);
mono_profiler_state.coverage_hash = g_hash_table_new (NULL, NULL);
-}
-static void
-lazy_initialize_coverage (void)
-{
- mono_lazy_initialize (&mono_profiler_state.coverage_status, initialize_coverage);
+ if (!mono_debug_enabled ())
+ mono_debug_init (MONO_DEBUG_FORMAT_MONO);
+
+ return TRUE;
}
static void
mono_os_mutex_unlock (&mono_profiler_state.coverage_mutex);
}
-void
+mono_bool
mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb)
{
- lazy_initialize_coverage ();
+ if (!mono_profiler_state.code_coverage)
+ return FALSE;
coverage_lock ();
coverage_unlock ();
if (!info)
- return;
+ return FALSE;
MonoError error;
MonoMethodHeader *header = mono_method_get_header_checked (method, &error);
}
mono_metadata_free_mh (header);
+
+ return TRUE;
}
MonoProfilerCoverageInfo *
mono_profiler_coverage_alloc (MonoMethod *method, guint32 entries)
{
- lazy_initialize_coverage ();
+ if (!mono_profiler_state.code_coverage)
+ return FALSE;
gboolean cover = FALSE;
return info;
}
-void
-mono_profiler_coverage_free (MonoMethod *method)
-{
- lazy_initialize_coverage ();
-
- coverage_lock ();
-
- MonoProfilerCoverageInfo *info = g_hash_table_lookup (mono_profiler_state.coverage_hash, method);
-
- if (info) {
- g_hash_table_remove (mono_profiler_state.coverage_hash, method);
- g_free (info);
- }
-
- coverage_unlock ();
-}
-
mono_bool
mono_profiler_enable_sampling (MonoProfilerHandle handle)
{
/*
* Installs a profiler and returns a handle for it. The handle is used with the
- * other functions in the profiler API (e.g. for setting up callbacks).
+ * other functions in the profiler API (e.g. for setting up callbacks). The
+ * given structure pointer will be passed to all callbacks from the profiler
+ * API. It can be NULL.
*
* This function may only be called from your profiler's init function.
*
*/
MONO_API MonoProfilerHandle mono_profiler_create (MonoProfiler *prof);
+/*
+ * Enables support for code coverage instrumentation. At the moment, this means
+ * enabling the debug info subsystem. If you do not call this function, you
+ * will not be able to use mono_profiler_get_coverage_data. Returns TRUE if
+ * code coverage support was enabled, or FALSE if the function was called too
+ * late for this to be possible.
+ *
+ * This function may only be called from your profiler's init function.
+ *
+ * This function is not async safe.
+ */
+MONO_API mono_bool mono_profiler_enable_coverage (void);
+
typedef mono_bool (*MonoProfilerCoverageFilterCallback) (MonoProfiler *prof, MonoMethod *method);
/*
/*
* Retrieves all coverage data for the specified method and invokes the given
- * callback for each entry.
+ * callback for each entry. Source location information will only be filled out
+ * if the given method has debug info available. Returns TRUE if the given
+ * method was instrumented for code coverage; otherwise, FALSE.
+ *
+ * Please note that the structure passed to the callback is only valid for the
+ * duration of the callback.
*
* This function is not async safe.
*/
-MONO_API void mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
+MONO_API mono_bool mono_profiler_get_coverage_data (MonoProfilerHandle handle, MonoMethod *method, MonoProfilerCoverageCallback cb);
typedef enum {
/*
mono_profiler_set_method_exception_leave_callback (handle, method_exc_leave);
}
- if (log_config.collect_coverage)
+ if (log_config.collect_coverage) {
+ mono_profiler_enable_coverage ();
mono_profiler_set_coverage_filter_callback (handle, coverage_filter);
+ }
mono_profiler_enable_allocations ();
mono_profiler_enable_sampling (handle);