Обратите внимание, что полоса битов доступна не во всех реализациях (в частности, она отсутствует в серии LPC1xxx от NXP).
Официальный способ реализации семафора с использованием LDREX / STREX см. В ARMРазработка примитивов синхронизации Статья .Он использует сборку ARM.
Ниже приведен простой класс, который я создал и который использует встроенные функции компилятора (не проверено!).Название, вероятно, неверно, так как на самом деле работает как мьютексВ нем также отсутствуют инструкции DMB, которые могут быть необходимы.
class Semaphore
{
enum { SemFree, SemTaken };
// semaphore value
int s;
public:
// constructor
Semaphore(): s(SemFree) {};
// try to take the semaphore and return success
// by default block until succeeded
bool take(bool block = true)
{
int oldval;
#if defined(TARGET_LPC1768) // on Cortex-M3 we can use ldrex/strex
do {
// read the semaphore value
oldval = __ldrex(&s);
// loop again if it is locked and we are blocking
// or setting it with strex failed
}
while ( (block && oldval == SemTaken) || __strex(SemTaken, &s) != 0 );
if ( !block ) __clrex(); // clear exclusive lock set by ldrex
#else // on arm7 there's only swp
do {
// swp sets the pointed data to the given value and returns the previous one
oldval = __swp(SemTaken, &s);
// if blocking, loop until the previous value becomes 0
// which would mean we have successfully taken the lock
}
while (block && oldval == SemTaken);
#endif
return oldval == SemFree;
}
// release the semaphore
void release()
{
s = SemFree;
}
};