summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2013-07-20 15:01:01 +0200
committerIvan Maidanski <ivmai@mail.ru>2013-07-20 15:01:01 +0200
commit2425f945784b3c6f625e1bc85c1312cd5ae866d1 (patch)
tree8158ef84f885c05d1da89695a63574abcd125dd0
parent14042f61bf4021abd27f9d630d487bdb203db5b5 (diff)
Fix 'stack section' pointer passed to push_all_stack_sections (Pthreads)
* pthread_stop_world.c (GC_push_all_stacks): Use traced_stack_sect->prev instead of traced_stack_sect if saved_stack_ptr (of traced_stack_sect) is the same as stop_info.stack_ptr of the examined thread (thus preventing assertion violation in GC_push_all_stack_sections invoked during incremental collection).
-rw-r--r--pthread_stop_world.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
index e633b0f..3e62929 100644
--- a/pthread_stop_world.c
+++ b/pthread_stop_world.c
@@ -343,6 +343,7 @@ GC_INNER void GC_push_all_stacks(void)
ptr_t lo, hi;
/* On IA64, we also need to scan the register backing store. */
IF_IA64(ptr_t bs_lo; ptr_t bs_hi;)
+ struct GC_traced_stack_sect_s *traced_stack_sect;
pthread_t self = pthread_self();
word total_size = 0;
@@ -355,6 +356,7 @@ GC_INNER void GC_push_all_stacks(void)
for (p = GC_threads[i]; p != 0; p = p -> next) {
if (p -> flags & FINISHED) continue;
++nthreads;
+ traced_stack_sect = p -> traced_stack_sect;
if (THREAD_EQUAL(p -> id, self)) {
GC_ASSERT(!p->thread_blocked);
# ifdef SPARC
@@ -367,6 +369,13 @@ GC_INNER void GC_push_all_stacks(void)
} else {
lo = p -> stop_info.stack_ptr;
IF_IA64(bs_hi = p -> backing_store_ptr;)
+ if (traced_stack_sect != NULL
+ && traced_stack_sect->saved_stack_ptr == lo) {
+ /* If the thread has never been stopped since the recent */
+ /* GC_call_with_gc_active invocation then skip the top */
+ /* "stack section" as stack_ptr already points to. */
+ traced_stack_sect = traced_stack_sect->prev;
+ }
}
if ((p -> flags & MAIN_THREAD) == 0) {
hi = p -> stack_end;
@@ -381,7 +390,7 @@ GC_INNER void GC_push_all_stacks(void)
(void *)p->id, lo, hi);
# endif
if (0 == lo) ABORT("GC_push_all_stacks: sp not set!");
- GC_push_all_stack_sections(lo, hi, p -> traced_stack_sect);
+ GC_push_all_stack_sections(lo, hi, traced_stack_sect);
# ifdef STACK_GROWS_UP
total_size += lo - hi;
# else
@@ -402,7 +411,7 @@ GC_INNER void GC_push_all_stacks(void)
/* entries, and hence overflow the mark stack, which is bad. */
GC_push_all_register_sections(bs_lo, bs_hi,
THREAD_EQUAL(p -> id, self),
- p -> traced_stack_sect);
+ traced_stack_sect);
total_size += bs_hi - bs_lo; /* bs_lo <= bs_hi */
# endif
}