X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-posix.c;h=a3fd4f0e2983c745e09adc7c2ec685733a8337af;hb=076e44ac27c1062a55fe26f74a1603bf1837d5c6;hp=f07b84d47f68a2c7cca51efa71532834c7ad5069;hpb=79219ca718a07c3d4fe82d69b2a94dd1366e0314;p=mono.git diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index f07b84d47f6..a3fd4f0e298 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -1,5 +1,6 @@ -/* - * mini-posix.c: POSIX signal handling support for Mono. +/** + * \file + * POSIX signal handling support for Mono. * * Authors: * Mono Team (mono-list@lists.ximian.com) @@ -39,7 +40,6 @@ #include #include #include -#include #include "mono/metadata/profiler.h" #include #include @@ -75,7 +75,7 @@ #include #endif -#if defined(__native_client__) || defined(HOST_WATCHOS) +#if defined(HOST_WATCHOS) void mono_runtime_setup_stat_profiler (void) @@ -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; @@ -315,7 +226,7 @@ static gint32 profiler_interrupt_signals_received; MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler) { int old_errno = errno; - int hp_save_index; + MONO_SIG_HANDLER_GET_CONTEXT; /* See the comment in mono_runtime_shutdown_stat_profiler (). */ @@ -326,21 +237,29 @@ MONO_SIG_HANDLER_FUNC (static, profiler_signal_handler) InterlockedIncrement (&profiler_signals_received); - if (mono_thread_info_get_small_id () == -1) - return; //an non-attached thread got the signal + // Did a non-attached or detaching thread get the signal? + if (mono_thread_info_get_small_id () == -1 || + !mono_domain_get () || + !mono_tls_get_jit_tls ()) { + errno = old_errno; + return; + } - if (!mono_domain_get () || !mono_tls_get_jit_tls ()) - return; //thread in the process of dettaching + // See the comment in sampling_thread_func (). + InterlockedWrite (&mono_thread_info_current ()->profiler_signal_ack, 1); InterlockedIncrement (&profiler_signals_accepted); - hp_save_index = mono_hazard_pointer_save_for_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); + errno = old_errno; mono_chain_signal (MONO_SIG_HANDLER_PARAMS); @@ -515,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; @@ -578,20 +497,32 @@ 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 + * real time. + */ #ifdef HAVE_CLOCK_NANOSLEEP + struct timespec ts = { 0 }; + /* - * If we don't have clock_nanosleep (), measuring the process time - * makes very little sense as we can only use nanosleep () to sleep on - * real time. + * Some systems (e.g. Windows Subsystem for Linux) declare the + * CLOCK_PROCESS_CPUTIME_ID clock but don't actually support it. For + * those systems, we fall back to CLOCK_MONOTONIC if we get EINVAL. */ - sampling_posix_clock = CLOCK_PROCESS_CPUTIME_ID; - break; + if (clock_nanosleep (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME, &ts, NULL) != EINVAL) { + sampling_posix_clock = CLOCK_PROCESS_CPUTIME_ID; + break; + } #endif - case MONO_PROFILER_STAT_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break; + + // fallthrough + } + case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break; default: g_assert_not_reached (); break; } } @@ -683,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); @@ -706,22 +635,46 @@ 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_sleep (); + goto init; + } + + clock_init (mode); + + for (guint64 sleep = clock_get_time_ns (); InterlockedRead (&sampling_thread_running); clock_sleep_ns_abs (sleep)) { + uint64_t freq; + MonoProfilerSampleMode new_mode; - guint64 sleep = clock_get_time_ns (); + mono_profiler_get_sample_mode (NULL, &new_mode, &freq); + + if (new_mode != mode) { + clock_cleanup (); + goto init; + } - while (InterlockedRead (&sampling_thread_running)) { - sleep += rate; + sleep += 1000000000 / freq; FOREACH_THREAD_SAFE (info) { /* info should never be this thread as we're a tools thread. */ g_assert (mono_thread_info_get_tid (info) != mono_native_thread_id_get ()); + /* + * Require an ack for the last sampling signal sent to the thread + * so that we don't overflow the signal queue, leading to all sorts + * of problems (e.g. GC STW failing). + */ + if (profiler_signal != SIGPROF && !InterlockedCompareExchange (&info->profiler_signal_ack, 0, 1)) + continue; + 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); @@ -828,33 +781,7 @@ mono_runtime_setup_stat_profiler (void) #endif -#endif /* defined(__native_client__) || defined(HOST_WATCHOS) */ - -#if defined(__native_client__) - -void -mono_gdb_render_native_backtraces (pid_t crashed_pid) -{ -} - -#else - -pid_t -mono_runtime_syscall_fork () -{ -#if defined(PLATFORM_ANDROID) - /* SYS_fork is defined to be __NR_fork which is not defined in some ndk versions */ - g_assert_not_reached (); - return 0; -#elif defined(SYS_fork) - return (pid_t) syscall (SYS_fork); -#elif defined(PLATFORM_MACOSX) && HAVE_FORK - return (pid_t) fork (); -#else - g_assert_not_reached (); - return 0; -#endif -} +#endif /* defined(HOST_WATCHOS) */ static gboolean native_stack_with_gdb (pid_t crashed_pid, const char **argv, FILE *commands, char* commands_filename) @@ -916,7 +843,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) commands = fopen (commands_filename, "w"); if (!commands) { - unlink (commands_filename); + unlink (commands_filename); return; } @@ -942,6 +869,7 @@ mono_gdb_render_native_backtraces (pid_t crashed_pid) return; exec: + fclose (commands); execv (argv [0], (char**)argv); _exit (-1); @@ -950,8 +878,6 @@ exec: #endif // HAVE_EXECV } -#endif /* defined(__native_client__) */ - #if !defined (__MACH__) gboolean