[runtime] New profiler API.
[mono.git] / mono / mini / mini-posix.c
index ba60bd9934a62f109dc6698bf24ad129796ebf51..a3fd4f0e2983c745e09adc7c2ec685733a8337af 100644 (file)
@@ -210,101 +210,12 @@ MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler)
        }
 }
 
-#if defined(__i386__) || defined(__x86_64__)
-#define FULL_STAT_PROFILER_BACKTRACE 1
-#define CURRENT_FRAME_GET_BASE_POINTER(f) (* (gpointer*)(f))
-#define CURRENT_FRAME_GET_RETURN_ADDRESS(f) (* (((gpointer*)(f)) + 1))
-#if MONO_ARCH_STACK_GROWS_UP
-#define IS_BEFORE_ON_STACK <
-#define IS_AFTER_ON_STACK >
-#else
-#define IS_BEFORE_ON_STACK >
-#define IS_AFTER_ON_STACK <
-#endif
-#else
-#define FULL_STAT_PROFILER_BACKTRACE 0
-#endif
-
 #if (defined (USE_POSIX_BACKEND) && defined (SIGRTMIN)) || defined (SIGPROF)
 #define HAVE_PROFILER_SIGNAL
 #endif
 
 #ifdef HAVE_PROFILER_SIGNAL
 
-static void
-per_thread_profiler_hit (void *ctx)
-{
-       int call_chain_depth = mono_profiler_stat_get_call_chain_depth ();
-       MonoProfilerCallChainStrategy call_chain_strategy = mono_profiler_stat_get_call_chain_strategy ();
-
-       if (call_chain_depth == 0) {
-               mono_profiler_stat_hit ((guchar *)mono_arch_ip_from_context (ctx), ctx);
-       } else {
-               MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
-               int current_frame_index = 1;
-               MonoContext mono_context;
-               guchar *ips [call_chain_depth + 1];
-
-               mono_sigctx_to_monoctx (ctx, &mono_context);
-               ips [0] = (guchar *)MONO_CONTEXT_GET_IP (&mono_context);
-               
-               if (jit_tls != NULL) {
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_NATIVE) {
-#if FULL_STAT_PROFILER_BACKTRACE
-                       guchar *current_frame;
-                       guchar *stack_bottom;
-                       guchar *stack_top;
-                       
-                       stack_bottom = (guchar *)jit_tls->end_of_stack;
-                       stack_top = (guchar *)MONO_CONTEXT_GET_SP (&mono_context);
-                       current_frame = (guchar *)MONO_CONTEXT_GET_BP (&mono_context);
-                       
-                       while ((current_frame_index <= call_chain_depth) &&
-                                       (stack_bottom IS_BEFORE_ON_STACK (guchar*) current_frame) &&
-                                       ((guchar*) current_frame IS_BEFORE_ON_STACK stack_top)) {
-                               ips [current_frame_index] = (guchar *)CURRENT_FRAME_GET_RETURN_ADDRESS (current_frame);
-                               current_frame_index ++;
-                               stack_top = current_frame;
-                               current_frame = (guchar *)CURRENT_FRAME_GET_BASE_POINTER (current_frame);
-                       }
-#else
-                               call_chain_strategy = MONO_PROFILER_CALL_CHAIN_GLIBC;
-#endif
-                       }
-                       
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_GLIBC) {
-#if GLIBC_PROFILER_BACKTRACE
-                               current_frame_index = backtrace ((void**) & ips [1], call_chain_depth);
-#else
-                               call_chain_strategy = MONO_PROFILER_CALL_CHAIN_MANAGED;
-#endif
-                       }
-
-                       if (call_chain_strategy == MONO_PROFILER_CALL_CHAIN_MANAGED) {
-                               MonoDomain *domain = mono_domain_get ();
-                               if (domain != NULL) {
-                                       MonoLMF *lmf = NULL;
-                                       MonoJitInfo *ji;
-                                       MonoJitInfo res;
-                                       MonoContext new_mono_context;
-                                       int native_offset;
-                                       ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
-                                                       &new_mono_context, NULL, &lmf, &native_offset, NULL);
-                                       while ((ji != NULL) && (current_frame_index <= call_chain_depth)) {
-                                               ips [current_frame_index] = (guchar *)MONO_CONTEXT_GET_IP (&new_mono_context);
-                                               current_frame_index ++;
-                                               mono_context = new_mono_context;
-                                               ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context,
-                                                               &new_mono_context, NULL, &lmf, &native_offset, NULL);
-                                       }
-                               }
-                       }
-               }
-               
-               mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx);
-       }
-}
-
 static MonoNativeThreadId sampling_thread;
 
 static gint32 profiler_signals_sent;
