Use the following commands to compile and link the examples:
$ gcc -std=c17 -pedantic-errors -O0 -g -S mutex.c
$ as --gstabs -o mutex.o mutex.s
$ gcc -o mutex mutex.o -lpthread
This implementation makes use of the C11 Atomic Operations Library.
A mutex is a mutual exclusion lock m
that is accessed only
through two standard atomic operations:
acquire(m)
-- blocks whilem
is locked, then locksm
; andrelease(m)
-- unlocksm
.
A mutex can be used to protect a critical section.
Consider the following line for acquiring the mutex / lock:
#define acquire(m) while (atomic_flag_test_and_set(m))
The atomic_flag_test_and_set
function checks the flag value. If the value is false
, then
it sets the flag to true
(i.e., locks the mutex). In all cases, it returns the previous value
of the flag. This function is guaranteed to be atomic by <stdatomic.h>
.
Therefore, the only way the while
loop can break is if the flag is false
(i.e., the mutex
is unlocked) before the call to atomic_flag_test_and_set
. Otherwise, the code will spin / busy
wait until it encounters the mutex in an unlocked state. Atomicity is important here because we do
not want another thread or process to acquire the lock in-between the comparison and the
potential setting of the new flag value as this would mean the mutex was acquired by some other
thread during that time. This atomic operation is an example of a
compare-and-swap (CAS).
Pthreads comes with its own mutex implementation. You can drop it in to this example using the following:
pthread_mutex_t mut;
#define acquire(m) pthread_mutex_lock(m)
#define release(m) pthread_mutex_unlock(m)
See pthread_mutex_lock(3p)
for more details.
Our implementation is not limited to Pthreads. It can be used to synchronize between processes
so long as the mut_t
(our atomic_flag
) is at an address that maps to a shared memory object.
Hello. Thx for this code. I would like to know if this is a real mutex or if it is a spinlock ? If it is a mutex so, what is a spinlock ? If it is a spinlock so, what is a mutex ?