]> granicus.if.org Git - gc/commitdiff
2010-09-30 Ivan Maidanski <ivmai@mail.ru>
authorivmai <ivmai>
Thu, 30 Sep 2010 06:05:44 +0000 (06:05 +0000)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 26 Jul 2011 17:06:55 +0000 (21:06 +0400)
* darwin_stop_world.c (GC_query_task_threads): New variable (or
macro).
* darwin_stop_world.c (GC_push_all_stacks): Use
GC_query_task_threads (to choose between algorithms based on
kernel task_threads and based on GC_threads table); update FIXME;
remove commented out GC_push_one statements.
* pthread_support.c (GC_thr_init, GC_do_blocking_inner,
GC_call_with_gc_active, GC_register_my_thread_inner): Initialize
stack_ptr field for all platforms.
* pthread_support.c (GC_call_with_gc_active): Initialize
saved_stack_ptr field for all platforms.
* include/private/darwin_stop_world.h (thread_stop_info): Add
stack_ptr field; change type of already_suspended from int to
GC_bool.

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

index 3022f8027e8aea81a81ad79df024f005672edc90..20baeb1c29706e366cd1abc10fb0a0ee9451a873 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2010-09-30  Ivan Maidanski <ivmai@mail.ru>
+
+       * darwin_stop_world.c (GC_query_task_threads): New variable (or
+       macro).
+       * darwin_stop_world.c (GC_push_all_stacks): Use
+       GC_query_task_threads (to choose between algorithms based on
+       kernel task_threads and based on GC_threads table); update FIXME;
+       remove commented out GC_push_one statements.
+       * pthread_support.c (GC_thr_init, GC_do_blocking_inner,
+       GC_call_with_gc_active, GC_register_my_thread_inner): Initialize
+       stack_ptr field for all platforms.
+       * pthread_support.c (GC_call_with_gc_active): Initialize
+       saved_stack_ptr field for all platforms.
+       * include/private/darwin_stop_world.h (thread_stop_info): Add
+       stack_ptr field; change type of already_suspended from int to
+       GC_bool.
+
 2010-09-29  Ivan Maidanski <ivmai@mail.ru>
 
        * darwin_stop_world.c (GC_MAX_MACH_THREADS): New macro.
index 034faf368532d3901ec2bfb7b377e2e6fcbca3e5..3874d37bd9e54f3145ce6d25b2786103d8763d2f 100644 (file)
@@ -87,6 +87,16 @@ static unsigned long FindTopOfStack(unsigned long stack_start)
 
 #endif /* !DARWIN_DONT_PARSE_STACK */
 
