X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini-posix.c;h=031cb6c0019744de9e8fb2a6c33cda05461780e9;hb=b511edee10b6dc52d24f1f5fed1135ba340d8f71;hp=67f5725de6ae2db75799a1b7a7f980ed203a4de6;hpb=80b9d3ac18399ffc2a63c53451df39ee0e03191e;p=mono.git diff --git a/mono/mini/mini-posix.c b/mono/mini/mini-posix.c index 67f5725de6a..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 @@ -81,7 +84,7 @@ mono_runtime_shutdown_stat_profiler (void) gboolean -SIG_HANDLER_SIGNATURE (mono_chain_signal) +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { return FALSE; } @@ -173,19 +176,17 @@ free_saved_signal_handlers (void) * was called, false otherwise. */ gboolean -SIG_HANDLER_SIGNATURE (mono_chain_signal) +MONO_SIG_HANDLER_SIGNATURE (mono_chain_signal) { - int signal = _dummy; + int signal = MONO_SIG_HANDLER_GET_SIGNO (); struct sigaction *saved_handler = get_saved_signal_handler (signal); - GET_CONTEXT; - if (saved_handler && saved_handler->sa_handler) { if (!(saved_handler->sa_flags & SA_SIGINFO)) { saved_handler->sa_handler (signal); } else { #ifdef MONO_ARCH_USE_SIGACTION - saved_handler->sa_sigaction (signal, info, ctx); + saved_handler->sa_sigaction (MONO_SIG_HANDLER_PARAMS); #endif /* MONO_ARCH_USE_SIGACTION */ } return TRUE; @@ -193,29 +194,28 @@ SIG_HANDLER_SIGNATURE (mono_chain_signal) return FALSE; } -SIG_HANDLER_FUNC (static, sigabrt_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigabrt_signal_handler) { MonoJitInfo *ji = NULL; - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (mono_thread_internal_current ()) - ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context(ctx)); + ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx)); if (!ji) { - if (mono_chain_signal (SIG_HANDLER_PARAMS)) + if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; mono_handle_native_sigsegv (SIGABRT, ctx); } } -SIG_HANDLER_FUNC (static, sigusr1_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigusr1_signal_handler) { gboolean running_managed; MonoException *exc; MonoInternalThread *thread = mono_thread_internal_current (); MonoDomain *domain = mono_domain_get (); void *ji; - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; if (!thread || !domain) { /* The thread might not have started up yet */ @@ -296,11 +296,12 @@ SIG_HANDLER_FUNC (static, sigusr1_signal_handler) #define FULL_STAT_PROFILER_BACKTRACE 0 #endif +#ifdef SIGPROF #if defined(__ia64__) || defined(__sparc__) || defined(sparc) || defined(__s390__) || defined(s390) -SIG_HANDLER_FUNC (static, sigprof_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler) { - if (mono_chain_signal (SIG_HANDLER_PARAMS)) + if (mono_chain_signal (MONO_SIG_HANDLER_PARAMS)) return; NOT_IMPLEMENTED; @@ -308,12 +309,14 @@ SIG_HANDLER_FUNC (static, sigprof_signal_handler) #else -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 (); - GET_CONTEXT; - + if (call_chain_depth == 0) { mono_profiler_stat_hit (mono_arch_ip_from_context (ctx), ctx); } else { @@ -322,7 +325,7 @@ 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) { @@ -380,17 +383,51 @@ 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 (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } +#endif #endif -SIG_HANDLER_FUNC (static, sigquit_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigquit_signal_handler) { gboolean res; - - GET_CONTEXT; + MONO_SIG_HANDLER_GET_CONTEXT; /* We use this signal to start the attach agent too */ res = mono_attach_start (); @@ -413,16 +450,16 @@ SIG_HANDLER_FUNC (static, sigquit_signal_handler) mono_print_thread_dump (ctx); } - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } -SIG_HANDLER_FUNC (static, sigusr2_signal_handler) +MONO_SIG_HANDLER_FUNC (static, sigusr2_signal_handler) { gboolean enabled = mono_trace_is_enabled (); mono_trace_enable (!enabled); - mono_chain_signal (SIG_HANDLER_PARAMS); + mono_chain_signal (MONO_SIG_HANDLER_PARAMS); } static void @@ -602,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) { @@ -622,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; @@ -646,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 }