summaryrefslogtreecommitdiff
path: root/rts/Threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Threads.c')
-rw-r--r--rts/Threads.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/rts/Threads.c b/rts/Threads.c
index 2bdcea1c00..8334c5a5ac 100644
--- a/rts/Threads.c
+++ b/rts/Threads.c
@@ -85,7 +85,8 @@ createThread(Capability *cap, W_ size)
SET_HDR(stack, &stg_STACK_info, cap->r.rCCCS);
stack->stack_size = stack_size - sizeofW(StgStack);
stack->sp = stack->stack + stack->stack_size;
- stack->dirty = 1;
+ stack->dirty = STACK_DIRTY;
+ stack->marking = 0;
tso = (StgTSO *)allocate(cap, sizeofW(StgTSO));
TICK_ALLOC_TSO();
@@ -611,6 +612,7 @@ threadStackOverflow (Capability *cap, StgTSO *tso)
TICK_ALLOC_STACK(chunk_size);
new_stack->dirty = 0; // begin clean, we'll mark it dirty below
+ new_stack->marking = 0;
new_stack->stack_size = chunk_size - sizeofW(StgStack);
new_stack->sp = new_stack->stack + new_stack->stack_size;
@@ -721,9 +723,17 @@ threadStackUnderflow (Capability *cap, StgTSO *tso)
barf("threadStackUnderflow: not enough space for return values");
}
- new_stack->sp -= retvals;
+ IF_NONMOVING_WRITE_BARRIER_ENABLED {
+ // ensure that values that we copy into the new stack are marked
+ // for the nonmoving collector. Note that these values won't
+ // necessarily form a full closure so we need to handle them
+ // specially.
+ for (unsigned int i = 0; i < retvals; i++) {
+ updateRemembSetPushClosure(cap, (StgClosure *) old_stack->sp[i]);
+ }
+ }
- memcpy(/* dest */ new_stack->sp,
+ memcpy(/* dest */ new_stack->sp - retvals,
/* src */ old_stack->sp,
/* size */ retvals * sizeof(W_));
}
@@ -735,8 +745,12 @@ threadStackUnderflow (Capability *cap, StgTSO *tso)
// restore the stack parameters, and update tot_stack_size
tso->tot_stack_size -= old_stack->stack_size;
- // we're about to run it, better mark it dirty
+ // we're about to run it, better mark it dirty.
+ //
+ // N.B. the nonmoving collector may mark the stack, meaning that sp must
+ // point at a valid stack frame.
dirty_STACK(cap, new_stack);
+ new_stack->sp -= retvals;
return retvals;
}
@@ -768,7 +782,7 @@ loop:
if (q == (StgMVarTSOQueue*)&stg_END_TSO_QUEUE_closure) {
/* No further takes, the MVar is now full. */
if (info == &stg_MVAR_CLEAN_info) {
- dirty_MVAR(&cap->r, (StgClosure*)mvar);
+ dirty_MVAR(&cap->r, (StgClosure*)mvar, mvar->value);
}
mvar->value = value;
@@ -804,7 +818,7 @@ loop:
// indicate that the MVar operation has now completed.
tso->_link = (StgTSO*)&stg_END_TSO_QUEUE_closure;
- if (stack->dirty == 0) {
+ if ((stack->dirty & STACK_DIRTY) == 0) {
dirty_STACK(cap, stack);
}