[docs] Update formatting in mono-api-security.
[mono.git] / mono / metadata / profiler.c
index bb8579e7ad904bc4ebf04bbde85ce61ddf6e9a74..4b81e2ebd9ba34d7bc6b18bef6870f243145ba95 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * profiler.c: Profiler interface for Mono
+/**
+ * \file
+ * Profiler interface for Mono
  *
  * Author:
  *   Paolo Molaro (lupus@ximian.com)
 #include "mono/metadata/assembly.h"
 #include "mono/metadata/debug-helpers.h"
 #include "mono/metadata/mono-debug.h"
-#include "mono/metadata/debug-mono-symfile.h"
+#include "mono/metadata/debug-internals.h"
 #include "mono/metadata/metadata-internals.h"
 #include "mono/metadata/class-internals.h"
 #include "mono/metadata/domain-internals.h"
 #include "mono/metadata/gc-internals.h"
 #include "mono/metadata/mono-config-dirs.h"
-#include "mono/io-layer/io-layer.h"
 #include "mono/utils/mono-dl.h"
 #include <mono/utils/mono-logger-internals.h>
 #include <string.h>
@@ -102,6 +102,11 @@ struct _ProfilerDesc {
        MonoProfileGCHandleFunc  gc_handle;
        MonoProfileGCRootFunc    gc_roots;
 
+       MonoProfileGCFinalizeFunc gc_finalize_begin;
+       MonoProfileGCFinalizeObjectFunc gc_finalize_object_begin;
+       MonoProfileGCFinalizeObjectFunc gc_finalize_object_end;
+       MonoProfileGCFinalizeFunc gc_finalize_end;
+
        MonoProfileFunc          runtime_initialized_event;
 
        MonoProfilerCodeChunkNew code_chunk_new;
@@ -122,14 +127,12 @@ MonoProfileFlags mono_profiler_events;
 
 /**
  * mono_profiler_install:
- * @prof: a MonoProfiler structure pointer, or a pointer to a derived structure.
- * @callback: the function to invoke at shutdown
- *
- * Use mono_profiler_install to activate profiling in the Mono runtime.
+ * \param prof a \c MonoProfiler structure pointer, or a pointer to a derived structure.
+ * \param callback the function to invoke at shutdown
+ * Use \c mono_profiler_install to activate profiling in the Mono runtime.
  * Typically developers of new profilers will create a new structure whose
- * first field is a MonoProfiler and put any extra information that they need
+ * first field is a \c MonoProfiler and put any extra information that they need
  * to access from the various profiling callbacks there.
- *
  */
 void
 mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
@@ -145,16 +148,15 @@ mono_profiler_install (MonoProfiler *prof, MonoProfileFunc callback)
 
 /**
  * mono_profiler_set_events:
- * @events: an ORed set of values made up of MONO_PROFILER_ flags
- *
- * The events descriped in the @events argument is a set of flags
+ * \param events an ORed set of values made up of \c MONO_PROFILER_ flags
+ * The events described in the \p events argument is a set of flags
  * that represent which profiling events must be triggered.  For
  * example if you have registered a set of methods for tracking
- * JIT compilation start and end with mono_profiler_install_jit_compile,
- * you will want to pass the MONO_PROFILE_JIT_COMPILATION flag to
+ * JIT compilation start and end with \c mono_profiler_install_jit_compile,
+ * you will want to pass the \c MONO_PROFILE_JIT_COMPILATION flag to
  * this routine.
  *
- * You can call mono_profile_set_events more than once and you can
+ * You can call \c mono_profile_set_events more than once and you can
  * do this at runtime to modify which methods are invoked.
  */
 void
@@ -182,12 +184,12 @@ mono_profiler_get_events (void)
 
 /**
  * mono_profiler_install_enter_leave:
- * @enter: the routine to be called on each method entry
- * @fleave: the routine to be called each time a method returns
+ * \param enter the routine to be called on each method entry
+ * \param fleave the routine to be called each time a method returns
  *
  * Use this routine to install routines that will be called everytime
  * a method enters and leaves.   The routines will receive as an argument
- * the MonoMethod representing the method that is entering or leaving.
+ * the \c MonoMethod representing the method that is entering or leaving.
  */
 void
 mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMethodFunc fleave)
