diff options
Diffstat (limited to 'boehm-gc/darwin_stop_world.c')
-rw-r--r-- | boehm-gc/darwin_stop_world.c | 113 |
1 files changed, 104 insertions, 9 deletions
diff --git a/boehm-gc/darwin_stop_world.c b/boehm-gc/darwin_stop_world.c index 2fad9474716..22c76a85733 100644 --- a/boehm-gc/darwin_stop_world.c +++ b/boehm-gc/darwin_stop_world.c @@ -14,7 +14,13 @@ Page 50: "If a leaf procedure's red zone usage would exceed 224 bytes, then it must set up a stack frame just like routines that call other routines." */ -#define PPC_RED_ZONE_SIZE 224 +#ifdef POWERPC +# if CPP_WORDSZ == 32 +# define PPC_RED_ZONE_SIZE 224 +# elif CPP_WORDSZ == 64 +# define PPC_RED_ZONE_SIZE 320 +# endif +#endif typedef struct StackFrame { unsigned long savedSP; @@ -24,12 +30,17 @@ typedef struct StackFrame { unsigned long savedRTOC; } StackFrame; - -unsigned int FindTopOfStack(unsigned int stack_start) { +unsigned long FindTopOfStack(unsigned int stack_start) { StackFrame *frame; if (stack_start == 0) { - __asm__ volatile("lwz %0,0(r1)" : "=r" (frame)); +# ifdef POWERPC +# if CPP_WORDSZ == 32 + __asm__ volatile("lwz %0,0(r1)" : "=r" (frame)); +# else + __asm__ volatile("ldz %0,0(r1)" : "=r" (frame)); +# endif +# endif } else { frame = (StackFrame *)stack_start; } @@ -38,7 +49,7 @@ unsigned int FindTopOfStack(unsigned int stack_start) { /* GC_printf1("FindTopOfStack start at sp = %p\n", frame); */ # endif do { - if (frame->savedSP == NULL) break; + if (frame->savedSP == 0) break; /* if there are no more stack frames, stop */ frame = (StackFrame*)frame->savedSP; @@ -54,9 +65,88 @@ unsigned int FindTopOfStack(unsigned int stack_start) { /* GC_printf1("FindTopOfStack finish at sp = %p\n", frame); */ # endif - return (unsigned int)frame; + return (unsigned long)frame; } +#ifdef DARWIN_DONT_PARSE_STACK +void GC_push_all_stacks() { + int i; + kern_return_t r; + GC_thread p; + pthread_t me; + ptr_t lo, hi; + ppc_thread_state_t state; + mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT; + + me = pthread_self(); + if (!GC_thr_initialized) GC_thr_init(); + + for(i=0;i<THREAD_TABLE_SZ;i++) { + for(p=GC_threads[i];p!=0;p=p->next) { + if(p -> flags & FINISHED) continue; + if(pthread_equal(p->id,me)) { + lo = GC_approx_sp(); + } else { + /* Get the thread state (registers, etc) */ + r = thread_get_state( + p->stop_info.mach_thread, + MACHINE_THREAD_STATE, + (natural_t*)&state, + &thread_state_count); + if(r != KERN_SUCCESS) ABORT("thread_get_state failed"); + + lo = (void*)(state.r1 - PPC_RED_ZONE_SIZE); + + GC_push_one(state.r0); + GC_push_one(state.r2); + GC_push_one(state.r3); + GC_push_one(state.r4); + GC_push_one(state.r5); + GC_push_one(state.r6); + GC_push_one(state.r7); + GC_push_one(state.r8); + GC_push_one(state.r9); + GC_push_one(state.r10); + GC_push_one(state.r11); + GC_push_one(state.r12); + GC_push_one(state.r13); + GC_push_one(state.r14); + GC_push_one(state.r15); + GC_push_one(state.r16); + GC_push_one(state.r17); + GC_push_one(state.r18); + GC_push_one(state.r19); + GC_push_one(state.r20); + GC_push_one(state.r21); + GC_push_one(state.r22); + GC_push_one(state.r23); + GC_push_one(state.r24); + GC_push_one(state.r25); + GC_push_one(state.r26); + GC_push_one(state.r27); + GC_push_one(state.r28); + GC_push_one(state.r29); + GC_push_one(state.r30); + GC_push_one(state.r31); + } /* p != me */ + if(p->flags & MAIN_THREAD) + hi = GC_stackbottom; + else + hi = p->stack_end; +#if DEBUG_THREADS + GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n", + (unsigned long) p -> id, + (unsigned long) lo, + (unsigned long) hi + ); +#endif + GC_push_all_stack(lo,hi); + } /* for(p=GC_threads[i]...) */ + } /* for(i=0;i<THREAD_TABLE_SZ...) */ +} + +#else /* !DARWIN_DONT_PARSE_STACK; Use FindTopOfStack() */ + void GC_push_all_stacks() { int i; kern_return_t r; @@ -76,8 +166,12 @@ void GC_push_all_stacks() { lo = GC_approx_sp(); hi = (ptr_t)FindTopOfStack(0); } else { -# ifdef POWERPC +# if defined(POWERPC) +# if CPP_WORDSZ == 32 ppc_thread_state_t info; +# else + ppc_thread_state64_t info; +# endif mach_msg_type_number_t outCount = THREAD_STATE_MAX; r = thread_get_state(thread, MACHINE_THREAD_STATE, (natural_t *)&info, &outCount); @@ -156,6 +250,7 @@ void GC_push_all_stacks() { GC_push_all_stack(lo, hi); } /* for(p=GC_threads[i]...) */ } +#endif /* !DARWIN_DONT_PARSE_STACK */ static mach_port_t GC_mach_handler_thread; static int GC_use_mach_handler_thread = 0; @@ -325,6 +420,8 @@ void GC_start_world() kern_return_t kern_result; thread_act_array_t act_list; mach_msg_type_number_t listcount; + struct thread_basic_info info; + mach_msg_type_number_t outCount = THREAD_INFO_MAX; # if DEBUG_THREADS GC_printf0("World starting\n"); @@ -351,8 +448,6 @@ void GC_start_world() # endif continue; } - struct thread_basic_info info; - mach_msg_type_number_t outCount = THREAD_INFO_MAX; kern_result = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &outCount); if(kern_result != KERN_SUCCESS) ABORT("thread_info failed"); |