add archipelago-dbg package
[archipelago] / xseg / xtypes / xatomic.h
1 #ifndef _XATOMIC_H
2 #define _XATOMIC_H
3
4 #include <stdint.h>
5
6 typedef struct xatomic {
7         __uint128_t value;
8 } xatomic;
9
10 #define MAX64   (0xffffffffffffffffUL)
11 #define MAX128  (~(__uint128_t)0)
12 #define Z128    ((__uint128_t)0)
13 #define U128    ((__uint128_t)1)
14
15 #define declare_cas(at, var)                                            \
16         uint64_t var, __xatomic_val_##var;                              \
17         __uint128_t __xatomic_serial_##var;                             \
18         xatomic *__xatomic_##var = (at)
19
20 #define cas_read(var)                                                   \
21         __xatomic_##var##_restart:                                      \
22         __xatomic_serial_##var = ((__xatomic_##var)->value >> 64);      \
23         var = __xatomic_val_##var =                                     \
24                 ((__xatomic_##var)->value & (0xffffffffffffffffUL)
25
26 #define cas_begin(at, var)                              \
27         uint64_t var, __xatomic_val_##var;              \
28         xatomic *__xatomic_##var = (at);                \
29         __xatomic_##var##_restart:                      \
30         var = __xatomic_val_##var = (__xatomic_##var)->value
31
32 #define cas_update(var)                         \
33         __sync_bool_compare_and_swap    (       \
34                 &(__xatomic_##var)->value,      \
35                 __xatomic_val_##var,            \
36                 var                             \
37         )
38
39 #define cas_restart(var)        \
40         goto __xatomic_##var##_restart
41
42
43 static inline uint64_t xatomic_read(xatomic *atomic)
44 {
45         return (uint64_t)atomic->value;
46 }
47
48 static inline void xatomic_write(xatomic *atomic, uint64_t newval)
49 {
50         cas_begin(atomic, val);
51         val = newval;
52         if (!cas_update(val))
53                 cas_restart(val);
54 }
55
56 static inline uint64_t xatomic_inc(xatomic *atomic, uint64_t inc)
57 {
58         uint64_t retval;
59
60         cas_begin(atomic, val);
61         retval = val;
62         val += inc;
63         if (!cas_update(val))
64                 cas_restart(val);
65
66         return retval;
67 }
68
69 static inline uint64_t xatomic_dec(xatomic *atomic, uint64_t dec)
70 {
71         uint64_t retval;
72
73         cas_begin(atomic, val);
74         retval = val;
75         val -= dec;
76         if (!cas_update(val))
77                 cas_restart(val);
78
79         return retval;
80 }
81
82 #endif