@@ -200,8 +202,8 @@ mono_profiler_install_enter_leave (MonoProfileMethodFunc enter, MonoProfileMetho
 
 /**
  * mono_profiler_install_jit_compile:
- * @start: the routine to be called when the JIT process starts.
- * @end: the routine to be called when the JIT process ends.
+ * \param start the routine to be called when the JIT process starts.
+ * \param end the routine to be called when the JIT process ends.
  *
  * Use this routine to install routines that will be called when JIT 
  * compilation of a method starts and completes.
@@ -240,6 +242,9 @@ mono_profiler_install_method_invoke (MonoProfileMethodFunc start, MonoProfileMet
        prof_list->method_end_invoke = end;
 }
 
+/**
+ * mono_profiler_install_thread:
+ */
 void 
 mono_profiler_install_thread (MonoProfileThreadFunc start, MonoProfileThreadFunc end)
 {
@@ -257,6 +262,9 @@ mono_profiler_install_thread_name (MonoProfileThreadNameFunc thread_name_cb)
        prof_list->thread_name = thread_name_cb;
 }
 
+/**
+ * mono_profiler_install_transition:
+ */
 void 
 mono_profiler_install_transition (MonoProfileMethodResult callback)
 {
@@ -265,10 +273,12 @@ mono_profiler_install_transition (MonoProfileMethodResult callback)
        prof_list->man_unman_transition = callback;
 }
 
+/**
+ * mono_profiler_install_allocation:
+ */
 void 
 mono_profiler_install_allocation (MonoProfileAllocFunc callback)
 {
-       mono_gc_enable_alloc_events ();
        if (!prof_list)
                return;
        prof_list->allocation_cb = callback;
@@ -283,12 +293,12 @@ mono_profiler_install_monitor  (MonoProfileMonitorFunc callback)
 }
 
 static MonoProfileSamplingMode sampling_mode = MONO_PROFILER_STAT_MODE_PROCESS;
-static int64_t sampling_frequency = 1000; //1ms
+static int64_t sampling_frequency = 100; // Hz
 
 /**
  * mono_profiler_set_statistical_mode:
- * @mode the sampling mode used.
- * @sample_frequency_is_us the sampling frequency in microseconds.
+ * \param mode the sampling mode used.
+ * \param 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.
@@ -298,12 +308,15 @@ static int64_t sampling_frequency = 1000; //1ms
  * 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)
+mono_profiler_set_statistical_mode (MonoProfileSamplingMode mode, int64_t sampling_frequency_hz)
 {
        sampling_mode = mode;
-       sampling_frequency = sampling_frequency_is_us;
+       sampling_frequency = sampling_frequency_hz;
 }
 
+/**
+ * mono_profiler_install_statistical:
+ */
 void 
 mono_profiler_install_statistical (MonoProfileStatFunc callback)
 {
@@ -366,6 +379,9 @@ void mono_profiler_install_exception (MonoProfileExceptionFunc throw_callback, M
        prof_list->exception_clause_cb = clause_callback;
 }
 
+/**
+ * mono_profiler_install_coverage_filter:
+ */
 void 
 mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
 {
@@ -374,6 +390,9 @@ mono_profiler_install_coverage_filter (MonoProfileCoverageFilterFunc callback)
        prof_list->coverage_filter_cb = callback;
 }
 
+/**
+ * mono_profiler_install_appdomain:
+ */
 void 
 mono_profiler_install_appdomain   (MonoProfileAppDomainFunc start_load, MonoProfileAppDomainResult end_load,
                                    MonoProfileAppDomainFunc start_unload, MonoProfileAppDomainFunc end_unload)
@@ -406,6 +425,9 @@ mono_profiler_install_context (MonoProfileContextFunc load, MonoProfileContextFu
        prof_list->context_unload = unload;
 }
 
+/**
+ * mono_profiler_install_assembly:
+ */
 void 
 mono_profiler_install_assembly    (MonoProfileAssemblyFunc start_load, MonoProfileAssemblyResult end_load,
                                    MonoProfileAssemblyFunc start_unload, MonoProfileAssemblyFunc end_unload)
@@ -418,6 +440,9 @@ mono_profiler_install_assembly    (MonoProfileAssemblyFunc start_load, MonoProfi
        prof_list->assembly_end_unload = end_unload;
 }
 
+/**
+ * mono_profiler_install_module:
+ */
 void 
 mono_profiler_install_module      (MonoProfileModuleFunc start_load, MonoProfileModuleResult end_load,
                                    MonoProfileModuleFunc start_unload, MonoProfileModuleFunc end_unload)
@@ -430,6 +455,9 @@ mono_profiler_install_module      (MonoProfileModuleFunc start_load, MonoProfile
        prof_list->module_end_unload = end_unload;
 }
 
+/**
+ * mono_profiler_install_class:
+ */
 void
 mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoProfileClassResult end_load,
                                    MonoProfileClassFunc start_unload, MonoProfileClassFunc end_unload)
@@ -442,6 +470,9 @@ mono_profiler_install_class       (MonoProfileClassFunc start_load, MonoProfileC
        prof_list->class_end_unload = end_unload;
 }
 
+/**
+ * mono_profiler_method_enter:
+ */
 void
 mono_profiler_method_enter (MonoMethod *method)
 {
@@ -452,6 +483,9 @@ mono_profiler_method_enter (MonoMethod *method)
        }
 }
 
