Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ARM cortex: mutex using bit banding

Given that, on the ARM Cortex M3, I can:

  • atomically read a single bit
  • atomically set a single bit
  • atomically clear a single bit

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.

like image 674
JeffV Avatar asked May 18 '10 13:05

JeffV


1 Answers

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)?

like image 188
Michael Burr Avatar answered Dec 28 '22 06:12

Michael Burr