static ProfilerDesc *prof_list = NULL;
-#define mono_profiler_coverage_lock() EnterCriticalSection (&profiler_coverage_mutex)
-#define mono_profiler_coverage_unlock() LeaveCriticalSection (&profiler_coverage_mutex)
-static CRITICAL_SECTION profiler_coverage_mutex;
+#define mono_profiler_coverage_lock() mono_mutex_lock (&profiler_coverage_mutex)
+#define mono_profiler_coverage_unlock() mono_mutex_unlock (&profiler_coverage_mutex)
+static mono_mutex_t profiler_coverage_mutex;
/* this is directly accessible to other mono libs.
* It is the ORed value of all the profiler's events.
{
ProfilerDesc *desc = g_new0 (ProfilerDesc, 1);
if (!prof_list)
- InitializeCriticalSection (&profiler_coverage_mutex);
+ mono_mutex_init_recursive (&profiler_coverage_mutex);
desc->profiler = prof;
desc->shutdown_callback = callback;
desc->next = prof_list;
prof_list->monitor_event_cb = callback;
}
+static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
+static int64_t sampling_frequency = 1000; //1ms
+
+/**
+ * mono_profiler_set_statistical_mode:
+ * @mode the sampling mode used.
+ * @sample_frequency_is_us the sampling frequency in microseconds.
+ *
+ * Set the sampling parameters for the profiler. Sampling mode affects the effective sampling rate as in samples/s you'll witness.
+ * The default sampling mode is process mode, which only reports samples when there's activity in the process.
+ *
+ * Sampling frequency should be interpreted as a suggestion that can't always be honored due to how most kernels expose alarms.
+ *
+ * Said that, when using statistical sampling, always assume variable rate sampling as all sort of external factors can interfere.
+ */
+void
+mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_is_us)
+{
+ sampling_mode = mode;
+ sampling_frequency = sampling_frequency_is_us;
+}
+
void
mono_profiler_install_statistical (MonoProfileStatFunc callback)
{
prof_list->statistical_cb = callback;
}
+int64_t
+mono_profiler_get_sampling_rate (void)
+{
+ return sampling_frequency;
+}
+
+MonoProfileSamplingMode
+mono_profiler_get_sampling_mode (void)
+{
+ return sampling_mode;
+}
+
void
mono_profiler_install_statistical_call_chain (MonoProfileStatCallChainFunc callback, int call_chain_depth, MonoProfilerCallChainStrategy call_chain_strategy) {
if (!prof_list)
}
void
-mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, void *data) {
+mono_profiler_code_buffer_new (gpointer buffer, int size, MonoProfilerCodeBufferType type, gconstpointer data) {
ProfilerDesc *prof;
for (prof = prof_list; prof; prof = prof->next) {
if (prof->code_buffer_new)
- prof->code_buffer_new (prof->profiler, buffer, size, type, data);
+ prof->code_buffer_new (prof->profiler, buffer, size, type, (void*)data);
}
}
#define INITIALIZER_NAME "mono_profiler_startup"
+static gboolean
+load_profiler (MonoDl *pmodule, const char *desc, const char *symbol)
+{
+ char *err;
+ ProfilerInitializer func;
+
+ if (!pmodule)
+ return FALSE;
+
+ if ((err = mono_dl_symbol (pmodule, symbol, (gpointer *) &func))) {
+ g_free (err);
+ return FALSE;
+ } else {
+ func (desc);
+ }
+ return TRUE;
+}
+
+static gboolean
+load_embedded_profiler (const char *desc, const char *name)
+{
+ char *err = NULL;
+ char *symbol;
+ MonoDl *pmodule = NULL;
+ gboolean result;
+
+ pmodule = mono_dl_open (NULL, MONO_DL_LAZY, &err);
+ if (!pmodule) {
+ g_warning ("Could not open main executable (%s)", err);
+ g_free (err);
+ return FALSE;
+ }
+
+ symbol = g_strdup_printf (INITIALIZER_NAME "_%s", name);
+ result = load_profiler (pmodule, desc, symbol);
+ g_free (symbol);
+
+ return result;
+}
+
static gboolean
load_profiler_from_directory (const char *directory, const char *libname, const char *desc)
{
iter = NULL;
err = NULL;
while ((path = mono_dl_build_path (directory, libname, &iter))) {
- g_free (err);
pmodule = mono_dl_open (path, MONO_DL_LAZY, &err);
- if (pmodule) {
- ProfilerInitializer func;
- if ((err = mono_dl_symbol (pmodule, INITIALIZER_NAME, (gpointer *)&func))) {
- g_warning ("Cannot find initializer function %s in profiler module: %s (%s)", INITIALIZER_NAME, libname, err);
- g_free (err);
- err = NULL;
- } else {
- func (desc);
- }
- g_free (path);
- return TRUE;
- }
g_free (path);
+ g_free (err);
+ if (pmodule)
+ return load_profiler (pmodule, desc, INITIALIZER_NAME);
}
return FALSE;
}
+static gboolean
+load_profiler_from_mono_instalation (const char *libname, const char *desc)
+{
+ char *err = NULL;
+ MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_LAZY, &err);
+ g_free (err);
+ if (pmodule)
+ return load_profiler (pmodule, desc, INITIALIZER_NAME);
+ return FALSE;
+}
+
/**
* mono_profiler_load:
* @desc: arguments to configure the profiler
const char* col = strchr (desc, ':');
char* libname;
char *mname;
+ gboolean res = FALSE;
+
if (col != NULL) {
mname = g_memdup (desc, col - desc + 1);
mname [col - desc] = 0;
} else {
mname = g_strdup (desc);
}
- libname = g_strdup_printf ("mono-profiler-%s", mname);
- if (!load_profiler_from_directory (NULL, libname, desc))
- if (!load_profiler_from_directory (MONO_ASSEMBLIES, libname, desc))
- g_warning ("Error loading profiler module '%s'", libname);
-
- g_free (libname);
+ if (!load_embedded_profiler (desc, mname)) {
+ libname = g_strdup_printf ("mono-profiler-%s", mname);
+#if defined (MONO_ASSEMBLIES)
+ res = load_profiler_from_directory (mono_assembly_getrootdir (), libname, desc);
+#endif
+ if (!res)
+ res = load_profiler_from_directory (NULL, libname, desc);
+ if (!res)
+ res = load_profiler_from_mono_instalation (libname, desc);
+ if (!res)
+ g_warning ("The '%s' profiler wasn't found in the main executable nor could it be loaded from '%s'.", mname, libname);
+ g_free (libname);
+ }
g_free (mname);
}
g_free (cdesc);