Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Implementing atomic operations

2010-03-11
2013-03-12
  • Pascal Dupuis
    Pascal Dupuis
    2010-03-11

    Hello,
    I would like to protect some critical section of code as follows:

    uint8_t counter1;
    uint16_t counter_freq;
    volatile __bit counter1_lock;
    void freq_meas(void)
    {
      static uint8_t counter2 = 0;
      if (try_lock(counter1_lock)) {
        /* we got the lock */
        if (counter2 > 0) {
          counter1 += counter2;
          counter2 = 0;
        }
        counter1++;
        counter_needs_updating = true;  
        counter1_lock = false;
      } else { /* someone else is busy with counter1 */
        counter2++;
      }
    }
    freq_meas is an interrupt routine associated with an interrupt source. I would like to implement try_lock as
    try_lock(bit_variable, SUCCESS_CLAUSE_BODY,  FAILURE_CLAUSE_BODY) as
    JBC bit_variable,  SUCCESS_CLAUSE_label
    FAILURE_CLAUSE;
    JMP __end_try_lock;
    SUCCESS_CLAUSE_label: SUCCESS_CLAUSE;
    __end_try_lock:

    The code test and set variable_bit to zero. If it was one, it execute SUCCESS_CLAUSE; else if execute FAILURE_CLAUSE.  The bit has to be tested only once.

    Which construct can I use ?

    Regards

    CdM

     
  • > Which construct can I use ?

    You probably have missed section 3.10.3 "Semaphore locking (mcs51/ds390)".

    If this does not apply probably 3.10.1 "Critical Functions and Critical Statements" or 3.10.2 will do.

     
  • I should have added: thanks for asking such a detailed question:)

    And: this is not compatible with the compiler option "-no-peep".

     
  • Pascal Dupuis
    Pascal Dupuis
    2010-03-12

    Hello,
    the 'trick' is indeed to factor the code as
      if (var_lock) {
        var_lock = false; /* we got the lock */
       /* code if we get the lock */
      var_lock = true;
    } else {
      /* code if we dont't have the lock
    }
    The test and set bit to zero have to be contiguous.

    I tried the following construct:
    #define try_lock(x) (x?(x=false,true):false)
    It does work, but the intermediate result is stored in the local context and further tested. This implies thus two tests and some jumps.
    So the best approach in an interrupt context is the first form; i.e. explicit test inside an 'if' clause

    Regards

    CdM