Let's we have the following simple mutex definition:
class Mutex {
private:
bool lock;
public:
void acquire();
void release();
Mutex() {
lock = 0;
}
};
And the following acquire()
func realization (with using of compare and swap operation):
void Mutex::acquire() {
bool oldValue;
__atomic_load(&lock, &oldValue, 0);
bool newValue = true;
while (!__atomic_compare_exchange_n(&lock, &oldValue, newValue, true, 0, 0)) {
sched_yield();
}
}
In that case, we get the following assembly code:
movzx eax, BYTE PTR [rsp+15]
lock cmpxchg BYTE PTR [rbx], bpl
je .L9
Or in the case of using __atomic_test_and_set
:
void Mutex::acquire() {
while (__atomic_test_and_set(&lock, 0)) {
sched_yield();
}
}
We get the following assembly code:
mov eax, ebp
xchg al, BYTE PTR [rbx]
test al, al
jne .L6
But, what if we don't have hardware support of atomic Test-and-Set and CAS-operations (xchg
and lock cmpxchg
on x86 and their equivalent ones on other architectures)? What solution will compiler use in this case?
P.S. - I used gcc 8.2 to produce assembly code, and here's __atomic_
built-in functions: https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html