+/**
+ * mono_profiler_method_leave:
+ */
 void
 mono_profiler_method_leave (MonoMethod *method)
 {
@@ -462,6 +496,9 @@ mono_profiler_method_leave (MonoMethod *method)
        }
 }
 
+/**
+ * mono_profiler_method_jit:
+ */
 void 
 mono_profiler_method_jit (MonoMethod *method)
 {
@@ -472,6 +509,9 @@ mono_profiler_method_jit (MonoMethod *method)
        }
 }
 
+/**
+ * mono_profiler_method_end_jit:
+ */
 void 
 mono_profiler_method_end_jit (MonoMethod *method, MonoJitInfo* jinfo, int result)
 {
@@ -516,6 +556,9 @@ mono_profiler_method_end_invoke (MonoMethod *method)
        }
 }
 
+/**
+ * mono_profiler_code_transition:
+ */
 void 
 mono_profiler_code_transition (MonoMethod *method, int result)
 {
@@ -526,6 +569,9 @@ mono_profiler_code_transition (MonoMethod *method, int result)
        }
 }
 
+/**
+ * mono_profiler_allocation:
+ */
 void 
 mono_profiler_allocation (MonoObject *obj)
 {
@@ -545,6 +591,9 @@ mono_profiler_monitor_event      (MonoObject *obj, MonoProfilerMonitorEvent even
        }
 }
 
+/**
+ * mono_profiler_stat_hit:
+ */
 void
 mono_profiler_stat_hit (guchar *ip, void *context)
 {
@@ -595,6 +644,9 @@ mono_profiler_exception_clause_handler (MonoMethod *method, int clause_type, int
        }
 }
 
+/**
+ * mono_profiler_thread_start:
+ */
 void
 mono_profiler_thread_start (gsize tid)
 {
@@ -605,6 +657,9 @@ mono_profiler_thread_start (gsize tid)
        }
 }
 
+/**
+ * mono_profiler_thread_end:
+ */
 void 
 mono_profiler_thread_end (gsize tid)
 {
@@ -625,6 +680,9 @@ mono_profiler_thread_name (gsize tid, const char *name)
        }
 }
 
+/**
+ * mono_profiler_assembly_event:
+ */
 void 
 mono_profiler_assembly_event  (MonoAssembly *assembly, int code)
 {
@@ -652,6 +710,9 @@ mono_profiler_assembly_event  (MonoAssembly *assembly, int code)
        }
 }
 
+/**
+ * mono_profiler_assembly_loaded:
+ */
 void 
 mono_profiler_assembly_loaded (MonoAssembly *assembly, int result)
 {
@@ -671,6 +732,9 @@ void mono_profiler_iomap (char *report, const char *pathname, const char *new_pa
        }
 }
 
+/**
+ * mono_profiler_module_event:
+ */
 void 
 mono_profiler_module_event  (MonoImage *module, int code)
 {
@@ -698,6 +762,9 @@ mono_profiler_module_event  (MonoImage *module, int code)
        }
 }
 
+/**
+ * mono_profiler_module_loaded:
+ */
 void 
 mono_profiler_module_loaded (MonoImage *module, int result)
 {
@@ -708,6 +775,9 @@ mono_profiler_module_loaded (MonoImage *module, int result)
        }
 }
 
+/**
+ * mono_profiler_class_event:
+ */
 void 
 mono_profiler_class_event  (MonoClass *klass, int code)
 {
@@ -735,6 +805,9 @@ mono_profiler_class_event  (MonoClass *klass, int code)
        }
 }
 
