Commit b7d6e20c authored by Simon Marlow's avatar Simon Marlow Committed by Ben Gamari

Fix an assertion that could randomly fail

Summary:
ASSERT_THREADED_CAPABILITY_INVARIANTS was testing properties of the
returning_tasks queue, but that requires cap->lock to access safely.
This assertion would randomly fail if stressed enough.

Instead I've removed it from the catch-all
ASSERT_PARTIAL_CAPABILITIY_INVARIANTS and made it a separate assertion
only called under cap->lock.

Test Plan:
```
cd testsuite/tests/concurrent/should_run
make TEST=setnumcapabilities001 WAY=threaded1 EXTRA_HC_OPTS=-with-rtsopts=-DS CLEANUP=0
while true; do ./setnumcapabilities001.run/setnumcapabilities001 4 9 2000 || break; done
```

Reviewers: niteria, bgamari, ezyang, austin, erikd

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D2440

GHC Trac Issues: #10860

(cherry picked from commit ce13a9a9)
parent 5230fa04
......@@ -206,6 +206,7 @@ newReturningTask (Capability *cap, Task *task)
}
cap->returning_tasks_tl = task;
cap->n_returning_tasks++;
ASSERT_RETURNING_TASKS(cap,task);
}
STATIC_INLINE Task *
......@@ -221,6 +222,7 @@ popReturningTask (Capability *cap)
}
task->next = NULL;
cap->n_returning_tasks--;
ASSERT_RETURNING_TASKS(cap,task);
return task;
}
#endif
......@@ -470,6 +472,7 @@ releaseCapability_ (Capability* cap,
task = cap->running_task;
ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task);
ASSERT_RETURNING_TASKS(cap,task);
cap->running_task = NULL;
......
......@@ -166,13 +166,15 @@ struct Capability_ {
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()
#if defined(THREADED_RTS)
#define ASSERT_THREADED_CAPABILITY_INVARIANTS(cap,task) \
#define ASSERT_RETURNING_TASKS(cap,task) \
ASSERT(cap->returning_tasks_hd == NULL ? \
cap->returning_tasks_tl == NULL && cap->n_returning_tasks == 0 \
: 1);
#else
#define ASSERT_THREADED_CAPABILITY_INVARIANTS(cap,task) /* nothing */
#define ASSERT_RETURNING_TASKS(cap,task) /* nothing */
#endif
// Sometimes a Task holds a Capability, but the Task is not associated
......@@ -185,7 +187,6 @@ struct Capability_ {
cap->run_queue_tl == END_TSO_QUEUE && cap->n_run_queue == 0 \
: 1); \
ASSERT(cap->suspended_ccalls == NULL ? cap->n_suspended_ccalls == 0 : 1); \
ASSERT_THREADED_CAPABILITY_INVARIANTS(cap,task); \
ASSERT(myTask() == task); \
ASSERT_TASK_ID(task);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment