2009-07-30 Mark Probst <mark.probst@gmail.com>
authorMark Probst <mark.probst@gmail.com>
Thu, 30 Jul 2009 10:29:14 +0000 (10:29 -0000)
committerMark Probst <mark.probst@gmail.com>
Thu, 30 Jul 2009 10:29:14 +0000 (10:29 -0000)
* mono-sigcontext.h: Include config.h.

2009-07-30  Mark Probst  <mark.probst@gmail.com>

* sgen-gc.c: When we stop a thread and its stack top is not within
its allocated stack (because it's in an altstack signal handler),
restart it and stop it again, until it is.

svn path=/trunk/mono/; revision=139047

mono/metadata/ChangeLog
mono/metadata/sgen-gc.c
mono/utils/ChangeLog
mono/utils/mono-sigcontext.h

index fbcb0a407032c58aaf03c6f9d93bb9c3092c3388..98114bb383b72c29bdec9faf59e00941a963b992 100644 (file)
@@ -1,3 +1,9 @@
+2009-07-30  Mark Probst  <mark.probst@gmail.com>
+
+       * sgen-gc.c: When we stop a thread and its stack top is not within
+       its allocated stack (because it's in an altstack signal handler),
+       restart it and stop it again, until it is.
+
 2009-07-30  Mark Probst  <mark.probst@gmail.com>
 
        * sgen-gc.c: Take a thread's stack top and registers from the
index ddfbfc2bf8d25890bf70bc21443aaea784104995..10c1c7c15f9cee74e1c95510528724de38bd13d4 100644 (file)
@@ -683,6 +683,7 @@ struct _SgenThreadInfo {
        int skip;
        void *stack_end;
        void *stack_start;
+       void *stack_start_limit;
        char **tlab_next_addr;
        char **tlab_start_addr;
        char **tlab_temp_end_addr;
@@ -3609,7 +3610,6 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                if (nursery_section) {
                        LOCK_GC;
 
-                       update_current_thread_stack (&dummy);
                        stop_world ();
                        collect_nursery (0);
                        restart_world ();
@@ -3672,8 +3672,6 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
         */
        g_assert (TLAB_NEXT == new_next);
        if (size > MAX_SMALL_OBJ_SIZE) {
-               /* get ready for possible collection */
-               update_current_thread_stack (&dummy);
                TLAB_NEXT -= size;
                p = alloc_large_inner (vtable, size);
        } else {
@@ -3699,8 +3697,6 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                                /* Allocate directly from the nursery */
                                if (nursery_next + size >= nursery_frag_real_end) {
                                        if (!search_fragment_for_size (size)) {
-                                               /* get ready for possible collection */
-                                               update_current_thread_stack (&dummy);
                                                minor_collect_or_expand_inner (size);
                                                if (degraded_mode) {
                                                        p = alloc_degraded (vtable, size);
@@ -3726,8 +3722,6 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                                if (nursery_next + tlab_size >= nursery_frag_real_end) {
                                        res = search_fragment_for_size (tlab_size);
                                        if (!res) {
-                                               /* get ready for possible collection */
-                                               update_current_thread_stack (&dummy);
                                                minor_collect_or_expand_inner (tlab_size);
                                                if (degraded_mode) {
                                                        p = alloc_degraded (vtable, size);
@@ -3786,7 +3780,6 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
        size &= ~(ALLOC_ALIGN - 1);
        LOCK_GC;
        if (size > MAX_FREELIST_SIZE) {
-               update_current_thread_stack (&p);
                /* large objects are always pinned anyway */
                p = alloc_large_inner (vtable, size);
        } else {
@@ -4548,6 +4541,7 @@ update_current_thread_stack (void *start)
        void *ptr = cur_thread_regs;
        SgenThreadInfo *info = thread_info_lookup (ARCH_GET_THREAD ());
        info->stack_start = align_pointer (&ptr);
+       g_assert (info->stack_start >= info->stack_start_limit && info->stack_start < info->stack_end);
        ARCH_STORE_REGS (ptr);
        info->stopped_regs = ptr;
        if (gc_callbacks.thread_suspend_func)
@@ -4570,6 +4564,12 @@ signal_desc (int signum)
 #ifdef MANAGED_ALLOCATION
 static gboolean
 is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip);
+#else
+static gboolean
+is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
+{
+       return FALSE;
+}
 #endif
 
 static void
@@ -4627,7 +4627,6 @@ restart_threads_until_none_in_managed_allocator (void)
        int i, result, num_threads_died = 0;
        int sleep_duration = -1;
 
-#ifdef MANAGED_ALLOCATION
        for (;;) {
                int restart_count = 0, restarted_count = 0;
                /* restart all threads that stopped in the
@@ -4636,7 +4635,8 @@ restart_threads_until_none_in_managed_allocator (void)
                        for (info = thread_table [i]; info; info = info->next) {
                                if (info->skip)
                                        continue;
-                               if (is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip)) {
+                               if (!info->stack_start ||
+                                               is_ip_in_managed_allocator (info->stopped_domain, info->stopped_ip)) {
                                        result = pthread_kill (info->id, restart_signal_num);
                                        if (result == 0) {
                                                ++restart_count;
@@ -4651,7 +4651,6 @@ restart_threads_until_none_in_managed_allocator (void)
                                           the others */
                                        info->stopped_ip = NULL;
                                        info->stopped_domain = NULL;
-                                       info->stopped_regs = NULL;
                                }
                        }
                }
@@ -4689,7 +4688,6 @@ restart_threads_until_none_in_managed_allocator (void)
                   again */
                wait_for_suspend_ack (restart_count);
        }
-#endif
 
        return num_threads_died;
 }
@@ -4703,6 +4701,7 @@ suspend_handler (int sig, siginfo_t *siginfo, void *context)
        int stop_count;
        int old_errno = errno;
        gpointer regs [ARCH_NUM_REGS];
+       gpointer stack_start;
 
        id = pthread_self ();
        info = thread_info_lookup (id);
@@ -4718,11 +4717,17 @@ suspend_handler (int sig, siginfo_t *siginfo, void *context)
        /* update the remset info in the thread data structure */
        info->remset = remembered_set;
 #endif
-       info->stack_start = (char*) ARCH_SIGCTX_SP (context) - REDZONE_SIZE;
-       g_assert (info->stack_start < info->stack_end);
-
-       ARCH_COPY_SIGCTX_REGS (regs, context);
-       info->stopped_regs = regs;
+       stack_start = (char*) ARCH_SIGCTX_SP (context) - 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 && info->stack_start <= info->stack_end) {
+               info->stack_start = stack_start;
+
+               ARCH_COPY_SIGCTX_REGS (regs, context);
+               info->stopped_regs = regs;
+       } else {
+               g_assert (!info->stack_start);
+       }
 
        /* Notify the JIT */
        if (gc_callbacks.thread_suspend_func)
@@ -4765,6 +4770,8 @@ stop_world (void)
 {
        int count;
 
+       update_current_thread_stack (&count);
+
        global_stop_count++;
        DEBUG (3, fprintf (gc_debug_file, "stopping world n %d from %p %p\n", global_stop_count, thread_info_lookup (ARCH_GET_THREAD ()), (gpointer)ARCH_GET_THREAD ()));
        TV_GETTIME (stop_world_time);
@@ -4779,10 +4786,18 @@ stop_world (void)
 static int
 restart_world (void)
 {
-       int count;
+       int count, i;
+       SgenThreadInfo *info;
        TV_DECLARE (end_sw);
        unsigned long usec;
 
+       for (i = 0; i < THREAD_HASH_SIZE; ++i) {
+               for (info = thread_table [i]; info; info = info->next) {
+                       info->stack_start = NULL;
+                       info->stopped_regs = NULL;
+               }
+       }
+
        count = thread_handshake (restart_signal_num);
        TV_GETTIME (end_sw);
        usec = TV_ELAPSED (stop_world_time, end_sw);
@@ -4873,12 +4888,10 @@ static gboolean
 ptr_on_stack (void *ptr)
 {
        int rs = 0;
-       int dummy;
+       gpointer stack_start = &stack_start;
        SgenThreadInfo *info = thread_info_lookup (ARCH_GET_THREAD ());
 
-       update_current_thread_stack (&dummy);
-
-       if (ptr >= (gpointer)info->stack_start && ptr < (gpointer)info->stack_end)
+       if (ptr >= stack_start && ptr < (gpointer)info->stack_end)
                return TRUE;
        return FALSE;
 }
@@ -5199,6 +5212,7 @@ gc_register_current_thread (void *addr)
                pthread_attr_t attr;
                pthread_getattr_np (pthread_self (), &attr);
                pthread_attr_getstack (&attr, &sstart, &size);
+               info->stack_start_limit = sstart;
                info->stack_end = (char*)sstart + size;
                pthread_attr_destroy (&attr);
        }
@@ -5998,7 +6012,6 @@ void
 mono_gc_collect (int generation)
 {
        LOCK_GC;
-       update_current_thread_stack (&generation);
        stop_world ();
        if (generation == 0) {
                collect_nursery (0);
index 096c5feb6b73c259e3e1e77b7e06300353153a5e..0e15d2074b6570317bd50379e18fde0a5c303bf6 100644 (file)
@@ -1,3 +1,7 @@
+2009-07-30  Mark Probst  <mark.probst@gmail.com>
+
+       * mono-sigcontext.h: Include config.h.
+
 2009-07-30  Mark Probst  <mark.probst@gmail.com>
 
        * mono-sigcontext.h, Makefile.am: Arch-dependent sigcontext
index e51870e36cefb5efad2a8d93413be5cf57a2470b..cc708ab473baa31930cf8a504e3be2f678dfd4aa 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __MONO_MONO_SIGCONTEXT_H__
 #define __MONO_MONO_SIGCONTEXT_H__
 
+#include <config.h>
+
 #if defined(__i386__)
 
 #if defined(__FreeBSD__) || defined(__APPLE__)