Given that, on the ARM Cortex M3, I can:
How can I combine these for a mutex style set of operations:
try lock
take lock
release lock
It seems that try_lock
or take_lock
would require two operations that would not be atomic.
Do I need more control to accomplish this? Disable global interrupts would do it but it seems there should be a more surgical approach.
Your rwl_TryLock()
doesn't necessarily return a failure if the lock is already held when it's called (your compiler should be giving at least a warning about a code path that has no return value). Try the following:
int rwl_TryLock(volatile uint32_t *lock, int who){
Var_SetBit_BB((uint32_t)lock, who);
if(*lock == (1<<who)){ // check that we have exclusive access
// got the lock!
return 1;
}
// do not have the lock
Var_ResetBit_BB((uint32_t)lock, who); // clear the lock flag
return 0;
}
Note that the above will not work for recursively claiming the same lock (ie., if the task specified by who == 1
already has the lock and tries to claim it again, the code above will not work correctly), but that was true of your original as well.
Also, interrupts can be disabled/enabled on the Cortex M3 pretty quickly (it's a simple update to an NVIC register). Are you sure your system can't live with an additional few cycles of interrupt latency to keep the code for handling the lock data structures simple (which generally means easier to make correct)?