+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.
#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;
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). */
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);
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);
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)
# 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 */
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;
/* 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;
}
# 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();
}
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. */
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
}
/* 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();
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 */
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");