1+ #include <stdatomic.h>
12#include <stddef.h>
23
34#include "mcslock.h"
@@ -14,34 +15,37 @@ enum { MCS_PROCEED = 0, MCS_WAIT = 1 };
1415#define spin_wait () ((void) 0)
1516#endif
1617
17- static inline void wait_until_equal_u8 (uint8_t * loc , uint8_t val , int mm )
18+ static inline void wait_until_equal_u8 (_Atomic uint8_t * loc ,
19+ uint8_t val ,
20+ memory_order mm )
1821{
19- while (__atomic_load_n (loc , mm ) != val )
22+ while (atomic_load_explicit (loc , mm ) != val )
2023 spin_wait ();
2124}
2225
2326void mcslock_init (mcslock_t * lock )
2427{
25- * lock = NULL ;
28+ atomic_init ( lock , NULL ) ;
2629}
2730
2831void mcslock_acquire (mcslock_t * lock , mcsnode_t * node )
2932{
30- node -> next = NULL ;
33+ atomic_init ( & node -> next , NULL ) ;
3134 /* A0: Read and write lock, synchronized with A0/A1 */
32- mcsnode_t * prev = __atomic_exchange_n (lock , node , __ATOMIC_ACQ_REL );
35+ mcsnode_t * prev =
36+ atomic_exchange_explicit (lock , node , memory_order_acq_rel );
3337 if (LIKELY (!prev )) /* Lock uncontended, the lock is acquired */
3438 return ;
3539 /* Otherwise, the lock is owned by another thread, waiting for its turn */
3640
37- node -> wait = MCS_WAIT ;
41+ atomic_store_explicit ( & node -> wait , MCS_WAIT , memory_order_release ) ;
3842 /* B0: Write next, synchronized with B1/B2 */
39- __atomic_store_n (& prev -> next , node , __ATOMIC_RELEASE );
43+ atomic_store_explicit (& prev -> next , node , memory_order_release );
4044
4145 /* Waiting for the previous thread to signal using the assigned node
4246 * C0: Read wait, synchronized with C1
4347 */
44- wait_until_equal_u8 (& node -> wait , MCS_PROCEED , __ATOMIC_ACQUIRE );
48+ wait_until_equal_u8 (& node -> wait , MCS_PROCEED , memory_order_acquire );
4549}
4650
4751void mcslock_release (mcslock_t * lock , mcsnode_t * node )
@@ -50,26 +54,28 @@ void mcslock_release(mcslock_t *lock, mcsnode_t *node)
5054
5155 /* Check if any waiting thread exists */
5256 /* B1: Read next, synchronized with B0 */
53- if ((next = __atomic_load_n (& node -> next , __ATOMIC_ACQUIRE )) == NULL ) {
57+ if ((next = atomic_load_explicit (& node -> next , memory_order_acquire )) ==
58+ NULL ) {
5459 /* No waiting threads detected, attempt lock release */
5560 /* Use temporary variable as it might be overwritten */
5661 mcsnode_t * tmp = node ;
5762
5863 /* A1: write lock, synchronize with A0 */
59- if (__atomic_compare_exchange_n ( lock , & tmp , NULL , 0 , __ATOMIC_RELEASE ,
60- __ATOMIC_RELAXED )) {
64+ if (atomic_compare_exchange_strong_explicit (
65+ lock , & tmp , NULL , memory_order_release , memory_order_relaxed )) {
6166 /* No waiting threads yet, lock released successfully */
6267 return ;
6368 }
6469 /* Otherwise, at least one waiting thread exists */
6570
6671 /* Wait for the first waiting thread to link its node with ours */
6772 /* B2: Read next, synchronized with B0 */
68- while ((next = __atomic_load_n (& node -> next , __ATOMIC_ACQUIRE )) == NULL )
73+ while ((next = atomic_load_explicit (& node -> next ,
74+ memory_order_acquire )) == NULL )
6975 spin_wait ();
7076 }
7177
7278 /* Signal the first waiting thread */
7379 /* C1: Write wait, synchronized with C0 */
74- __atomic_store_n (& next -> wait , MCS_PROCEED , __ATOMIC_RELEASE );
80+ atomic_store_explicit (& next -> wait , MCS_PROCEED , memory_order_release );
7581}
0 commit comments