Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / mini-posix.c
index eb0ddd11bf3b35947af70e0f7bfef37a90f68d47..331b7ca3c02bff600ca6b3d5ae8e517824bf28c1 100644 (file)
@@ -40,7 +40,6 @@
 #include <mono/metadata/threads.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
-#include "mono/metadata/profiler.h"
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/environment.h>
@@ -69,7 +68,7 @@
 
 #include "jit-icalls.h"
 
-#ifdef PLATFORM_MACOSX
+#ifdef HOST_DARWIN
 #include <mach/mach.h>
 #include <mach/mach_time.h>
 #include <mach/clock.h>
@@ -96,7 +95,7 @@ MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal)
        return FALSE;
 }
 
-#ifndef PLATFORM_MACOSX
+#ifndef HOST_DARWIN
 void
 mono_runtime_install_handlers (void)
 {
@@ -210,101 +209,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;
@@ -316,8 +226,6 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
 {
        int old_errno = errno;
 
-       InterlockedWrite (&mono_thread_info_current ()->profiler_signal_ack, 1);
-
        MONO_SIG_HANDLER_GET_CONTEXT;
 
        /* See the comment in mono_runtime_shutdown_stat_profiler (). */
@@ -336,12 +244,17 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler)
                return;
        }
 
+       // See the comment in sampling_thread_func ().
+       InterlockedWrite (&mono_thread_info_current ()->profiler_signal_ack, 1);
+
        InterlockedIncrement (&profiler_signals_accepted);
 
        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);
@@ -389,7 +302,7 @@ add_signal_handler (int signo, gpointer handler, int flags)
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
 
 /*Apple likes to deliver SIGBUS for *0 */
-#ifdef PLATFORM_MACOSX
+#ifdef HOST_DARWIN
        if (signo == SIGSEGV || signo == SIGBUS) {
 #else
        if (signo == SIGSEGV) {
@@ -483,7 +396,7 @@ mono_runtime_posix_install_handlers (void)
        add_signal_handler (SIGSEGV, mono_sigsegv_signal_handler, 0);
 }
 
-#ifndef PLATFORM_MACOSX
+#ifndef HOST_DARWIN
 void
 mono_runtime_install_handlers (void)
 {
@@ -515,12 +428,12 @@ mono_runtime_cleanup_handlers (void)
 
 static volatile gint32 sampling_thread_running;
 
-#ifdef PLATFORM_MACOSX
+#ifdef HOST_DARWIN
 
 static clock_serv_t sampling_clock_service;
 
 static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
 {
        kern_return_t ret;
 
@@ -583,10 +496,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
@@ -608,7 +521,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;
        }
 }
@@ -700,8 +613,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);
@@ -723,12 +634,34 @@ 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);
+
+       if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
+               mono_profiler_sampling_thread_wait ();
+
+               if (!InterlockedRead (&sampling_thread_running))
+                       goto done;
+
+               goto init;
+       }
+
+       clock_init (mode);
 
-       guint64 sleep = clock_get_time_ns ();
+       for (guint64 sleep = clock_get_time_ns (); InterlockedRead (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
+               uint32_t freq;
+               MonoProfilerSampleMode new_mode;
 
-       while (InterlockedRead (&sampling_thread_running)) {
-               sleep += rate;
+               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. */
@@ -745,14 +678,13 @@ 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);
-
        clock_cleanup ();
 
+done:
+       InterlockedWrite (&sampling_thread_exiting, 1);
+
        pthread_setschedparam (pthread_self (), old_policy, &old_sched);
 
        mono_thread_info_detach ();
@@ -765,7 +697,9 @@ mono_runtime_shutdown_stat_profiler (void)
 {
        InterlockedWrite (&sampling_thread_running, 0);
 
-#ifndef PLATFORM_MACOSX
+       mono_profiler_sampling_thread_post ();
+
+#ifndef HOST_DARWIN
        /*
         * There is a slight problem when we're using CLOCK_PROCESS_CPUTIME_ID: If
         * we're shutting down and there's largely no activity in the process other
@@ -821,7 +755,7 @@ mono_runtime_setup_stat_profiler (void)
         * get us a 100% sampling rate. However, this may interfere with the GC's
         * STW logic. Could perhaps be solved by taking the suspend lock.
         */
-#if defined (USE_POSIX_BACKEND) && defined (SIGRTMIN) && !defined (PLATFORM_ANDROID)
+#if defined (USE_POSIX_BACKEND) && defined (SIGRTMIN) && !defined (HOST_ANDROID)
        /* Just take the first real-time signal we can get. */
        profiler_signal = mono_threads_suspend_search_alternative_signal ();
 #else
@@ -921,7 +855,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid)
 
        memset (argv, 0, sizeof (char*) * 10);
 
-#if defined(PLATFORM_MACOSX)
+#if defined(HOST_DARWIN)
        if (native_stack_with_lldb (crashed_pid, argv, commands, commands_filename))
                goto exec;
 #endif
@@ -929,7 +863,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid)
        if (native_stack_with_gdb (crashed_pid, argv, commands, commands_filename))
                goto exec;
 
-#if !defined(PLATFORM_MACOSX)
+#if !defined(HOST_DARWIN)
        if (native_stack_with_lldb (crashed_pid, argv, commands, commands_filename))
                goto exec;
 #endif