]> granicus.if.org Git - gc/commitdiff
2010-10-06 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Wed, 6 Oct 2010 20:09:27 +0000 (20:09 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:55 +0000 (21:06 +0400)
* darwin_stop_world.c (FindTopOfStack): Change return type to
ptr_t (from long); make GC_INNER; add GC_ prefix.
* darwin_stop_world.c (GC_push_all_stacks): Add thread_blocked
local variable (initialized from the corresponding GC_thread
field unless GC_query_task_threads); add assertion that our
thread is not blocked; prefix FindTopOfStack with GC_ and remove
no longer needed cast to ptr_t of the result; handle thread
blocked case (and remove FIXME); use GC_push_all_stack_sections
unless GC_query_task_threads (and remove FIXME).
* pthread_support.c (GC_FindTopOfStack): Declare (if needed).
* pthread_support.c (GC_do_blocking_inner): Call
GC_save_regs_in_stack (if needed) before acquiring the lock.
* win32_threads.c (GC_do_blocking_inner): Ditto.
* pthread_support.c (GC_do_blocking_inner): Set/clear topOfStack
field of GC_thread (Darwin only).
* include/private/pthread_support.h (GC_thread): Add topOfStack
field for Darwin (unless DARWIN_DONT_PARSE_STACK).

ChangeLog
darwin_stop_world.c
include/private/pthread_support.h
pthread_support.c
win32_threads.c

index 441e6782ba44e925a70c2ef6a81c1b0efc6c98d2..56095e826d55a1c03dee2a193f5d13541d73c3fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2010-10-06  Ivan Maidanski <ivmai@mail.ru>
+
+       * darwin_stop_world.c (FindTopOfStack): Change return type to
+       ptr_t (from long); make GC_INNER; add GC_ prefix.
+       * darwin_stop_world.c (GC_push_all_stacks): Add thread_blocked
+       local variable (initialized from the corresponding GC_thread
+       field unless GC_query_task_threads); add assertion that our
+       thread is not blocked; prefix FindTopOfStack with GC_ and remove
+       no longer needed cast to ptr_t of the result; handle thread
+       blocked case (and remove FIXME); use GC_push_all_stack_sections
+       unless GC_query_task_threads (and remove FIXME).
+       * pthread_support.c (GC_FindTopOfStack): Declare (if needed).
+       * pthread_support.c (GC_do_blocking_inner): Call
+       GC_save_regs_in_stack (if needed) before acquiring the lock.
+       * win32_threads.c (GC_do_blocking_inner): Ditto.
+       * pthread_support.c (GC_do_blocking_inner): Set/clear topOfStack
+       field of GC_thread (Darwin only).
+       * include/private/pthread_support.h (GC_thread): Add topOfStack
+       field for Darwin (unless DARWIN_DONT_PARSE_STACK).
+
 2010-10-05  Ivan Maidanski <ivmai@mail.ru>
 
        * finalize.c (GC_check_finalizer_nested): Change return type to
index 3874d37bd9e54f3145ce6d25b2786103d8763d2f..533ea76e4313d99a55ed5e7a230b47f8553cbd9f 100644 (file)
@@ -49,9 +49,9 @@ typedef struct StackFrame {
   unsigned long savedRTOC;
 } StackFrame;
 
-static unsigned long FindTopOfStack(unsigned long stack_start)
+GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start)
 {
-  StackFrame    *frame;
+  StackFrame *frame;
 
   if (stack_start == 0) {
 # ifdef POWERPC
@@ -82,7 +82,7 @@ static unsigned long FindTopOfStack(unsigned long stack_start)
 # ifdef DEBUG_THREADS
     /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */
 # endif
-  return (unsigned long)frame;
+  return (ptr_t)frame;
 }
 
 #endif /* !DARWIN_DONT_PARSE_STACK */
@@ -122,28 +122,36 @@ GC_INNER void GC_push_all_stacks(void)
   }
 
   for (i = 0; i < (int)listcount; i++) {
-    GC_thread p = GC_query_task_threads ? 0 : GC_threads[i];
+    GC_thread p = GC_query_task_threads ? NULL : GC_threads[i];
     for (;; p = p->next) {
       thread_act_t thread;
+      GC_bool thread_blocked;
       if (GC_query_task_threads) {
         thread = act_list[i];
+        thread_blocked = FALSE;
       } else {
-        if (p == 0) break;
+        if (p == NULL) break;
         if (p->flags & FINISHED) continue;
         thread = p->stop_info.mach_thread;
+        thread_blocked = (GC_bool)p->thread_blocked;
       }
 
       nthreads++;
       if (thread == me) {
-        /* FIXME: check thread not blocked */
+        GC_ASSERT(!thread_blocked);
         lo = GC_approx_sp();
 #       ifndef DARWIN_DONT_PARSE_STACK
-          hi = (ptr_t)FindTopOfStack(0);
+          hi = GC_FindTopOfStack(0);
 #       endif
         found_me = TRUE;
-      } else {
-        /* FIXME: if blocked then use stop_info.stack_ptr for lo */
 
+      } else if (thread_blocked) {
+        lo = p->stop_info.stack_ptr;
+#       ifndef DARWIN_DONT_PARSE_STACK
+          hi = p->topOfStack;
+#       endif
+
+      } else {
         /* MACHINE_THREAD_STATE_COUNT does not seem to be defined       */
         /* everywhere.  Hence we use our own version.  Alternatively,   */
         /* we could use THREAD_STATE_MAX (but seems to be not optimal). */
@@ -162,7 +170,7 @@ GC_INNER void GC_push_all_stacks(void)
 #       if defined(I386)
           lo = (void *)state.THREAD_FLD(esp);
 #         ifndef DARWIN_DONT_PARSE_STACK
-            hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(esp));
+            hi = GC_FindTopOfStack(state.THREAD_FLD(esp));
 #         endif
           GC_push_one(state.THREAD_FLD(eax));
           GC_push_one(state.THREAD_FLD(ebx));
@@ -175,7 +183,7 @@ GC_INNER void GC_push_all_stacks(void)
 #       elif defined(X86_64)
           lo = (void *)state.THREAD_FLD(rsp);
 #         ifndef DARWIN_DONT_PARSE_STACK
-            hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(rsp));
+            hi = GC_FindTopOfStack(state.THREAD_FLD(rsp));
 #         endif
           GC_push_one(state.THREAD_FLD(rax));
           GC_push_one(state.THREAD_FLD(rbx));
@@ -197,7 +205,7 @@ GC_INNER void GC_push_all_stacks(void)
 #       elif defined(POWERPC)
           lo = (void *)(state.THREAD_FLD(r1) - PPC_RED_ZONE_SIZE);
 #         ifndef DARWIN_DONT_PARSE_STACK
-            hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(r1));
+            hi = GC_FindTopOfStack(state.THREAD_FLD(r1));
 #         endif
           GC_push_one(state.THREAD_FLD(r0));
           GC_push_one(state.THREAD_FLD(r2));