+/**
+ * mono_profiler_class_loaded:
+ */
 void 
 mono_profiler_class_loaded (MonoClass *klass, int result)
 {
@@ -745,6 +818,9 @@ mono_profiler_class_loaded (MonoClass *klass, int result)
        }
 }
 
+/**
+ * mono_profiler_appdomain_event:
+ */
 void 
 mono_profiler_appdomain_event  (MonoDomain *domain, int code)
 {
@@ -772,6 +848,9 @@ mono_profiler_appdomain_event  (MonoDomain *domain, int code)
        }
 }
 
+/**
+ * mono_profiler_appdomain_loaded:
+ */
 void 
 mono_profiler_appdomain_loaded (MonoDomain *domain, int result)
 {
@@ -806,6 +885,9 @@ mono_profiler_context_unloaded (MonoAppContext *context)
                        prof->context_unload (prof->profiler, context);
 }
 
+/**
+ * mono_profiler_shutdown:
+ */
 void 
 mono_profiler_shutdown (void)
 {
@@ -818,6 +900,9 @@ mono_profiler_shutdown (void)
        mono_profiler_set_events ((MonoProfileFlags)0);
 }
 
+/**
+ * mono_profiler_gc_heap_resize:
+ */
 void
 mono_profiler_gc_heap_resize (gint64 new_size)
 {
@@ -828,6 +913,9 @@ mono_profiler_gc_heap_resize (gint64 new_size)
        }
 }
 
+/**
+ * mono_profiler_gc_event:
+ */
 void
 mono_profiler_gc_event (MonoGCEvent event, int generation)
 {
@@ -868,10 +956,12 @@ mono_profiler_gc_roots (int num, void **objects, int *root_types, uintptr_t *ext
        }
 }
 
+/**
+ * mono_profiler_install_gc:
+ */
 void
 mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
 {
-       mono_gc_enable_events ();
        if (!prof_list)
                return;
        prof_list->gc_event = callback;
@@ -880,9 +970,9 @@ mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc he
 
 /**
  * mono_profiler_install_gc_moves:
- * @callback: callback function
+ * \param callback callback function
  *
- * Install the @callback function that the GC will call when moving objects.
+ * Install the \p callback function that the GC will call when moving objects.
  * The callback receives an array of pointers and the number of elements
  * in the array. Every even element in the array is the original object location
  * and the following odd element is the new location of the object in memory.
@@ -902,15 +992,15 @@ mono_profiler_install_gc_moves (MonoProfileGCMoveFunc callback)
 
 /**
  * mono_profiler_install_gc_roots:
- * @handle_callback: callback function
- * @roots_callback: callback function
+ * \param handle_callback callback function
+ * \param roots_callback callback function
  *
- * Install the @handle_callback function that the GC will call when GC
+ * Install the \p handle_callback function that the GC will call when GC
  * handles are created or destroyed.
- * The callback receives an operation, which is either #MONO_PROFILER_GC_HANDLE_CREATED
- * or #MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
+ * The callback receives an operation, which is either \c MONO_PROFILER_GC_HANDLE_CREATED
+ * or \c MONO_PROFILER_GC_HANDLE_DESTROYED, the handle type, the handle value and the
  * object pointer, if present.
- * Install the @roots_callback function that the GC will call when tracing
+ * Install the \p roots_callback function that the GC will call when tracing
  * the roots for a collection.
  * The callback receives the number of elements and three arrays: an array
  * of objects, an array of root types and flags and an array of extra info.
@@ -925,6 +1015,50 @@ mono_profiler_install_gc_roots (MonoProfileGCHandleFunc handle_callback, MonoPro
        prof_list->gc_roots = roots_callback;
 }
 
+void
+mono_profiler_gc_finalize_begin (void)
+{
+       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
+               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_begin)
+                       prof->gc_finalize_begin (prof->profiler);
+}
+
+void
+mono_profiler_gc_finalize_object_begin (MonoObject *obj)
+{
+       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
+               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_begin)
+                       prof->gc_finalize_object_begin (prof->profiler, obj);
+}
+
+void
+mono_profiler_gc_finalize_object_end (MonoObject *obj)
+{
+       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
+               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_object_end)
+                       prof->gc_finalize_object_end (prof->profiler, obj);
+}
+
+void
+mono_profiler_gc_finalize_end (void)
+{
+       for (ProfilerDesc *prof = prof_list; prof; prof = prof->next)
+               if ((prof->events & MONO_PROFILE_GC_FINALIZATION) && prof->gc_finalize_end)
+                       prof->gc_finalize_end (prof->profiler);
+}
+
+void
+mono_profiler_install_gc_finalize (MonoProfileGCFinalizeFunc begin, MonoProfileGCFinalizeObjectFunc begin_obj, MonoProfileGCFinalizeObjectFunc end_obj, MonoProfileGCFinalizeFunc end)
+{
+       if (!prof_list)
+               return;
+
+       prof_list->gc_finalize_begin = begin;
+       prof_list->gc_finalize_object_begin = begin_obj;
+       prof_list->gc_finalize_object_end = end_obj;
+       prof_list->gc_finalize_end = end;
+}
+
 void
 mono_profiler_install_runtime_initialized (MonoProfileFunc runtime_initialized_callback)
 {
@@ -1052,15 +1186,15 @@ mono_profiler_coverage_free (MonoMethod *method)
 
 /**
  * mono_profiler_coverage_get:
- * @prof: The profiler handle, installed with mono_profiler_install
- * @method: the method to gather information from.
- * @func: A routine that will be called back with the results
+ * \param prof The profiler handle, installed with mono_profiler_install
+ * \param method the method to gather information from.
+ * \param func A routine that will be called back with the results
  *
- * If the MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
- * it is posisble to obtain coverage information about a give method.
+ * If the \c MONO_PROFILER_INS_COVERAGE flag was active during JIT compilation
+ * it is possible to obtain coverage information about a give method.
  *
- * The function @func will be invoked repeatedly with instances of the
- * MonoProfileCoverageEntry structure.
+ * The function \p func will be invoked repeatedly with instances of the
+ * \c MonoProfileCoverageEntry structure.
  */
 void 
 mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileCoverageFunc func)