@@ -342,7 +253,9 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
        int hp_save_index = mono_hazard_pointer_save_for_signal_handler ();
 
        mono_thread_info_set_is_async_context (TRUE);
-       per_thread_profiler_hit (ctx);
+
+       MONO_PROFILER_RAISE (sample_hit, (mono_arch_ip_from_context (ctx), ctx));
+
        mono_thread_info_set_is_async_context (FALSE);
 
        mono_hazard_pointer_restore_for_signal_handler (hp_save_index);
@@ -521,7 +434,7 @@ static volatile gint32 sampling_thread_running;
 static clock_serv_t sampling_clock_service;
 
 static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
 {
        kern_return_t ret;
 
@@ -584,10 +497,10 @@ clock_sleep_ns_abs (guint64 ns_abs)
 clockid_t sampling_posix_clock;
 
 static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
 {
-       switch (mono_profiler_get_sampling_mode ()) {
-       case MONO_PROFILER_STAT_MODE_PROCESS: {
+       switch (mode) {
+       case MONO_PROFILER_SAMPLE_MODE_PROCESS: {
        /*
         * If we don't have clock_nanosleep (), measuring the process time
         * makes very little sense as we can only use nanosleep () to sleep on
@@ -609,7 +522,7 @@ clock_init (void)
 
                // fallthrough
        }
-       case MONO_PROFILER_STAT_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
+       case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
        default: g_assert_not_reached (); break;
        }
 }
@@ -701,8 +614,6 @@ sampling_thread_func (void *data)
        mono_threads_attach_tools_thread ();
        mono_native_thread_set_name (mono_native_thread_id_get (), "Profiler sampler");
 
-       gint64 rate = 1000000000 / mono_profiler_get_sampling_rate ();
-
        int old_policy;
        struct sched_param old_sched;
        pthread_getschedparam (pthread_self (), &old_policy, &old_sched);
@@ -724,12 +635,30 @@ sampling_thread_func (void *data)
        struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
        pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);
 
-       clock_init ();
+       MonoProfilerSampleMode mode;
+
+init:
+       mono_profiler_get_sample_mode (NULL, &mode, NULL);
 
-       guint64 sleep = clock_get_time_ns ();
+       if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
+               mono_profiler_sampling_thread_sleep ();
+               goto init;
+       }
+
+       clock_init (mode);
 
-       while (InterlockedRead (&sampling_thread_running)) {
-               sleep += rate;
+       for (guint64 sleep = clock_get_time_ns (); InterlockedRead (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
+               uint64_t freq;
+               MonoProfilerSampleMode new_mode;
+
+               mono_profiler_get_sample_mode (NULL, &new_mode, &freq);
+
+               if (new_mode != mode) {
+                       clock_cleanup ();
+                       goto init;
+               }
+
+               sleep += 1000000000 / freq;
 
                FOREACH_THREAD_SAFE (info) {
                        /* info should never be this thread as we're a tools thread. */
@@ -746,8 +675,6 @@ sampling_thread_func (void *data)
                        mono_threads_pthread_kill (info, profiler_signal);
                        InterlockedIncrement (&profiler_signals_sent);
                } FOREACH_THREAD_SAFE_END
-
-               clock_sleep_ns_abs (sleep);
        }
 
        InterlockedWrite (&sampling_thread_exiting, 1);