+/* GC_query_task_threads controls whether to obtain the list of */
+/* the threads from the kernel or to use GC_threads table.      */
+#ifdef DARWIN_DONT_PARSE_STACK
+# define GC_query_task_threads FALSE
+#else
+  /* FIXME: use STATIC; initialize to false, add setter function. */
+  /* FIXME: use it in GC_stop_world and GC_start_world. */
+  GC_bool GC_query_task_threads = TRUE;
+#endif
+
 GC_INNER void GC_push_all_stacks(void)
 {
   int i;
@@ -96,45 +106,44 @@ GC_INNER void GC_push_all_stacks(void)
   mach_port_t me = mach_thread_self();
   GC_bool found_me = FALSE;
   int nthreads = 0;
-# ifndef DARWIN_DONT_PARSE_STACK
-    task_t my_task;
-    thread_act_array_t act_list = 0;
-    mach_msg_type_number_t listcount = 0;
-# endif
+  mach_msg_type_number_t listcount = (mach_msg_type_number_t)THREAD_TABLE_SZ;
+  task_t my_task = 0; /* initialized to prevent a warning */
+  thread_act_array_t act_list = 0;
 
   if (!GC_thr_initialized)
     GC_thr_init();
 
-# ifdef DARWIN_DONT_PARSE_STACK
-    for (i = 0; i < THREAD_TABLE_SZ; i++)
-# else
+  if (GC_query_task_threads) {
+    /* Obtain the list of the threads from the kernel.  */
     my_task = current_task();
     r = task_threads(my_task, &act_list, &listcount);
     if (r != KERN_SUCCESS)
       ABORT("task_threads failed");
+  }
 
-    for (i = 0; i < (int)listcount; i++)
-# endif
-  {
-#   ifdef DARWIN_DONT_PARSE_STACK
-      GC_thread p;
-      for (p = GC_threads[i]; p != 0; p = p->next)
-#   endif
-    {
-#     ifdef DARWIN_DONT_PARSE_STACK
-        thread_act_t thread = p->stop_info.mach_thread;
+  for (i = 0; i < (int)listcount; i++) {
+    GC_thread p = GC_query_task_threads ? 0 : GC_threads[i];
+    for (;; p = p->next) {
+      thread_act_t thread;
+      if (GC_query_task_threads) {
+        thread = act_list[i];
+      } else {
+        if (p == 0) break;
         if (p->flags & FINISHED) continue;
-#     else
-        thread_act_t thread = act_list[i];
-#     endif
+        thread = p->stop_info.mach_thread;
+      }
+
       nthreads++;
       if (thread == me) {
+        /* FIXME: check thread not blocked */
         lo = GC_approx_sp();
 #       ifndef DARWIN_DONT_PARSE_STACK
           hi = (ptr_t)FindTopOfStack(0);
 #       endif
         found_me = TRUE;
       } else {
+        /* FIXME: if blocked then use stop_info.stack_ptr for lo */
+
         /* 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,14 +171,6 @@ GC_INNER void GC_push_all_stacks(void)
           GC_push_one(state.THREAD_FLD(edi));
           GC_push_one(state.THREAD_FLD(esi));
           GC_push_one(state.THREAD_FLD(ebp));
-          /* GC_push_one(state.THREAD_FLD(esp)); */
-          /* GC_push_one(state.THREAD_FLD(ss));
-          GC_push_one(state.THREAD_FLD(eip));
-          GC_push_one(state.THREAD_FLD(cs));
-          GC_push_one(state.THREAD_FLD(ds));
-          GC_push_one(state.THREAD_FLD(es));
-          GC_push_one(state.THREAD_FLD(fs));
-          GC_push_one(state.THREAD_FLD(gs)); */
 
 #       elif defined(X86_64)
           lo = (void *)state.THREAD_FLD(rsp);
@@ -192,11 +193,6 @@ GC_INNER void GC_push_all_stacks(void)
           GC_push_one(state.THREAD_FLD(r13));
           GC_push_one(state.THREAD_FLD(r14));
           GC_push_one(state.THREAD_FLD(r15));
-          /* GC_push_one(state.THREAD_FLD(rip));
-          GC_push_one(state.THREAD_FLD(rflags));
-          GC_push_one(state.THREAD_FLD(cs));
-          GC_push_one(state.THREAD_FLD(fs));
-          GC_push_one(state.THREAD_FLD(gs)); */
 
 #       elif defined(POWERPC)
           lo = (void *)(state.THREAD_FLD(r1) - PPC_RED_ZONE_SIZE);
@@ -269,21 +265,22 @@ GC_INNER void GC_push_all_stacks(void)
         GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n",
                   (unsigned long) thread, lo, hi);
 #     endif
-      /* FIXME: It is impossible to use GC_push_all_stack_sections()    */
-      /* here while GC_do_blocking_inner() and GC_call_with_gc_active() */
-      /* contain unimplemented code for Darwin.                         */
+      /* FIXME: use GC_push_all_stack_sections */
       GC_push_all_stack(lo, hi);
-#     ifndef DARWIN_DONT_PARSE_STACK
-        mach_port_deallocate(my_task, thread);
-#     endif
       total_size += hi - lo; /* lo <= hi */
-    }
+      if (GC_query_task_threads) {
+        mach_port_deallocate(my_task, thread);
+        break;
+      }
+    } /* for (p) */
   } /* for (i=0; ...) */
-# ifndef DARWIN_DONT_PARSE_STACK
+
+  if (GC_query_task_threads) {
+    mach_port_deallocate(my_task, me);
     vm_deallocate(my_task, (vm_address_t)act_list,
                   sizeof(thread_t) * listcount);
-    mach_port_deallocate(my_task, me);
-# endif
+  }
+
   if (GC_print_stats == VERBOSE)
     GC_log_printf("Pushed %d thread stacks\n", nthreads);
   if (!found_me && !GC_in_thread_creation)
index d726df55b46670c3e8a0f8b6305868089270cdb5..f4808697dbebdb7140a57f02dfee2c9a19f4bab6 100644 (file)
 
 struct thread_stop_info {
   mach_port_t mach_thread;
+  ptr_t stack_ptr; /* Valid only when stopped.  */
 };
 
 struct GC_mach_thread {
   thread_act_t thread;
-  int already_suspended;
+  GC_bool already_suspended;
 };
 
 #endif
index 8688d90b50b659b9b92d7dc2e5ca6055acb8843b..7610ce2eefbb2659878468e0c0dbd3b5a0ed60bf 100644 (file)
@@ -348,9 +348,9 @@ STATIC void * GC_mark_thread(void * id)
 # ifdef IA64
     marker_bsp[(word)id] = GC_save_regs_in_stack();
 # endif
-#ifdef GC_DARWIN_THREADS
+# ifdef GC_DARWIN_THREADS
     marker_mach_threads[(word)id] = mach_thread_self();
-#endif
+# endif
 
   if ((word)id == (word)-1) return 0; /* to make compiler happy */
 
@@ -840,7 +840,7 @@ STATIC void GC_fork_child_proc(void)
     sysctl(mib, sizeof(mib)/sizeof(int), &res, &len, NULL, 0);
     return res;
   }
-#endif  /* GC_NETBSD_THREADS */
+#endif  /* GC_DARWIN_THREADS || ... */
 
 #if defined(GC_LINUX_THREADS) && defined(INCLUDE_LINUX_THREAD_DESCR)
   __thread int GC_dummy_thread_local;
@@ -849,10 +849,7 @@ STATIC void GC_fork_child_proc(void)
 /* We hold the allocation lock. */
 GC_INNER void GC_thr_init(void)
 {
-#   ifndef GC_DARWIN_THREADS
-        int dummy;
-#   endif
-    GC_thread t;
+    int dummy;
 
     if (GC_thr_initialized) return;
     GC_thr_initialized = TRUE;
@@ -878,13 +875,14 @@ GC_INNER void GC_thr_init(void)
         }
 #   endif
     /* Add the initial thread, so we can stop it.       */
-      t = GC_new_thread(pthread_self());
+    {
+      GC_thread t = GC_new_thread(pthread_self());
 #     ifdef GC_DARWIN_THREADS
-         t -> stop_info.mach_thread = mach_thread_self();
-#     else
-         t -> stop_info.stack_ptr = (ptr_t)(&dummy);
+        t -> stop_info.mach_thread = mach_thread_self();
 #     endif
+      t -> stop_info.stack_ptr = (ptr_t)(&dummy);
       t -> flags = DETACHED | MAIN_THREAD;
+    }
 
     GC_stop_init();
 
@@ -998,7 +996,7 @@ GC_INNER void GC_init_parallel(void)
     }
     return(REAL_FUNC(pthread_sigmask)(how, set, oset));
   }