@@ -234,7 +242,7 @@ GC_INNER void GC_push_all_stacks(void)
 #       elif defined(ARM32)
           lo = (void *)state.__sp;
 #         ifndef DARWIN_DONT_PARSE_STACK
-            hi = (ptr_t)FindTopOfStack(state.__sp);
+            hi = GC_FindTopOfStack(state.__sp);
 #         endif
           GC_push_one(state.__r[0]);
           GC_push_one(state.__r[1]);
@@ -258,20 +266,22 @@ GC_INNER void GC_push_all_stacks(void)
 #         error FIXME for non-x86 || ppc || arm architectures
 #       endif
       } /* thread != me */
+
 #     ifdef DARWIN_DONT_PARSE_STACK
+        /* p is non-NULL since GC_query_task_threads is FALSE */
         hi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end;
 #     endif
 #     ifdef DEBUG_THREADS
         GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n",
                   (unsigned long) thread, lo, hi);
 #     endif
-      /* FIXME: use GC_push_all_stack_sections */
-      GC_push_all_stack(lo, hi);
       total_size += hi - lo; /* lo <= hi */
       if (GC_query_task_threads) {
+        GC_push_all_stack(lo, hi);
         mach_port_deallocate(my_task, thread);
         break;
       }
+      GC_push_all_stack_sections(lo, hi, p->traced_stack_sect);
     } /* for (p) */
   } /* for (i=0; ...) */
 
