struct _SgenClientThreadInfo {
MonoThreadInfo info;
+ /*
+ * `skip` is set to TRUE when STW fails to suspend a thread, most probably because
+ * the underlying thread is dead.
+ */
+ gboolean skip, suspend_done;
+ volatile int in_critical_region;
+
gpointer stopped_ip; /* only valid if the thread is stopped */
MonoDomain *stopped_domain; /* dsto */
};
gboolean sgen_resume_thread (SgenThreadInfo *info);
void sgen_wait_for_suspend_ack (int count);
+#ifdef HAVE_KW_THREAD
+#define TLAB_ACCESS_INIT
+#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
+#else
+#define TLAB_ACCESS_INIT SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
+#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
+#endif
+
+#ifndef DISABLE_CRITICAL_REGION
+
+#ifdef HAVE_KW_THREAD
+#define IN_CRITICAL_REGION sgen_thread_info->client_info.in_critical_region
+#else
+#define IN_CRITICAL_REGION (__thread_info__->client_info.in_critical_region)
+#endif
+
+/* Enter must be visible before anything is done in the critical region. */
+#define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
+
+/* Exit must make sure all critical regions stores are visible before it signal the end of the region.
+ * We don't need to emit a full barrier since we
+ */
+#define EXIT_CRITICAL_REGION do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
+
+#endif
+
#endif
FOREACH_THREAD (info) {
char **start = (char**)info->stack_start;
- if (info->skip)
+ if (info->client_info.skip)
continue;
while (start < (char**)info->stack_end) {
if (*start >= obj && *start < endobj) {
info->stop_count = -1;
info->signal = 0;
#endif
- info->skip = 0;
sgen_client_thread_register (info, stack_bottom_fallback);
info->stack_start = NULL;
#ifdef USE_MONO_CTX
struct _SgenThreadInfo {
SgenClientThreadInfo client_info;
- /*
- This is set to TRUE when STW fails to suspend a thread, most probably because the
- underlying thread is dead.
- */
- gboolean skip, suspend_done;
- volatile int in_critical_region;
-
/*
This is set the argument of mono_gc_set_skip_thread.
extern __thread char *stack_end;
#endif
-#ifdef HAVE_KW_THREAD
-#define TLAB_ACCESS_INIT
-#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
-#else
-#define TLAB_ACCESS_INIT SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
-#define IN_CRITICAL_REGION (__thread_info__->in_critical_region)
-#endif
-
-#ifndef DISABLE_CRITICAL_REGION
-
-#ifdef HAVE_KW_THREAD
-#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
-#else
-#define IN_CRITICAL_REGION (__thread_info__->in_critical_region)
-#endif
-
-/* Enter must be visible before anything is done in the critical region. */
-#define ENTER_CRITICAL_REGION do { mono_atomic_store_acquire (&IN_CRITICAL_REGION, 1); } while (0)
-
-/* Exit must make sure all critical regions stores are visible before it signal the end of the region.
- * We don't need to emit a full barrier since we
- */
-#define EXIT_CRITICAL_REGION do { mono_atomic_store_release (&IN_CRITICAL_REGION, 0); } while (0)
-
-#endif
-
/* Other globals */
extern GCMemSection *nursery_section;
void
sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
{
+ info->client_info.skip = 0;
info->client_info.stopped_ip = NULL;
info->client_info.stopped_domain = NULL;
}
static gboolean
thread_in_critical_region (SgenThreadInfo *info)
{
- return info->in_critical_region;
+ return info->client_info.in_critical_region;
}
static void
scan_area_arg_end = end_nursery;
FOREACH_THREAD (info) {
- if (info->skip) {
+ if (info->client_info.skip) {
SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %td", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start);
continue;
}
SGEN_LOG (3, "Skipping non-running thread %p, range: %p-%p, size: %td (state %x)", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start, info->client_info.info.thread_state);
continue;
}
- g_assert (info->suspend_done);
+ g_assert (info->client_info.suspend_done);
SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %td, pinned=%zd", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start, sgen_get_pinned_count ());
if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
mono_gc_get_gc_callbacks ()->thread_mark_func (info->runtime_data, info->stack_start, info->stack_end, precise, &ctx);
int count = 0;
- cur_thread->suspend_done = TRUE;
+ cur_thread->client_info.suspend_done = TRUE;
FOREACH_THREAD_SAFE (info) {
if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
continue;
- info->suspend_done = FALSE;
+ info->client_info.suspend_done = FALSE;
if (info->gc_disabled)
continue;
MonoNativeThreadId me = mono_native_thread_id_get ();
count = 0;
- mono_thread_info_current ()->suspend_done = TRUE;
+ mono_thread_info_current ()->client_info.suspend_done = TRUE;
FOREACH_THREAD_SAFE (info) {
if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
continue;
}
- info->suspend_done = FALSE;
+ info->client_info.suspend_done = FALSE;
if (info->gc_disabled)
continue;
/*if (signum == suspend_signal_num && info->stop_count == global_stop_count)
if (result == 0) {
count++;
} else {
- info->skip = 1;
+ info->client_info.skip = 1;
}
} END_FOREACH_THREAD_SAFE
SgenThreadInfo *current = mono_thread_info_current ();
int count = 0;
- current->suspend_done = TRUE;
+ current->client_info.suspend_done = TRUE;
FOREACH_THREAD_SAFE (info) {
if (info == current)
continue;
- info->suspend_done = FALSE;
+ info->client_info.suspend_done = FALSE;
if (info->gc_disabled)
continue;
if (suspend) {
allocator */
FOREACH_THREAD_SAFE (info) {
gboolean result;
- if (info->skip || info->gc_disabled || info->suspend_done)
+ if (info->client_info.skip || info->gc_disabled || info->client_info.suspend_done)
continue;
- if (mono_thread_info_is_live (info) && (!info->stack_start || info->in_critical_region || info->client_info.info.inside_critical_region ||
+ if (mono_thread_info_is_live (info) &&
+ (!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);
if (result) {
++restart_count;
} else {
- info->skip = 1;
+ info->client_info.skip = 1;
}
} else {
/* we set the stopped_ip to
the others */
info->client_info.stopped_ip = NULL;
info->client_info.stopped_domain = NULL;
- info->suspend_done = TRUE;
+ info->client_info.suspend_done = TRUE;
}
} END_FOREACH_THREAD_SAFE
/* if no threads were restarted, we're done */
/* stop them again */
FOREACH_THREAD (info) {
gboolean result;
- if (info->skip || info->client_info.stopped_ip == NULL)
+ if (info->client_info.skip || info->client_info.stopped_ip == NULL)
continue;
result = sgen_suspend_thread (info);
if (result) {
++restarted_count;
} else {
- info->skip = 1;
+ info->client_info.skip = 1;
}
} END_FOREACH_THREAD
/* some threads might have died */
We have detected that this thread is failing/dying, ignore it.
FIXME: can't we merge this with thread_is_dying?
*/
- if (info->skip) {
+ if (info->client_info.skip) {
return FALSE;
}
THREADS_STW_DEBUG ("[GC-STW-BEGIN] *** BEGIN SUSPEND *** \n");
FOREACH_THREAD_SAFE (info) {
- info->skip = FALSE;
- info->suspend_done = FALSE;
+ info->client_info.skip = FALSE;
+ info->client_info.suspend_done = FALSE;
if (sgen_is_thread_in_current_stw (info)) {
- info->skip = !mono_thread_info_begin_suspend (info, FALSE);
- THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), info->skip);
- if (!info->skip)
+ info->client_info.skip = !mono_thread_info_begin_suspend (info, FALSE);
+ THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), info->client_info.skip);
+ if (!info->client_info.skip)
++count;
} else {
THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->skip);
}
} END_FOREACH_THREAD_SAFE
- mono_thread_info_current ()->suspend_done = TRUE;
+ mono_thread_info_current ()->client_info.suspend_done = TRUE;
mono_threads_wait_pending_operations ();
for (;;) {
restart_counter = 0;
FOREACH_THREAD_SAFE (info) {
- if (info->suspend_done || !sgen_is_thread_in_current_stw (info)) {
- THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->suspend_done, !sgen_is_thread_in_current_stw (info));
+ if (info->client_info.suspend_done || !sgen_is_thread_in_current_stw (info)) {
+ THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->client_info.suspend_done, !sgen_is_thread_in_current_stw (info));
continue;
}
*/
if (!mono_threads_core_check_suspend_result (info)) {
THREADS_STW_DEBUG ("[GC-STW-RESTART] SKIP thread %p failed to finish to suspend\n", mono_thread_info_get_tid (info));
- info->skip = TRUE;
+ info->client_info.skip = TRUE;
} else if (mono_thread_info_in_critical_location (info)) {
gboolean res;
g_assert (mono_thread_info_suspend_count (info) == 1);
if (res)
++restart_counter;
else
- info->skip = TRUE;
+ info->client_info.skip = TRUE;
} else {
THREADS_STW_DEBUG ("[GC-STW-RESTART] DONE thread %p deemed fully suspended\n", mono_thread_info_get_tid (info));
- g_assert (!info->in_critical_region);
- info->suspend_done = TRUE;
+ g_assert (!info->client_info.in_critical_region);
+ info->client_info.suspend_done = TRUE;
}
} END_FOREACH_THREAD_SAFE
gboolean res = mono_thread_info_begin_suspend (info, FALSE);
THREADS_STW_DEBUG ("[GC-STW-RESTART] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), res);
if (!res)
- info->skip = TRUE;
+ info->client_info.skip = TRUE;
}
} END_FOREACH_THREAD_SAFE
FOREACH_THREAD_SAFE (info) {
if (sgen_is_thread_in_current_stw (info)) {
THREADS_STW_DEBUG ("[GC-STW-SUSPEND-END] thread %p is suspended\n", mono_thread_info_get_tid (info));
- g_assert (info->suspend_done);
+ g_assert (info->client_info.suspend_done);
update_sgen_info (info);
} else {
- g_assert (!info->suspend_done || info == mono_thread_info_current ());
+ g_assert (!info->client_info.suspend_done || info == mono_thread_info_current ());
}
} END_FOREACH_THREAD_SAFE