+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).
+
2010-10-05 Ivan Maidanski <ivmai@mail.ru>
* finalize.c (GC_check_finalizer_nested): Change return type to
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
# 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 */
}
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). */
# 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));
# 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));
# 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));
# 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]);
# 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; ...) */
/* 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. */
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;
}
#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. */
{
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 */
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();
}
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 */