summaryrefslogtreecommitdiff
path: root/pthread_support.c
diff options
context:
space:
mode:
authorivmai <ivmai>2010-10-06 22:09:27 +0200
committerIvan Maidanski <ivmai@mail.ru>2011-07-26 19:06:55 +0200
commit24b29a7e89dc3b25b4d6933b7aaf49acf19c71a4 (patch)
tree5c6184fca0e66fa8379c77696667275b66653f63 /pthread_support.c
parent34867e9d2269c71f9753f7ce472904f9c4528a28 (diff)
2010-10-06 Ivan Maidanski <ivmai@mail.ru>
* 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).
Diffstat (limited to 'pthread_support.c')
-rw-r--r--pthread_support.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/pthread_support.c b/pthread_support.c
index 6c20209..f7da172 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();
}