-#endif /* !GC_DARWIN_THREADS */
+#endif /* !GC_DARWIN_THREADS && !GC_OPENBSD_THREADS */
 
 /* Wrapper for functions that are likely to block for an appreciable    */
 /* length of time.                                                      */
@@ -1015,7 +1013,7 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context)
     GC_ASSERT(!(me -> thread_blocked));
 #   ifdef SPARC
         me -> stop_info.stack_ptr = GC_save_regs_in_stack();
-#   elif !defined(GC_DARWIN_THREADS)
+#   else
         me -> stop_info.stack_ptr = GC_approx_sp();
 #   endif
 #   ifdef IA64
@@ -1063,11 +1061,7 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn,
     }
 
     /* Setup new "stack section".       */
-#   ifdef GC_DARWIN_THREADS
-      /* FIXME: Implement it (and GC_do_blocking_inner) for Darwin. */
-#   else
-      stacksect.saved_stack_ptr = me -> stop_info.stack_ptr;
-#   endif
+    stacksect.saved_stack_ptr = me -> stop_info.stack_ptr;
 #   ifdef IA64
       /* This is the same as in GC_call_with_stack_base().      */
       stacksect.backing_store_end = GC_save_regs_in_stack();
@@ -1091,9 +1085,7 @@ GC_API void * GC_CALL GC_call_with_gc_active(GC_fn_type fn,
       me -> backing_store_ptr = stacksect.saved_backing_store_ptr;
 #   endif
     me -> thread_blocked = TRUE;
-#   ifndef GC_DARWIN_THREADS
-      me -> stop_info.stack_ptr = stacksect.saved_stack_ptr;
-#   endif
+    me -> stop_info.stack_ptr = stacksect.saved_stack_ptr;
     UNLOCK();
 
     return client_data; /* result */
@@ -1270,9 +1262,8 @@ STATIC GC_thread GC_register_my_thread_inner(const struct GC_stack_base *sb,
       ABORT("Failed to allocate memory for thread registering.");
 #   ifdef GC_DARWIN_THREADS
       me -> stop_info.mach_thread = mach_thread_self();
-#   else
-      me -> stop_info.stack_ptr = sb -> mem_base;
 #   endif
+    me -> stop_info.stack_ptr = sb -> mem_base;
     me -> stack_end = sb -> mem_base;
     if (me -> stack_end == NULL)
       ABORT("Bad stack base in GC_register_my_thread");