@@ -1101,7 +1235,7 @@ mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileC
                        if (debug_minfo) {
                                MonoDebugSourceLocation *location;
 
-                               location = mono_debug_symfile_lookup_location (debug_minfo, offset);
+                               location = mono_debug_method_lookup_location (debug_minfo, offset);
                                if (location) {
                                        entry.line = location->row;
                                        entry.col = location->column;
@@ -1147,7 +1281,15 @@ load_embedded_profiler (const char *desc, const char *name)
        MonoDl *pmodule = NULL;
        gboolean result;
 
-       pmodule = mono_dl_open (NULL, MONO_DL_LAZY, &err);
+       /*
+        * Some profilers (such as ours) may need to call back into the runtime
+        * from their sampling callback (which is called in async-signal context).
+        * They need to be able to know that all references back to the runtime
+        * have been resolved; otherwise, calling runtime functions may result in
+        * invoking the dynamic linker which is not async-signal-safe. Passing
+        * MONO_DL_EAGER will ask the dynamic linker to resolve everything upfront.
+        */
+       pmodule = mono_dl_open (NULL, MONO_DL_EAGER, &err);
        if (!pmodule) {
                g_warning ("Could not open main executable (%s)", err);
                g_free (err);
@@ -1175,7 +1317,7 @@ load_profiler_from_directory (const char *directory, const char *libname, const
        iter = NULL;
        err = NULL;
        while ((path = mono_dl_build_path (directory, libname, &iter))) {
-               pmodule = mono_dl_open (path, MONO_DL_LAZY, &err);
+               pmodule = mono_dl_open (path, MONO_DL_EAGER, &err);
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler: %s, %ssuccessful, err: %s", path, pmodule?"":"not ", err);
                g_free (path);
                g_free (err);
@@ -1190,7 +1332,7 @@ static gboolean
 load_profiler_from_mono_installation (const char *libname, const char *desc)
 {
        char *err = NULL;
-       MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_LAZY, &err);
+       MonoDl *pmodule = mono_dl_open_runtime_lib (libname, MONO_DL_EAGER, &err);
        mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "Attempting to load profiler from runtime libs: %s, %ssuccessful, err: %s", libname, pmodule?"":"not ", err);
        g_free (err);
        if (pmodule)
@@ -1200,7 +1342,7 @@ load_profiler_from_mono_installation (const char *libname, const char *desc)
 
 /**
  * mono_profiler_load:
- * @desc: arguments to configure the profiler
+ * \param desc arguments to configure the profiler
  *
  * Invoke this method to initialize the profiler.   This will drive the
  * loading of the internal ("default") or any external profilers.