/* Evaluates the stack range for a given thread. Returns the lower */
/* bound and sets *phi to the upper one. */
STATIC ptr_t GC_stack_range_for(ptr_t *phi, thread_act_t thread, GC_thread p,
- GC_bool thread_blocked, mach_port_t my_thread)
+ GC_bool thread_blocked, mach_port_t my_thread,
+ ptr_t *paltstack_lo, ptr_t *paltstack_hi)
{
ptr_t lo;
if (thread == my_thread) {
/* p is guaranteed to be non-NULL regardless of GC_query_task_threads. */
*phi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end;
# endif
+
+ if (p->altstack && lo >= p->altstack && lo <= p->altstack + p->altstack_size) {
+ *paltstack_lo = lo;
+ *paltstack_hi = p->altstack + p->altstack_size;
+ lo = (char*)p->stack;
+ *phi = (char*)p->stack + p->stack_size;
+ } else {
+ *paltstack_lo = NULL;
+ }
+
# ifdef DEBUG_THREADS
GC_log_printf("Darwin: Stack for thread %p = [%p,%p)\n",
(void *)thread, lo, *phi);
GC_INNER void GC_push_all_stacks(void)
{
int i;
- ptr_t lo, hi;
+ ptr_t lo, hi, altstack_lo, altstack_hi;
task_t my_task = current_task();
mach_port_t my_thread = mach_thread_self();
GC_bool found_me = FALSE;
for (i = 0; i < (int)listcount; i++) {
thread_act_t thread = act_list[i];
- lo = GC_stack_range_for(&hi, thread, NULL, FALSE, my_thread);
- GC_ASSERT((word)lo <= (word)hi);
- total_size += hi - lo;
- GC_push_all_stack(lo, hi);
+ lo = GC_stack_range_for(&hi, thread, NULL, FALSE, my_thread,
+ &altstack_lo, &altstack_hi);
+ if (lo) {
+ GC_ASSERT((word)lo <= (word)hi);
+ total_size += hi - lo;
+ GC_push_all_stack(lo,hi);
+ }
+ if (altstack_lo) {
+ total_size += altstack_hi - altstack_lo;
+ GC_push_all_stack(altstack_lo,altstack_hi);
+ }
nthreads++;
if (thread == my_thread)
found_me = TRUE;
if ((p->flags & FINISHED) == 0) {
thread_act_t thread = (thread_act_t)p->stop_info.mach_thread;
lo = GC_stack_range_for(&hi, thread, p, (GC_bool)p->thread_blocked,
- my_thread);
- GC_ASSERT((word)lo <= (word)hi);
- total_size += hi - lo;
- GC_push_all_stack_sections(lo, hi, p->traced_stack_sect);
+ my_thread, &altstack_lo, &altstack_hi);
+ if (lo) {
+ GC_ASSERT((word)lo <= (word)hi);
+ total_size += hi - lo;
+ GC_push_all_stack_sections(lo, hi, p->traced_stack_sect);
+ }
+ if (altstack_lo) {
+ total_size += altstack_hi - altstack_lo;
+ GC_push_all_stack(altstack_lo, altstack_hi);
+ }
nthreads++;
if (thread == my_thread)
found_me = TRUE;
/* registered with the garbage collector. */
GC_API int GC_CALL GC_thread_is_registered(void);
+/* Notify the collector about the stack and the altstack of the current thread */
+/* STACK/STACK_SIZE is used to determine the stack dimensions when a thread is
+ * suspended while it is on an altstack.
+ */
+GC_API void GC_register_altstack(void *stack, int stack_size, void *altstack, int altstack_size);
+
/* Unregister the current thread. Only an explicitly registered */
/* thread (i.e. for which GC_register_my_thread() returns GC_SUCCESS) */
/* is allowed (and required) to call this function. (As a special */
return me != NULL;
}
+static pthread_t main_pthread_self;
+static void *main_stack, *main_altstack;
+static int main_stack_size, main_altstack_size;
+
+void GC_register_altstack (void *stack, int stack_size, void *altstack, int altstack_size)
+{
+ GC_thread thread;
+
+ LOCK();
+ thread = (void *)GC_lookup_thread(pthread_self());
+ if (thread) {
+ thread->stack = stack;
+ thread->stack_size = stack_size;
+ thread->altstack = altstack;
+ thread->altstack_size = altstack_size;
+ } else {
+ /*
+ * This happens if we are called before GC_thr_init ().
+ */
+ main_pthread_self = pthread_self ();
+ main_stack = stack;
+ main_stack_size = stack_size;
+ main_altstack = altstack;
+ main_altstack_size = altstack_size;
+ }
+ UNLOCK();
+}
+
#ifdef CAN_HANDLE_FORK
/* Remove all entries from the GC_threads table, except the */
/* one for the current thread. We need to do this in the child */
t -> stop_info.stack_ptr = GC_approx_sp();
# endif
t -> flags = DETACHED | MAIN_THREAD;
+ if (pthread_self () == main_pthread_self) {
+ t->stack = main_stack;
+ t->stack_size = main_stack_size;
+ t->altstack = main_altstack;
+ t->altstack_size = main_altstack_size;
+ }
}
# ifndef GC_DARWIN_THREADS