From 24b29a7e89dc3b25b4d6933b7aaf49acf19c71a4 Mon Sep 17 00:00:00 2001 From: ivmai Date: Wed, 6 Oct 2010 20:09:27 +0000 Subject: [PATCH] 2010-10-06 Ivan Maidanski * darwin_stop_world.c (FindTopOfStack): Change return type to ptr_t (from long); make GC_INNER; add GC_ prefix. * darwin_stop_world.c (GC_push_all_stacks): Add thread_blocked local variable (initialized from the corresponding GC_thread field unless GC_query_task_threads); add assertion that our thread is not blocked; prefix FindTopOfStack with GC_ and remove no longer needed cast to ptr_t of the result; handle thread blocked case (and remove FIXME); use GC_push_all_stack_sections unless GC_query_task_threads (and remove FIXME). * pthread_support.c (GC_FindTopOfStack): Declare (if needed). * pthread_support.c (GC_do_blocking_inner): Call GC_save_regs_in_stack (if needed) before acquiring the lock. * win32_threads.c (GC_do_blocking_inner): Ditto. * pthread_support.c (GC_do_blocking_inner): Set/clear topOfStack field of GC_thread (Darwin only). * include/private/pthread_support.h (GC_thread): Add topOfStack field for Darwin (unless DARWIN_DONT_PARSE_STACK). --- ChangeLog | 20 ++++++++++++++++ darwin_stop_world.c | 40 +++++++++++++++++++------------ include/private/pthread_support.h | 7 +++++- pthread_support.c | 26 ++++++++++++++++++-- win32_threads.c | 5 +++- 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 441e6782..56095e82 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2010-10-06 Ivan Maidanski + + * darwin_stop_world.c (FindTopOfStack): Change return type to + ptr_t (from long); make GC_INNER; add GC_ prefix. + * darwin_stop_world.c (GC_push_all_stacks): Add thread_blocked + local variable (initialized from the corresponding GC_thread + field unless GC_query_task_threads); add assertion that our + thread is not blocked; prefix FindTopOfStack with GC_ and remove + no longer needed cast to ptr_t of the result; handle thread + blocked case (and remove FIXME); use GC_push_all_stack_sections + unless GC_query_task_threads (and remove FIXME). + * pthread_support.c (GC_FindTopOfStack): Declare (if needed). + * pthread_support.c (GC_do_blocking_inner): Call + GC_save_regs_in_stack (if needed) before acquiring the lock. + * win32_threads.c (GC_do_blocking_inner): Ditto. + * pthread_support.c (GC_do_blocking_inner): Set/clear topOfStack + field of GC_thread (Darwin only). + * include/private/pthread_support.h (GC_thread): Add topOfStack + field for Darwin (unless DARWIN_DONT_PARSE_STACK). + 2010-10-05 Ivan Maidanski * finalize.c (GC_check_finalizer_nested): Change return type to diff --git a/darwin_stop_world.c b/darwin_stop_world.c index 3874d37b..533ea76e 100644 --- a/darwin_stop_world.c +++ b/darwin_stop_world.c @@ -49,9 +49,9 @@ typedef struct StackFrame { unsigned long savedRTOC; } StackFrame; -static unsigned long FindTopOfStack(unsigned long stack_start) +GC_INNER ptr_t GC_FindTopOfStack(unsigned long stack_start) { - StackFrame *frame; + StackFrame *frame; if (stack_start == 0) { # ifdef POWERPC @@ -82,7 +82,7 @@ static unsigned long FindTopOfStack(unsigned long stack_start) # ifdef DEBUG_THREADS /* GC_printf("FindTopOfStack finish at sp = %p\n", frame); */ # endif - return (unsigned long)frame; + return (ptr_t)frame; } #endif /* !DARWIN_DONT_PARSE_STACK */ @@ -122,28 +122,36 @@ GC_INNER void GC_push_all_stacks(void) } for (i = 0; i < (int)listcount; i++) { - GC_thread p = GC_query_task_threads ? 0 : GC_threads[i]; + GC_thread p = GC_query_task_threads ? NULL : GC_threads[i]; for (;; p = p->next) { thread_act_t thread; + GC_bool thread_blocked; if (GC_query_task_threads) { thread = act_list[i]; + thread_blocked = FALSE; } else { - if (p == 0) break; + if (p == NULL) break; if (p->flags & FINISHED) continue; thread = p->stop_info.mach_thread; + thread_blocked = (GC_bool)p->thread_blocked; } nthreads++; if (thread == me) { - /* FIXME: check thread not blocked */ + GC_ASSERT(!thread_blocked); lo = GC_approx_sp(); # ifndef DARWIN_DONT_PARSE_STACK - hi = (ptr_t)FindTopOfStack(0); + hi = GC_FindTopOfStack(0); # endif found_me = TRUE; - } else { - /* FIXME: if blocked then use stop_info.stack_ptr for lo */ + } else if (thread_blocked) { + lo = p->stop_info.stack_ptr; +# ifndef DARWIN_DONT_PARSE_STACK + hi = p->topOfStack; +# endif + + } else { /* 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). */ @@ -162,7 +170,7 @@ GC_INNER void GC_push_all_stacks(void) # if defined(I386) lo = (void *)state.THREAD_FLD(esp); # ifndef DARWIN_DONT_PARSE_STACK - hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(esp)); + hi = GC_FindTopOfStack(state.THREAD_FLD(esp)); # endif GC_push_one(state.THREAD_FLD(eax)); GC_push_one(state.THREAD_FLD(ebx)); @@ -175,7 +183,7 @@ GC_INNER void GC_push_all_stacks(void) # elif defined(X86_64) lo = (void *)state.THREAD_FLD(rsp); # ifndef DARWIN_DONT_PARSE_STACK - hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(rsp)); + hi = GC_FindTopOfStack(state.THREAD_FLD(rsp)); # endif GC_push_one(state.THREAD_FLD(rax)); GC_push_one(state.THREAD_FLD(rbx)); @@ -197,7 +205,7 @@ GC_INNER void GC_push_all_stacks(void) # elif defined(POWERPC) lo = (void *)(state.THREAD_FLD(r1) - PPC_RED_ZONE_SIZE); # ifndef DARWIN_DONT_PARSE_STACK - hi = (ptr_t)FindTopOfStack(state.THREAD_FLD(r1)); + hi = GC_FindTopOfStack(state.THREAD_FLD(r1)); # endif GC_push_one(state.THREAD_FLD(r0)); GC_push_one(state.THREAD_FLD(r2)); @@ -234,7 +242,7 @@ GC_INNER void GC_push_all_stacks(void) # elif defined(ARM32) lo = (void *)state.__sp; # ifndef DARWIN_DONT_PARSE_STACK - hi = (ptr_t)FindTopOfStack(state.__sp); + hi = GC_FindTopOfStack(state.__sp); # endif GC_push_one(state.__r[0]); GC_push_one(state.__r[1]); @@ -258,20 +266,22 @@ GC_INNER void GC_push_all_stacks(void) # error FIXME for non-x86 || ppc || arm architectures # endif } /* thread != me */ + # ifdef DARWIN_DONT_PARSE_STACK + /* p is non-NULL since GC_query_task_threads is FALSE */ hi = (p->flags & MAIN_THREAD) != 0 ? GC_stackbottom : p->stack_end; # endif # ifdef DEBUG_THREADS GC_printf("Darwin: Stack for thread 0x%lx = [%p,%p)\n", (unsigned long) thread, lo, hi); # endif - /* FIXME: use GC_push_all_stack_sections */ - GC_push_all_stack(lo, hi); total_size += hi - lo; /* lo <= hi */ if (GC_query_task_threads) { + GC_push_all_stack(lo, hi); mach_port_deallocate(my_task, thread); break; } + GC_push_all_stack_sections(lo, hi, p->traced_stack_sect); } /* for (p) */ } /* for (i=0; ...) */ diff --git a/include/private/pthread_support.h b/include/private/pthread_support.h index 3c804a52..04a8b55c 100644 --- a/include/private/pthread_support.h +++ b/include/private/pthread_support.h @@ -67,7 +67,7 @@ typedef struct GC_Thread_Rep { /* Treated as a boolean value. If set, */ /* thread will acquire GC lock before */ /* doing any pointer manipulations, and */ - /* has set its sp value. Thus it does */ + /* has set its SP value. Thus it does */ /* not need to be sent a signal to stop */ /* it. */ @@ -80,6 +80,11 @@ typedef struct GC_Thread_Rep { ptr_t stack_end; /* Cold end of the stack (except for */ /* main thread). */ +# if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) + ptr_t topOfStack; /* Result of GC_FindTopOfStack(0); */ + /* valid only if the thread is blocked; */ + /* non-NULL value means already set. */ +# endif # ifdef IA64 ptr_t backing_store_end; ptr_t backing_store_ptr; diff --git a/pthread_support.c b/pthread_support.c index 6c202098..f7da1727 100644 --- a/pthread_support.c +++ b/pthread_support.c @@ -998,6 +998,10 @@ GC_INNER void GC_init_parallel(void) } #endif /* !GC_DARWIN_THREADS && !GC_OPENBSD_THREADS */ +#if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) + GC_INNER ptr_t GC_FindTopOfStack(unsigned long); +#endif + /* Wrapper for functions that are likely to block for an appreciable */ /* length of time. */ @@ -1006,18 +1010,32 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) { struct blocking_data * d = (struct blocking_data *) data; GC_thread me; +# if defined(SPARC) || defined(IA64) + ptr_t stack_ptr = GC_save_regs_in_stack(); +# endif +# if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) + GC_bool topOfStackUnset = FALSE; +# endif DCL_LOCK_STATE; LOCK(); me = GC_lookup_thread(pthread_self()); GC_ASSERT(!(me -> thread_blocked)); # ifdef SPARC - me -> stop_info.stack_ptr = GC_save_regs_in_stack(); + me -> stop_info.stack_ptr = stack_ptr; # else me -> stop_info.stack_ptr = GC_approx_sp(); # endif +# if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) + if (me -> topOfStack == NULL) { + /* GC_do_blocking_inner is not called recursively, */ + /* so topOfStack should be computed now. */ + topOfStackUnset = TRUE; + me -> topOfStack = GC_FindTopOfStack(0); + } +# endif # ifdef IA64 - me -> backing_store_ptr = GC_save_regs_in_stack(); + me -> backing_store_ptr = stack_ptr; # endif me -> thread_blocked = (unsigned char)TRUE; /* Save context here if we want to support precise stack marking */ @@ -1025,6 +1043,10 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) d -> client_data = (d -> fn)(d -> client_data); LOCK(); /* This will block if the world is stopped. */ me -> thread_blocked = FALSE; +# if defined(GC_DARWIN_THREADS) && !defined(DARWIN_DONT_PARSE_STACK) + if (topOfStackUnset) + me -> topOfStack = NULL; /* make topOfStack unset again */ +# endif UNLOCK(); } diff --git a/win32_threads.c b/win32_threads.c index 40f39158..894e10fd 100644 --- a/win32_threads.c +++ b/win32_threads.c @@ -764,13 +764,16 @@ GC_INNER void GC_do_blocking_inner(ptr_t data, void * context) struct blocking_data * d = (struct blocking_data *) data; DWORD t = GetCurrentThreadId(); GC_thread me; +# ifdef IA64 + ptr_t stack_ptr = GC_save_regs_in_stack(); +# endif DCL_LOCK_STATE; LOCK(); me = GC_lookup_thread_inner(t); GC_ASSERT(me -> thread_blocked_sp == NULL); # ifdef IA64 - me -> backing_store_ptr = GC_save_regs_in_stack(); + me -> backing_store_ptr = stack_ptr; # endif me -> thread_blocked_sp = (ptr_t) &d; /* save approx. sp */ /* Save context here if we want to support precise stack marking */ -- 2.40.0