b5de5c7384ba4a210fc61eaa4c712d464341f5d4
[c11tester.git] / include / impatomic.c
1
2 #include <stdint.h>
3 #include "impatomic.h"
4
5
6 #if defined(__GNUC__)
7 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 0)
8 #define USE_SYNC
9 #endif
10 #endif
11
12 bool atomic_flag_test_and_set_explicit
13 ( volatile atomic_flag* __a__, memory_order __x__ )
14 {
15 #ifdef USE_SYNC
16     if ( __x__ >= memory_order_acq_rel )
17         __sync_synchronize();
18     return __sync_lock_test_and_set( &(__a__->__f__), 1 );
19 #else
20     bool result = __a__->__f__;
21     __a__->__f__ = true;
22     return result;
23 #endif
24 }
25
26 bool atomic_flag_test_and_set( volatile atomic_flag* __a__ )
27 { return atomic_flag_test_and_set_explicit( __a__, memory_order_seq_cst ); }
28
29 void atomic_flag_clear_explicit
30 ( volatile atomic_flag* __a__, memory_order __x__ )
31 {
32 #ifdef USE_SYNC
33     __sync_lock_release( &(__a__->__f__) );
34     if ( __x__ >= memory_order_acq_rel )
35         __sync_synchronize();
36 #else
37     __a__->__f__ = false;
38 #endif
39 }
40
41 void atomic_flag_clear( volatile atomic_flag* __a__ )
42 { atomic_flag_clear_explicit( __a__, memory_order_seq_cst ); }
43
44 void atomic_flag_fence( const volatile atomic_flag* __a__, memory_order __x__ )
45 {
46 #ifdef USE_SYNC
47     __sync_synchronize();
48 #endif
49 }
50
51 void __atomic_flag_wait__( volatile atomic_flag* __a__ )
52 { while ( atomic_flag_test_and_set( __a__ ) ); }
53
54 void __atomic_flag_wait_explicit__( volatile atomic_flag* __a__,
55                                     memory_order __x__ )
56 { while ( atomic_flag_test_and_set_explicit( __a__, __x__ ) ); }
57
58 #define LOGSIZE 4
59
60 static atomic_flag volatile __atomic_flag_anon_table__[ 1 << LOGSIZE ] =
61 {
62     ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
63     ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
64     ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
65     ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT, ATOMIC_FLAG_INIT,
66 };
67
68 volatile atomic_flag* __atomic_flag_for_address__( const volatile void* __z__ )
69 {
70     uintptr_t __u__ = (uintptr_t)__z__;
71     __u__ += (__u__ >> 2) + (__u__ << 4);
72     __u__ += (__u__ >> 7) + (__u__ << 5);
73     __u__ += (__u__ >> 17) + (__u__ << 13);
74     if ( sizeof(uintptr_t) > 4 ) __u__ += (__u__ >> 31);
75     __u__ &= ~((~(uintptr_t)0) << LOGSIZE);
76     return __atomic_flag_anon_table__ + __u__;
77 }
78