X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-posix.c;h=031cb6c0019744de9e8fb2a6c33cda05461780e9;hb=b511edee10b6dc52d24f1f5fed1135ba340d8f71;hp=0c2fa1dc1f0a1525208eb8bdd332f933f1da6e7c;hpb=63eb94b5249af5aeb1a86b107f4491f1c0564e9a;p=mono.git diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 0c2fa1dc1f0..031cb6c0019 100644 --- a/mono/mini/mini-posix.c +++ b/mono/mini/mini-posix.c @@ -25,6 +25,8 @@ #ifdef HAVE_SYS_SYSCALL_H #include #endif +#include + #include #include @@ -55,6 +57,7 @@ #include #include #include +#include #include "mini.h" #include @@ -306,12 +309,14 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) #else -MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) +static int profiling_signal_in_use; + +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 (); - MONO_SIG_HANDLER_GET_CONTEXT; - + if (call_chain_depth == 0) { mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx); } else { @@ -320,7 +325,7 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) MonoContext mono_context; guchar *ips [call_chain_depth + 1]; - mono_arch_sigctx_to_monoctx (ctx, &mono_context); + mono_sigctx_to_monoctx (ctx, &mono_context); ips [0] = MONO_CONTEXT_GET_IP (&mono_context); if (jit_tls != NULL) { @@ -378,6 +383,40 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) mono_profiler_stat_call_chain (current_frame_index, & ips [0], ctx); } +} + +MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) +{ + MonoThreadInfo *info; + int old_errno = errno; + int hp_save_index; + MONO_SIG_HANDLER_GET_CONTEXT; + + if (mono_thread_info_get_small_id () == -1) + return; //an non-attached thread got the signal + + if (!mono_domain_get () || !mono_native_tls_get_value (mono_jit_tls_id)) + return; //thread in the process of dettaching + + hp_save_index = mono_hazard_pointer_save_for_signal_handler (); + + /* If we can't consume a profiling request it means we're the initiator. */ + if (!(mono_threads_consume_async_jobs () & MONO_SERVICE_REQUEST_SAMPLE)) { + FOREACH_THREAD_SAFE (info) { + if (mono_thread_info_get_tid (info) == mono_native_thread_id_get ()) + continue; + + mono_threads_add_async_job (info, MONO_SERVICE_REQUEST_SAMPLE); + mono_threads_pthread_kill (info, profiling_signal_in_use); + } END_FOREACH_THREAD_SAFE; + } + + mono_thread_info_set_is_async_context (TRUE); + per_thread_profiler_hit (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); } @@ -600,6 +639,30 @@ mono_runtime_shutdown_stat_profiler (void) #endif } +#ifdef ITIMER_PROF +static int +get_itimer_mode (void) +{ + switch (mono_profiler_get_sampling_mode ()) { + case MONO_PROFILER_STAT_MODE_PROCESS: return ITIMER_PROF; + case MONO_PROFILER_STAT_MODE_REAL: return ITIMER_REAL; + } + g_assert_not_reached (); + return 0; +} + +static int +get_itimer_signal (void) +{ + switch (mono_profiler_get_sampling_mode ()) { + case MONO_PROFILER_STAT_MODE_PROCESS: return SIGPROF; + case MONO_PROFILER_STAT_MODE_REAL: return SIGALRM; + } + g_assert_not_reached (); + return 0; +} +#endif + void mono_runtime_setup_stat_profiler (void) { @@ -620,7 +683,8 @@ mono_runtime_setup_stat_profiler (void) perror ("open /dev/rtc"); return; } - add_signal_handler (SIGPROF, sigprof_signal_handler); + profiling_signal_in_use = SIGPROF; + add_signal_handler (profiling_signal_in_use, sigprof_signal_handler); if (ioctl (rtc_fd, RTC_IRQP_SET, freq) == -1) { perror ("set rtc freq"); return; @@ -644,14 +708,15 @@ mono_runtime_setup_stat_profiler (void) return; #endif - itval.it_interval.tv_usec = 999; + itval.it_interval.tv_usec = (1000000 / mono_profiler_get_sampling_rate ()) - 1; itval.it_interval.tv_sec = 0; itval.it_value = itval.it_interval; - setitimer (ITIMER_PROF, &itval, NULL); if (inited) return; inited = 1; - add_signal_handler (SIGPROF, sigprof_signal_handler); + profiling_signal_in_use = get_itimer_signal (); + add_signal_handler (profiling_signal_in_use, sigprof_signal_handler); + setitimer (get_itimer_mode (), &itval, NULL); #endif }