dint() / eint() / critical_section / mutex

14 Dec 2009 . Edited: 15 Dec 2009

 

Hi all && mbed Team,

  I wrote a class fifo<typename T_ Tsize_>, which has to be synchronised as it 
  could be read/written in the main loop as well as in a e.g. Serial receive 
  interrupt. (I would like to use parts of my code on the mbed as well as the
  host unix/win system).

  How can I disable / enable the interrupts (EINT / DINT) in order to get 
  that stuff done || is there already a class like critical_section?    

  Thanks very much for your help ;)

Cheers,

     Stefan

------------------------------------------------------ 
I thought of something probably looking like this.
(Methods are const and instance variables hence mutable to enable
to lock/unlock in const methods that are using synchronisation.)
What I'm missing is eint() and dint().

namespace sw { namespace sync {

class critical_section
{
public:

#if defined(OS_UNIX)
    critical_section()      { pthread_mutex_init(&_cs, NULL);       }
    ~critical_section()     { pthread_mutex_destroy(&_cs);          }
    void lock() const       { pthread_mutex_lock(&_cs);             }
    void unlock() const     { pthread_mutex_unlock(&_cs);           }
    bool trylock()  const   { return pthread_mutex_trylock(&_cs);   }
#elif defined(OS_WIN)
    critical_section()      { InitializeCriticalSection(&_cs);      }
    ~critical_section()     { DeleteCriticalSection(&_cs);          }
    void lock() const       { EnterCriticalSection(&_cs);           }
    void unlock() const     { LeaveCriticalSection(&_cs);           }
    bool trylock() const    { TryEnterCriticalSection(&_cs);        }
#elif defined(OS_MBED)
    critical_section()      { _count = 0;                           }
    ~critical_section()     { }
    void lock() const       { dint(); _count++;                     }
    void unlock() const     { if(--_count<=0) { _count=0; eint(); } }
    bool trylock() const    { dint(); _count++; return true;        }
#endif

private:

#ifdef OS_WIN
    mutable CRITICAL_SECTION _cs;
#elif defined(OS_UNIX)
    mutable pthread_mutex_t _cs;
#elif defined(OS_MBED)
    mutable short _count;
#endif
};


class cslock
{
public:

    explicit cslock(critical_section & cs) : _locked(false), _cs(cs) { ; }
    ~cslock() { if(_locked) unlock(); }

   void lock()          { if(!_locked) _cs.lock(); _locked=true; }
   void unlock()        { if(_locked) _cs.unlock(); _locked=false; }
   bool trylock()       { if(!_locked) _locked=_cs.trylock(); return _locked; }

private:

    explicit cslock() : _locked(false) { }
    explicit cslock(const cslock& l) : _locked(false) { }

    mutable bool _locked;
    mutable critical_section &_cs; // I edited this after posting, "&" 
};

}}
14 Dec 2009

You can use __disable_irq()/__enable_irq(). Howewer, it might be better to not do something that drastic just for synchronization... try my semaphore class that uses exclusive load instructions.

15 Dec 2009

Thanks very much! I'll try both and give you feedback.