index 3c804a52509997897b4cae9cf40239616e91013c..04a8b55c0529fe1e05257495a52134da13edc851 100644 (file)
@@ -67,7 +67,7 @@ typedef struct GC_Thread_Rep {
                                 /* Treated as a boolean value.  If set, */
                                 /* thread will acquire GC lock before   */
                                 /* doing any pointer manipulations, and */
-                                /* has set its sp value.  Thus it does  */
+                                /* has set its SP value.  Thus it does  */
                                 /* not need to be sent a signal to stop */
                                 /* it.                                  */
 
@@ -80,6 +80,11 @@ typedef struct GC_Thread_Rep {
 
     ptr_t stack_end;            /* Cold end of the stack (except for    */
                                 /* main thread).                        */
+#   if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
+      ptr_t topOfStack;         /* Result of GC_FindTopOfStack(0);      */
+                                /* valid only if the thread is blocked; */
+                                /* non-NULL value means already set.    */
+#   endif
 #   ifdef IA64
         ptr_t backing_store_end;
         ptr_t backing_store_ptr;
index 6c20209885f47c5e9cfad2b53e274d595c4a07a6..f7da17270023d89ac2329cc46eb34eacb5d5dbf3 100644 (file)
@@ -998,6 +998,10 @@ GC_INNER void GC_init_parallel(void)
   }
 #endif /* !GC_DARWIN_THREADS && !GC_OPENBSD_THREADS */
 
+#if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
+  GC_INNER ptr_t GC_FindTopOfStack(unsigned long);
+#endif
+
 /* Wrapper for functions that are likely to block for an appreciable    */
 /* length of time.                                                      */
 
@@ -1006,18 +1010,32 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context)
 {
     struct blocking_data * d = (struct blocking_data *) data;
     GC_thread me;
+#   if defined(SPARC) || defined(IA64)
+        ptr_t stack_ptr = GC_save_regs_in_stack();
+#   endif
+#   if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
+        GC_bool topOfStackUnset = FALSE;
+#   endif
     DCL_LOCK_STATE;
 
     LOCK();
     me = GC_lookup_thread(pthread_self());
     GC_ASSERT(!(me -> thread_blocked));
 #   ifdef SPARC
-        me -> stop_info.stack_ptr = GC_save_regs_in_stack();
+        me -> stop_info.stack_ptr = stack_ptr;
 #   else
         me -> stop_info.stack_ptr = GC_approx_sp();
 #   endif
+#   if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
+        if (me -> topOfStack == NULL) {
+            /* GC_do_blocking_inner is not called recursively,  */
+            /* so topOfStack should be computed now.            */
+            topOfStackUnset = TRUE;
+            me -> topOfStack = GC_FindTopOfStack(0);
+        }
+#   endif
 #   ifdef IA64
-        me -> backing_store_ptr = GC_save_regs_in_stack();
+        me -> backing_store_ptr = stack_ptr;
 #   endif
     me -> thread_blocked = (unsigned char)TRUE;
     /* Save context here if we want to support precise stack marking */
@@ -1025,6 +1043,10 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context)
     d -> client_data = (d -> fn)(d -> client_data);
     LOCK();   /* This will block if the world is stopped.       */
     me -> thread_blocked = FALSE;
+#   if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK)
+        if (topOfStackUnset)
+            me -> topOfStack = NULL; /* make topOfStack unset again */
+#   endif
     UNLOCK();
 }
 
index 40f39158e4755fe261294d94edd187cddc3f1691..894e10fd939377caaae79906a3ebbbcec72d3eb8 100644 (file)
@@ -764,13 +764,16 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context)
   struct blocking_data * d = (struct blocking_data *) data;
   DWORD t = GetCurrentThreadId();
   GC_thread me;
+# ifdef IA64
+    ptr_t stack_ptr = GC_save_regs_in_stack();
+# endif
   DCL_LOCK_STATE;
 
   LOCK();
   me = GC_lookup_thread_inner(t);
   GC_ASSERT(me -> thread_blocked_sp == NULL);
 # ifdef IA64
-    me -> backing_store_ptr = GC_save_regs_in_stack();
+    me -> backing_store_ptr = stack_ptr;
 # endif
   me -> thread_blocked_sp = (ptr_t) &d; /* save approx. sp */
   /* Save context here if we want to support precise stack marking */