been scanned.
*/
gboolean gc_disabled;
+
+ void *stack_end;
+ void *stack_start;
+ void *stack_start_limit;
};
#else
char *endobj = obj + size;
FOREACH_THREAD (info) {
- char **start = (char**)info->stack_start;
+ char **start = (char**)info->client_info.stack_start;
if (info->client_info.skip)
continue;
- while (start < (char**)info->stack_end) {
- if (*start >= obj && *start < endobj) {
- SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->stack_start, info->stack_end);
- }
+ while (start < (char**)info->client_info.stack_end) {
+ if (*start >= obj && *start < endobj)
+ SGEN_LOG (0, "Object %p referenced in thread %p (id %p) at %p, stack: %p-%p", obj, info, (gpointer)mono_thread_info_get_tid (info), start, info->client_info.stack_start, info->client_info.stack_end);
start++;
}
#ifdef HAVE_KW_THREAD
__thread SgenThreadInfo *sgen_thread_info;
-__thread char *stack_end;
#endif
/* The size of a TLAB */
void*
sgen_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
{
- size_t stsize = 0;
- guint8 *staddr = NULL;
-
#ifndef HAVE_KW_THREAD
info->tlab_start = info->tlab_next = info->tlab_temp_end = info->tlab_real_end = NULL;
info->signal = 0;
#endif
sgen_client_thread_register (info, stack_bottom_fallback);
- info->stack_start = NULL;
#ifdef USE_MONO_CTX
memset (&info->ctx, 0, sizeof (MonoContext));
#else
binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info));
- /* On win32, stack_start_limit should be 0, since the stack can grow dynamically */
- mono_thread_info_get_stack_bounds (&staddr, &stsize);
- if (staddr) {
-#ifndef HOST_WIN32
- info->stack_start_limit = staddr;
-#endif
- info->stack_end = staddr + stsize;
- } else {
- gsize stack_bottom = (gsize)stack_bottom_fallback;
- stack_bottom += 4095;
- stack_bottom &= ~4095;
- info->stack_end = (char*)stack_bottom;
- }
-
-#ifdef HAVE_KW_THREAD
- stack_end = info->stack_end;
-#endif
-
- SGEN_LOG (3, "registered thread %p (%p) stack end %p", info, (gpointer)mono_thread_info_get_tid (info), info->stack_end);
-
if (gc_callbacks.thread_attach_func)
info->runtime_data = gc_callbacks.thread_attach_func ();
return info;
return mono_thread_info_attach (baseptr) != NULL;
}
-/*
- * mono_gc_set_stack_end:
- *
- * Set the end of the current threads stack to STACK_END. The stack space between
- * STACK_END and the real end of the threads stack will not be scanned during collections.
- */
-void
-mono_gc_set_stack_end (void *stack_end)
-{
- SgenThreadInfo *info;
-
- LOCK_GC;
- info = mono_thread_info_current ();
- if (info) {
- g_assert (stack_end < info->stack_end);
- info->stack_end = stack_end;
- }
- UNLOCK_GC;
-}
-
#if USE_PTHREAD_INTERCEPT
struct _SgenThreadInfo {
SgenClientThreadInfo client_info;
- void *stack_end;
- void *stack_start;
- void *stack_start_limit;
char **tlab_next_addr;
char **tlab_start_addr;
char **tlab_temp_end_addr;
#ifdef HAVE_KW_THREAD
extern __thread SgenThreadInfo *sgen_thread_info;
-extern __thread char *stack_end;
#endif
/* Other globals */
gpointer stack_start = &stack_start;
SgenThreadInfo *info = mono_thread_info_current ();
- if (ptr >= stack_start && ptr < (gpointer)info->stack_end)
+ if (ptr >= stack_start && ptr < (gpointer)info->client_info.stack_end)
return TRUE;
return FALSE;
}
MonoMethod **write_barrier_method_addr;
#ifdef MANAGED_WBARRIER
int i, nursery_check_labels [2];
-
-#ifdef HAVE_KW_THREAD
- int stack_end_offset = -1;
-
- MONO_THREAD_VAR_OFFSET (stack_end, stack_end_offset);
- g_assert (stack_end_offset != -1);
-#endif
#endif
// FIXME: Maybe create a separate version for ctors (the branch would be
void
sgen_client_thread_register (SgenThreadInfo* info, void *stack_bottom_fallback)
{
+ size_t stsize = 0;
+ guint8 *staddr = NULL;
+
info->client_info.skip = 0;
info->client_info.stopped_ip = NULL;
info->client_info.stopped_domain = NULL;
+
+ info->client_info.stack_start = NULL;
+
+ /* On win32, stack_start_limit should be 0, since the stack can grow dynamically */
+ mono_thread_info_get_stack_bounds (&staddr, &stsize);
+ if (staddr) {
+#ifndef HOST_WIN32
+ info->client_info.stack_start_limit = staddr;
+#endif
+ info->client_info.stack_end = staddr + stsize;
+ } else {
+ gsize stack_bottom = (gsize)stack_bottom_fallback;
+ stack_bottom += 4095;
+ stack_bottom &= ~4095;
+ info->client_info.stack_end = (char*)stack_bottom;
+ }
+
+ SGEN_LOG (3, "registered thread %p (%p) stack end %p", info, (gpointer)mono_thread_info_get_tid (info), info->client_info.stack_end);
}
void
FOREACH_THREAD (info) {
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);
+ SGEN_LOG (3, "Skipping dead thread %p, range: %p-%p, size: %td", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start);
continue;
}
if (info->client_info.gc_disabled) {
- SGEN_LOG (3, "GC disabled for thread %p, range: %p-%p, size: %td", info, info->stack_start, info->stack_end, (char*)info->stack_end - (char*)info->stack_start);
+ SGEN_LOG (3, "GC disabled for thread %p, range: %p-%p, size: %td", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start);
continue;
}
if (!mono_thread_info_is_live (info)) {
- 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);
+ SGEN_LOG (3, "Skipping non-running thread %p, range: %p-%p, size: %td (state %x)", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, info->client_info.info.thread_state);
continue;
}
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 ());
+ SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %td, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_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);
+ mono_gc_get_gc_callbacks ()->thread_mark_func (info->runtime_data, info->client_info.stack_start, info->client_info.stack_end, precise, &ctx);
} else if (!precise) {
if (!conservative_stack_mark) {
fprintf (stderr, "Precise stack mark not supported - disabling.\n");
conservative_stack_mark = TRUE;
}
- sgen_conservatively_pin_objects_from (info->stack_start, info->stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
+ sgen_conservatively_pin_objects_from (info->client_info.stack_start, info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
}
if (!precise) {
} END_FOREACH_THREAD
}
+/*
+ * mono_gc_set_stack_end:
+ *
+ * Set the end of the current threads stack to STACK_END. The stack space between
+ * STACK_END and the real end of the threads stack will not be scanned during collections.
+ */
+void
+mono_gc_set_stack_end (void *stack_end)
+{
+ SgenThreadInfo *info;
+
+ LOCK_GC;
+ info = mono_thread_info_current ();
+ if (info) {
+ SGEN_ASSERT (0, stack_end < info->client_info.stack_end, "Can only lower stack end");
+ info->client_info.stack_end = stack_end;
+ }
+ UNLOCK_GC;
+}
+
/*
* Miscellaneous
*/
info->client_info.stopped_domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN);
info->client_info.stopped_ip = (gpointer) mono_mach_arch_get_ip (state);
- info->stack_start = NULL;
+ info->client_info.stack_start = NULL;
stack_start = (char*) mono_mach_arch_get_sp (state) - REDZONE_SIZE;
/* If stack_start is not within the limits, then don't set it in info and we will be restarted. */
- if (stack_start >= info->stack_start_limit && stack_start <= info->stack_end) {
- info->stack_start = stack_start;
+ if (stack_start >= info->client_info.stack_start_limit && stack_start <= info->client_info.stack_end) {
+ info->client_info.stack_start = stack_start;
#ifdef USE_MONO_CTX
mono_sigctx_to_monoctx (&ctx, &info->ctx);
ARCH_COPY_SIGCTX_REGS (&info->regs, &ctx);
#endif
} else {
- g_assert (!info->stack_start);
+ g_assert (!info->client_info.stack_start);
}
/* Notify the JIT */
if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, &ctx, NULL);
- SGEN_LOG (2, "thread %p stopped at %p stack_start=%p", (void*)(gsize)info->client_info.info.native_handle, info->client_info.stopped_ip, info->stack_start);
+ SGEN_LOG (2, "thread %p stopped at %p stack_start=%p", (void*)(gsize)info->client_info.info.native_handle, info->client_info.stopped_ip, info->client_info.stack_start);
binary_protocol_thread_suspend ((gpointer)mono_thread_info_get_tid (info), info->client_info.stopped_ip);
return TRUE;
/* If stack_start is not within the limits, then don't set it
in info and we will be restarted. */
- if (stack_start >= info->stack_start_limit && stack_start <= info->stack_end) {
- info->stack_start = stack_start;
+ if (stack_start >= info->client_info.stack_start_limit && stack_start <= info->client_info.stack_end) {
+ info->client_info.stack_start = stack_start;
#ifdef USE_MONO_CTX
if (context) {
}
#endif
} else {
- g_assert (!info->stack_start);
+ g_assert (!info->client_info.stack_start);
}
/* Notify the JIT */
#endif
SgenThreadInfo *info = mono_thread_info_current ();
- info->stack_start = align_pointer (&stack_guard);
- g_assert (info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end);
+ info->client_info.stack_start = align_pointer (&stack_guard);
+ g_assert (info->client_info.stack_start >= info->client_info.stack_start_limit && info->client_info.stack_start < info->client_info.stack_end);
#ifdef USE_MONO_CTX
MONO_CONTEXT_GET_CURRENT (cur_thread_ctx);
memcpy (&info->ctx, &cur_thread_ctx, sizeof (MonoContext));
if (info->client_info.skip || info->client_info.gc_disabled || info->client_info.suspend_done)
continue;
if (mono_thread_info_is_live (info) &&
- (!info->stack_start || info->client_info.in_critical_region || info->client_info.info.inside_critical_region ||
+ (!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);
mono_sgen_gc_event_moves ();
FOREACH_THREAD (info) {
- info->stack_start = NULL;
+ info->client_info.stack_start = NULL;
#ifdef USE_MONO_CTX
memset (&info->ctx, 0, sizeof (MonoContext));
#else
stack_start = (char*)MONO_CONTEXT_GET_SP (&mono_thread_info_get_suspend_state (info)->ctx) - REDZONE_SIZE;
/* altstack signal handler, sgen can't handle them, mono-threads should have handled this. */
- if (stack_start < (char*)info->stack_start_limit || stack_start >= (char*)info->stack_end)
+ if (stack_start < (char*)info->client_info.stack_start_limit || stack_start >= (char*)info->client_info.stack_end)
g_error ("BAD STACK");
- info->stack_start = stack_start;
+ info->client_info.stack_start = stack_start;
#ifdef USE_MONO_CTX
info->ctx = mono_thread_info_get_suspend_state (info)->ctx;
#else