summaryrefslogtreecommitdiff
path: root/rts/Capability.h
diff options
context:
space:
mode:
Diffstat (limited to 'rts/Capability.h')
-rw-r--r--rts/Capability.h28
1 files changed, 17 insertions, 11 deletions
diff --git a/rts/Capability.h b/rts/Capability.h
index 87ec53801a..8c5b1e814e 100644
--- a/rts/Capability.h
+++ b/rts/Capability.h
@@ -182,10 +182,10 @@ struct Capability_ {
#endif
// These properties should be true when a Task is holding a Capability
-#define ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task) \
- ASSERT(cap->running_task != NULL && cap->running_task == task); \
- ASSERT(task->cap == cap); \
- ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task)
+#define ASSERT_FULL_CAPABILITY_INVARIANTS(_cap,_task) \
+ ASSERT(_cap->running_task != NULL && _cap->running_task == _task); \
+ ASSERT(_task->cap == _cap); \
+ ASSERT_PARTIAL_CAPABILITY_INVARIANTS(_cap,_task)
// This assert requires cap->lock to be held, so it can't be part of
// ASSERT_PARTIAL_CAPABILITY_INVARIANTS()
@@ -419,14 +419,16 @@ recordMutableCap (const StgClosure *p, Capability *cap, uint32_t gen)
// ASSERT(cap->running_task == myTask());
// NO: assertion is violated by performPendingThrowTos()
bd = cap->mut_lists[gen];
- if (bd->free >= bd->start + BLOCK_SIZE_W) {
+ if (RELAXED_LOAD(&bd->free) >= bd->start + BLOCK_SIZE_W) {
bdescr *new_bd;
new_bd = allocBlockOnNode_lock(cap->node);
new_bd->link = bd;
+ new_bd->free = new_bd->start;
bd = new_bd;
cap->mut_lists[gen] = bd;
}
- *bd->free++ = (StgWord)p;
+ RELAXED_STORE(bd->free, (StgWord) p);
+ NONATOMIC_ADD(&bd->free, 1);
}
EXTERN_INLINE void
@@ -460,29 +462,33 @@ stopCapability (Capability *cap)
// It may not work - the thread might be updating HpLim itself
// at the same time - so we also have the context_switch/interrupted
// flags as a sticky way to tell the thread to stop.
- cap->r.rHpLim = NULL;
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->r.rHpLim, "stopCapability");
+ SEQ_CST_STORE(&cap->r.rHpLim, NULL);
}
INLINE_HEADER void
interruptCapability (Capability *cap)
{
stopCapability(cap);
- cap->interrupt = 1;
+ SEQ_CST_STORE(&cap->interrupt, true);
}
INLINE_HEADER void
contextSwitchCapability (Capability *cap)
{
stopCapability(cap);
- cap->context_switch = 1;
+ SEQ_CST_STORE(&cap->context_switch, true);
}
#if defined(THREADED_RTS)
INLINE_HEADER bool emptyInbox(Capability *cap)
{
- return (cap->inbox == (Message*)END_TSO_QUEUE &&
- cap->putMVars == NULL);
+ // This may race with writes to putMVars and inbox but this harmless for the
+ // intended uses of this function.
+ TSAN_ANNOTATE_BENIGN_RACE(&cap->putMVars, "emptyInbox(cap->putMVars)");
+ return (RELAXED_LOAD(&cap->inbox) == (Message*)END_TSO_QUEUE &&
+ RELAXED_LOAD(&cap->putMVars) == NULL);
}
#endif