[Tinyos-devel] SimpleArbiterP bug
Philip Levis
pal at cs.stanford.edu
Wed Oct 15 10:29:23 PDT 2008
I think this is a bug in SimpleArbiterP, but wanted to check with
everyone to make sure. In particular, whether there are existing
systems which depend on the current behavior, such that fixing it
would break them.
A bit of background: arbiters (power locks) are built around
SimpleArbiterP. SimpleArbiterP uses a queue interface, and the
implementation of that queue interface controls its locking policy
(e.g., First-come, first-served vs. round-robin).
The test case is as follows. I'm using indentation to show the call
graph. E.g., 2a is called on 2's stack frame.
1. Client A requests and acquires power lock P
2. Client B requests power lock P
2a. P signals to Client A that the lock has been requested
2aa. Client A releases P
2ab. Client A re-requests P
In this case, I think that P should grant to B; 2aa and 2ab are a
yield from A. When B releases the lock, A will re-acquire it. However,
the request code looks like this (immediateRequest is similar):
async command error_t Resource.request[uint8_t id]() {
signal ResourceRequested.requested[resId]();
atomic {
if(state == RES_CONTROLLED) {
state = RES_GRANTING;
reqResId = id;
}
else return call Queue.enqueue(id);
}
signal ResourceDefaultOwner.requested();
return SUCCESS;
}
Because requested() is signaled before the caller's request is put on
the queue, then in the case above, this is what happens:
1. Client A requests and acquires power lock P
2. Client B requests power lock P
2a. P signals to Client A that the lock has been requested
2aa. Client A releases P
2ab. Client A re-requests P
2aba. P puts A at head of queue
2abb. P posts a task to grant A the lock
2b. P puts B on queue
....
3. A re-acquires lock, while B is waiting on queue
I think the code should be this:
async command error_t Resource.request[uint8_t id]() {
bool getsNow = TRUE;
atomic {
if(state == RES_CONTROLLED) {
state = RES_GRANTING;
reqResId = id;
getsNow = FALSE;
}
}
if (getsNow == FALSE) {
error_t rval = call Queue.enqueue(id);
signal ResourceRequested.requested[resId]();
return rval;
}
else {
signal ResourceDefaultOwner.requested();
return SUCCESS;
}
}
Thoughts?
Phil
More information about the Tinyos-devel
mailing list