Skip to content

Commit

Permalink
[project @ 2005-11-25 14:03:00 by simonmar]
Browse files Browse the repository at this point in the history
Modify some assertions that were occasionally incorrect
  • Loading branch information
simonmar committed Nov 25, 2005
1 parent 9512557 commit c282a81
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 16 deletions.
13 changes: 6 additions & 7 deletions ghc/rts/Capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ giveCapabilityToTask (Capability *cap, Task *task)
{
ASSERT_LOCK_HELD(&cap->lock);
ASSERT(task->cap == cap);
// We are not modifying task->cap, so we do not need to take task->lock.
IF_DEBUG(scheduler,
sched_belch("passing capability %d to %s %p",
cap->no, task->tso ? "bound task" : "worker",
Expand Down Expand Up @@ -248,7 +247,7 @@ releaseCapability_ (Capability* cap)

task = cap->running_task;

ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task);

cap->running_task = NULL;

Expand Down Expand Up @@ -416,7 +415,7 @@ waitForReturnCapability (Capability **pCap,

}

ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);

IF_DEBUG(scheduler,
sched_belch("returning; got capability %d", cap->no));
Expand All @@ -435,15 +434,14 @@ yieldCapability (Capability** pCap, Task *task)
{
Capability *cap = *pCap;

// The fast path; no locking
if ( cap->returning_tasks_hd == NULL && anyWorkForMe(cap,task) )
return;
// The fast path has no locking, if we don't enter this while loop

while ( cap->returning_tasks_hd != NULL || !anyWorkForMe(cap,task) ) {
IF_DEBUG(scheduler, sched_belch("giving up capability %d", cap->no));

// We must now release the capability and wait to be woken up
// again.
task->wakeup = rtsFalse;
releaseCapabilityAndQueueWorker(cap);

for (;;) {
Expand All @@ -457,6 +455,7 @@ yieldCapability (Capability** pCap, Task *task)
IF_DEBUG(scheduler, sched_belch("woken up on capability %d", cap->no));
ACQUIRE_LOCK(&cap->lock);
if (cap->running_task != NULL) {
IF_DEBUG(scheduler, sched_belch("capability %d is owned by another task", cap->no));
RELEASE_LOCK(&cap->lock);
continue;
}
Expand Down Expand Up @@ -484,7 +483,7 @@ yieldCapability (Capability** pCap, Task *task)

*pCap = cap;

ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);

return;
}
Expand Down
16 changes: 12 additions & 4 deletions ghc/rts/Capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,20 @@ struct Capability_ {
#endif

// These properties should be true when a Task is holding a Capability
#define ASSERT_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(cap->run_queue_hd == END_TSO_QUEUE ? \
cap->run_queue_tl == END_TSO_QUEUE : 1); \
ASSERT(myTask() == task); \
ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task)

// Sometimes a Task holds a Capability, but the Task is not associated
// with that Capability (ie. task->cap != cap). This happens when
// (a) a Task holds multiple Capabilities, and (b) when the current
// Task is bound, its thread has just blocked, and it may have been
// moved to another Capability.
#define ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task) \
ASSERT(cap->run_queue_hd == END_TSO_QUEUE ? \
cap->run_queue_tl == END_TSO_QUEUE : 1); \
ASSERT(myTask() == task); \
ASSERT_TASK_ID(task);

// Converts a *StgRegTable into a *Capability.
Expand Down
2 changes: 1 addition & 1 deletion ghc/rts/RtsAPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ rts_unlock (Capability *cap)
Task *task;

task = cap->running_task;
ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);

// slightly delicate ordering of operations below, pay attention!

Expand Down
9 changes: 5 additions & 4 deletions ghc/rts/Schedule.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ schedule (Capability *initialCapability, Task *task)
// thread for a bit, even if there are others banging at the
// door.
first = rtsFalse;
ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);
} else {
// Yield the capability to higher-priority tasks if necessary.
yieldCapability(&cap, task);
Expand Down Expand Up @@ -639,7 +639,7 @@ schedule (Capability *initialCapability, Task *task)
}
#endif

ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);

// ----------------------------------------------------------------------

Expand Down Expand Up @@ -681,7 +681,7 @@ schedule (Capability *initialCapability, Task *task)

case ThreadFinished:
if (scheduleHandleThreadFinished(cap, task, t)) return cap;
ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);
break;

default:
Expand Down Expand Up @@ -795,6 +795,7 @@ schedulePushWork(Capability *cap USED_WHEN_SMP,
prev->link = t;
prev = t;
} else {
IF_DEBUG(scheduler, sched_belch("pushing thread %d to capability %d", t->id, free_caps[i]->no));
appendToRunQueue(free_caps[i],t);
if (t->bound) { t->bound->cap = free_caps[i]; }
i++;
Expand Down Expand Up @@ -2599,7 +2600,7 @@ scheduleWaitThread (StgTSO* tso, /*[out]*/HaskellObj* ret, Capability *cap)
cap = schedule(cap,task);

ASSERT(task->stat != NoStatus);
ASSERT_CAPABILITY_INVARIANTS(cap,task);
ASSERT_FULL_CAPABILITY_INVARIANTS(cap,task);

IF_DEBUG(scheduler, sched_belch("bound thread (%d) finished", task->tso->id));
return cap;
Expand Down

0 comments on commit c282a81

Please sign in to comment.