summaryrefslogtreecommitdiff
path: root/boehm-gc/darwin_stop_world.c
diff options
context:
space:
mode:
Diffstat (limited to 'boehm-gc/darwin_stop_world.c')
-rw-r--r--boehm-gc/darwin_stop_world.c113
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");