int sgen_thread_handshake (BOOL suspend) { SgenThreadInfo *info; SgenThreadInfo *current = mono_thread_info_current (); int count = 0; current->client_info.suspend_done = TRUE; FOREACH_THREAD_SAFE (info) { if (info == current) continue; info->client_info.suspend_done = FALSE; if (info->client_info.gc_disabled) continue; if (suspend) { if (!sgen_suspend_thread (info)) continue; } else { if (!sgen_resume_thread (info)) continue; } ++count; } END_FOREACH_THREAD_SAFE return count; }
int sgen_thread_handshake (BOOL suspend) { SgenThreadInfo *info; SgenThreadInfo *current = mono_thread_info_current (); int count = 0; FOREACH_THREAD_SAFE (info) { info->joined_stw = suspend; if (info == current) continue; if (info->gc_disabled) continue; if (suspend) { g_assert (!info->doing_handshake); info->doing_handshake = TRUE; if (!sgen_suspend_thread (info)) continue; } else { g_assert (info->doing_handshake); info->doing_handshake = FALSE; if (!sgen_resume_thread (info)) continue; } ++count; } END_FOREACH_THREAD_SAFE return count; }
static int restart_threads_until_none_in_managed_allocator (void) { int num_threads_died = 0; int sleep_duration = -1; for (;;) { int restart_count = 0, restarted_count = 0; /* restart all threads that stopped in the allocator */ FOREACH_THREAD (info) { gboolean result; if (info->client_info.skip || info->client_info.gc_disabled || info->client_info.suspend_done) continue; if (mono_thread_info_is_live (info) && (!info->client_info.stack_start || info->client_info.in_critical_region || info->client_info.info.inside_critical_region || is_ip_in_managed_allocator (info->client_info.stopped_domain, info->client_info.stopped_ip))) { binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info)); SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->client_info.info.native_handle); result = sgen_resume_thread (info); if (result) { ++restart_count; } else { info->client_info.skip = 1; } } else { /* we set the stopped_ip to NULL for threads which we're not restarting so that we can easily identify the others */ info->client_info.stopped_ip = NULL; info->client_info.stopped_domain = NULL; info->client_info.suspend_done = TRUE; } } FOREACH_THREAD_END /* if no threads were restarted, we're done */ if (restart_count == 0) break; /* wait for the threads to signal their restart */ sgen_wait_for_suspend_ack (restart_count); if (sleep_duration < 0) { mono_thread_info_yield (); sleep_duration = 0; } else { g_usleep (sleep_duration); sleep_duration += 10; } /* stop them again */ FOREACH_THREAD (info) { gboolean result; if (info->client_info.skip || info->client_info.stopped_ip == NULL) continue; result = sgen_suspend_thread (info); if (result) { ++restarted_count; } else { info->client_info.skip = 1; } } FOREACH_THREAD_END /* some threads might have died */ num_threads_died += restart_count - restarted_count; /* wait for the threads to signal their suspension again */ sgen_wait_for_suspend_ack (restarted_count); } return num_threads_died; }
static int restart_threads_until_none_in_managed_allocator (void) { SgenThreadInfo *info; int num_threads_died = 0; int sleep_duration = -1; for (;;) { int restart_count = 0, restarted_count = 0; /* restart all threads that stopped in the allocator */ FOREACH_THREAD_SAFE (info) { gboolean result; if (info->skip || info->gc_disabled) continue; #ifdef SGEN_POSIX_STW if (info->signal < 0) continue; #endif if (mono_thread_info_run_state (info) == STATE_RUNNING && (!info->stack_start || info->in_critical_region || info->info.inside_critical_region || is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip))) { binary_protocol_thread_restart ((gpointer)mono_thread_info_get_tid (info)); SGEN_LOG (3, "thread %p resumed.", (void*) (size_t) info->info.native_handle); result = sgen_resume_thread (info); if (result) { ++restart_count; } else { info->skip = 1; } } else { /* we set the stopped_ip to NULL for threads which we're not restarting so that we can easily identify the others */ info->stopped_ip = NULL; info->stopped_domain = NULL; } } END_FOREACH_THREAD_SAFE /* if no threads were restarted, we're done */ if (restart_count == 0) break; /* wait for the threads to signal their restart */ sgen_wait_for_suspend_ack (restart_count); if (sleep_duration < 0) { #ifdef HOST_WIN32 SwitchToThread (); #else sched_yield (); #endif sleep_duration = 0; } else { g_usleep (sleep_duration); sleep_duration += 10; } /* stop them again */ FOREACH_THREAD (info) { gboolean result; if (info->skip || info->stopped_ip == NULL) continue; result = sgen_suspend_thread (info); if (result) { ++restarted_count; } else { info->skip = 1; } } END_FOREACH_THREAD /* some threads might have died */ num_threads_died += restart_count - restarted_count; /* wait for the threads to signal their suspension again */ sgen_wait_for_suspend_ack (restarted_count); } return num_threads_died; }