X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=libgc%2Fdarwin_stop_world.c;h=ac50256fd1f6d965262463b038dfd27cd0e24522;hb=577517c3bc1cc8f0ab6f2518b555eaf56861e349;hp=60acd83c6bd663155fea7cf8b5f014a56b61e90f;hpb=97fcf119b390d0e13d16fd29519f18510c30fe7e;p=mono.git diff --git a/libgc/darwin_stop_world.c b/libgc/darwin_stop_world.c index 60acd83c6bd..ac50256fd1f 100644 --- a/libgc/darwin_stop_world.c +++ b/libgc/darwin_stop_world.c @@ -2,6 +2,13 @@ # if defined(GC_DARWIN_THREADS) +#include +#include "mono/utils/mono-compiler.h" + +#ifdef MONO_DEBUGGER_SUPPORTED +#include "include/libgc-mono-debugger.h" +#endif + /* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple Page 49: "The space beneath the stack pointer, where a new stack frame would normally @@ -12,23 +19,33 @@ 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 -/* Not 64-bit clean. Wait until Apple defines their 64-bit ABI */ typedef struct StackFrame { - unsigned int savedSP; - unsigned int savedCR; - unsigned int savedLR; - unsigned int reserved[2]; - unsigned int savedRTOC; + unsigned long savedSP; + unsigned long savedCR; + unsigned long savedLR; + unsigned long reserved[2]; + 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; } @@ -37,7 +54,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; @@ -53,11 +70,205 @@ 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; +#if defined(POWERPC) + ppc_thread_state_t state; + mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT; +#elif defined(I386) + i386_thread_state_t state; + mach_msg_type_number_t thread_state_count = i386_THREAD_STATE_COUNT; +#elif defined(ARM) + arm_thread_state_t state; + mach_msg_type_number_t thread_state_count = ARM_THREAD_STATE_COUNT; +#elif defined(X86_64) + x86_thread_state64_t state; + mach_msg_type_number_t thread_state_count = x86_THREAD_STATE64_COUNT; +#else +# error FIXME for non-x86 || ppc architectures + mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT; +#endif + + me = pthread_self(); + if (!GC_thr_initialized) GC_thr_init(); + + for(i=0;inext) { + 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, + GC_MACH_THREAD_STATE_FLAVOR, + (natural_t*)&state, + &thread_state_count); + if(r != KERN_SUCCESS) continue; + +#if defined(I386) +#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + + lo = state.__esp; + + GC_push_one(state.__eax); + GC_push_one(state.__ebx); + GC_push_one(state.__ecx); + GC_push_one(state.__edx); + GC_push_one(state.__edi); + GC_push_one(state.__esi); + GC_push_one(state.__ebp); +#else + lo = state.esp; + + GC_push_one(state.eax); + GC_push_one(state.ebx); + GC_push_one(state.ecx); + GC_push_one(state.edx); + GC_push_one(state.edi); + GC_push_one(state.esi); + GC_push_one(state.ebp); +#endif +#elif defined(X86_64) + lo = state.__rsp; + GC_push_one(state.__rax); + GC_push_one(state.__rbx); + GC_push_one(state.__rcx); + GC_push_one(state.__rdx); + GC_push_one(state.__rdi); + GC_push_one(state.__rsi); + GC_push_one(state.__rbp); + 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); +#elif defined(POWERPC) +#if defined(_STRUCT_PPC_EXCEPTION_STATE) && defined(__DARWIN_UNIX03) + 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); +#else + 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); +#endif +#elif defined(ARM) + lo = (void*)state.__sp; + + GC_push_one(state.__r[0]); + GC_push_one(state.__r[1]); + GC_push_one(state.__r[2]); + GC_push_one(state.__r[3]); + GC_push_one(state.__r[4]); + GC_push_one(state.__r[5]); + GC_push_one(state.__r[6]); + GC_push_one(state.__r[7]); + GC_push_one(state.__r[8]); + GC_push_one(state.__r[9]); + GC_push_one(state.__r[10]); + GC_push_one(state.__r[11]); + GC_push_one(state.__r[12]); + /* GC_push_one(state.__sp); */ + GC_push_one(state.__lr); + GC_push_one(state.__pc); + GC_push_one(state.__cpsr); +#else +# error FIXME for non-x86 || ppc architectures +#endif + } /* 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= MAC_OS_X_VERSION_10_5 + lo = (void*)info.__esp; + hi = (ptr_t)FindTopOfStack(info.__esp); + + GC_push_one(info.__eax); + GC_push_one(info.__ebx); + GC_push_one(info.__ecx); + GC_push_one(info.__edx); + GC_push_one(info.__edi); + GC_push_one(info.__esi); + GC_push_one(info.__ebp); + /* GC_push_one(info.__esp); */ + GC_push_one(info.__ss); + GC_push_one(info.__eip); + GC_push_one(info.__cs); + GC_push_one(info.__ds); + GC_push_one(info.__es); + GC_push_one(info.__fs); + GC_push_one(info.__gs); +#else lo = (void*)info.esp; hi = (ptr_t)FindTopOfStack(info.esp); @@ -134,7 +407,7 @@ void GC_push_all_stacks() { GC_push_one(info.edx); GC_push_one(info.edi); GC_push_one(info.esi); - /* GC_push_one(info.ebp); */ + GC_push_one(info.ebp); /* GC_push_one(info.esp); */ GC_push_one(info.ss); GC_push_one(info.eip); @@ -143,7 +416,35 @@ void GC_push_all_stacks() { GC_push_one(info.es); GC_push_one(info.fs); GC_push_one(info.gs); -# endif /* !POWERPC */ +#endif +# elif defined(ARM) /* !I386 */ + arm_thread_state_t info; + mach_msg_type_number_t outCount = THREAD_STATE_MAX; + r = thread_get_state(thread, GC_MACH_THREAD_STATE_FLAVOR, + (natural_t *)&info, &outCount); + if(r != KERN_SUCCESS) continue; + + lo = (void*)info.__sp; + hi = (ptr_t)FindTopOfStack(info.__sp); + + GC_push_one(info.__r[0]); + GC_push_one(info.__r[1]); + GC_push_one(info.__r[2]); + GC_push_one(info.__r[3]); + GC_push_one(info.__r[4]); + GC_push_one(info.__r[5]); + GC_push_one(info.__r[6]); + GC_push_one(info.__r[7]); + GC_push_one(info.__r[8]); + GC_push_one(info.__r[9]); + GC_push_one(info.__r[10]); + GC_push_one(info.__r[11]); + GC_push_one(info.__r[12]); + /* GC_push_one(info.__sp); */ + GC_push_one(info.__lr); + GC_push_one(info.__pc); + GC_push_one(info.__cpsr); +# endif /* !ARM */ } # if DEBUG_THREADS GC_printf3("Darwin: Stack for thread 0x%lx = [%lx,%lx)\n", @@ -152,21 +453,25 @@ void GC_push_all_stacks() { (unsigned long) hi ); # endif - GC_push_all_stack(lo, hi); + GC_push_all_stack(lo, hi); + mach_port_deallocate(my_task, thread); } /* for(p=GC_threads[i]...) */ - vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount); + vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount); + mach_port_deallocate(my_task, me); } +#endif /* !DARWIN_DONT_PARSE_STACK */ static mach_port_t GC_mach_handler_thread; static int GC_use_mach_handler_thread = 0; -static struct GC_mach_thread GC_mach_threads[THREAD_TABLE_SZ]; +#define SUSPEND_THREADS_SIZE 2048 +static struct GC_mach_thread GC_mach_threads[SUSPEND_THREADS_SIZE]; static int GC_mach_threads_count; void GC_stop_init() { int i; - for (i = 0; i < THREAD_TABLE_SZ; i++) { + for (i = 0; i < SUSPEND_THREADS_SIZE; i++) { GC_mach_threads[i].thread = 0; GC_mach_threads[i].already_suspended = 0; } @@ -247,6 +552,8 @@ int GC_suspend_thread_list(thread_act_array_t act_list, int count, } if (!found) GC_mach_threads_count++; } + + mach_port_deallocate(current_task(), my_thread); return changed; } @@ -256,6 +563,7 @@ void GC_stop_world() { int i, changes; GC_thread p; + task_t my_task = current_task(); mach_port_t my_thread = mach_thread_self(); kern_return_t kern_result; thread_act_array_t act_list, prev_list; @@ -290,16 +598,31 @@ void GC_stop_world() prev_list = NULL; prevcount = 0; do { - int result; - kern_result = task_threads(current_task(), &act_list, &listcount); - result = GC_suspend_thread_list(act_list, listcount, - prev_list, prevcount); - changes = result; - prev_list = act_list; - prevcount = listcount; - vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount); + int result; + kern_result = task_threads(my_task, &act_list, &listcount); + + if(kern_result == KERN_SUCCESS) { + result = GC_suspend_thread_list(act_list, listcount, + prev_list, prevcount); + changes = result; + + if(prev_list != NULL) { + for(i = 0; i < prevcount; i++) + mach_port_deallocate(my_task, prev_list[i]); + + vm_deallocate(my_task, (vm_address_t)prev_list, sizeof(thread_t) * prevcount); + } + + prev_list = act_list; + prevcount = listcount; + } } while (changes); - + + for(i = 0; i < listcount; i++) + mach_port_deallocate(my_task, act_list[i]); + + vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount); + # ifdef MPROTECT_VDB if(GC_incremental) { @@ -314,18 +637,23 @@ void GC_stop_world() #if DEBUG_THREADS GC_printf1("World stopped from 0x%lx\n", my_thread); #endif + + mach_port_deallocate(my_task, my_thread); } /* Caller holds allocation lock, and has held it continuously since */ /* the world stopped. */ void GC_start_world() { + task_t my_task = current_task(); mach_port_t my_thread = mach_thread_self(); int i, j; GC_thread p; 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"); @@ -338,7 +666,7 @@ void GC_start_world() } # endif - kern_result = task_threads(current_task(), &act_list, &listcount); + kern_result = task_threads(my_task, &act_list, &listcount); for(i = 0; i < listcount; i++) { thread_act_t thread = act_list[i]; if (thread != my_thread && @@ -352,8 +680,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) continue; @@ -368,8 +694,12 @@ void GC_start_world() } } } + + mach_port_deallocate(my_task, thread); } - vm_deallocate(current_task(), (vm_address_t)act_list, sizeof(thread_t) * listcount); + vm_deallocate(my_task, (vm_address_t)act_list, sizeof(thread_t) * listcount); + + mach_port_deallocate(my_task, my_thread); # if DEBUG_THREADS GC_printf0("World started\n"); # endif @@ -380,4 +710,17 @@ void GC_darwin_register_mach_handler_thread(mach_port_t thread) { GC_use_mach_handler_thread = 1; } +#ifdef MONO_DEBUGGER_SUPPORTED +GCThreadFunctions *gc_thread_vtable = NULL; + +void * +GC_mono_debugger_get_stack_ptr (void) +{ + GC_thread me; + + me = GC_lookup_thread (pthread_self ()); + return &me->stop_info.stack_ptr; +} +#endif + #endif