}
}
-#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;
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);
static clock_serv_t sampling_clock_service;
static void
-clock_init (void)
+clock_init (MonoProfilerSampleMode mode)
{
kern_return_t ret;
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
// 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;
}
}
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);
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. */
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);