3cb699194702a204b0b13a06a2349edb1658e708
[m6w6/libmemcached] / src / bin / contrib / memaslap / ms_atomic.h
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #ifndef CLIENTS_MS_ATOMIC_H
17 #define CLIENTS_MS_ATOMIC_H
18
19 #if HAVE_C_STDATOMIC
20 # define ATOMIC _Atomic
21 #else
22 # define ATOMIC volatile
23 #endif
24
25 #if defined(__SUNPRO_C)
26 # define _KERNEL
27 # include <atomic.h>
28 # if SIZEOF_SIZE_T == 8
29 # define atomic_add_size(X, Y) atomic_add_64((X), (Y))
30 # define atomic_add_size_nv(X, Y) atomic_add_64((X), (Y))
31 # define atomic_dec_size(X, Y) atomic_add_64((X), (Y))
32 # define atomic_dec_size_nv(X, Y) atomic_add_64((X), (Y))
33 # else
34 # define atomic_add_size(X, Y) atomic_add_32((X), (Y))
35 # define atomic_add_size_nv(X, Y) atomic_add_32((X), (Y))
36 # define atomic_dec_size(X, Y) atomic_add_32((X), (Y))
37 # define atomic_dec_size_nv(X, Y) atomic_add_32((X), (Y))
38 # endif
39 # undef _KERNEL
40 #elif HAVE_GCC_ATOMIC_BUILTINS
41 # define atomic_add_8(X, Y) __sync_fetch_and_add((X), (Y))
42 # define atomic_add_16(X, Y) __sync_fetch_and_add((X), (Y))
43 # define atomic_add_32(X, Y) __sync_fetch_and_add((X), (Y))
44 # define atomic_add_size(X, Y) __sync_fetch_and_add((X), (Y))
45 # define atomic_dec_8(X) __sync_fetch_and_sub((X), 1)
46 # define atomic_dec_16(X) __sync_fetch_and_sub((X), 1)
47 # define atomic_dec_32(X) __sync_fetch_and_sub((X), 1)
48 # define atomic_dec_size(X) __sync_fetch_and_sub((X), 1)
49 /* The same as above, but these return the new value instead of void */
50 # define atomic_add_8_nv(X, Y) __sync_fetch_and_add((X), (Y))
51 # define atomic_add_16_nv(X, Y) __sync_fetch_and_add((X), (Y))
52 # define atomic_add_32_nv(X, Y) __sync_fetch_and_add((X), (Y))
53 # define atomic_add_size_nv(X, Y) __sync_fetch_and_add((X), (Y))
54 # define atomic_dec_8_nv(X) __sync_fetch_and_sub((X), 1)
55 # define atomic_dec_16_nv(X) __sync_fetch_and_sub((X), 1)
56 # define atomic_dec_32_nv(X) __sync_fetch_and_sub((X), 1)
57 # define atomic_dec_size_nv(X) __sync_fetch_and_sub((X), 1)
58 #elif HAVE_C_STDATOMIC
59 # include <stdatomic.h>
60 # define atomic_add_8(X, Y) atomic_fetch_add(X, Y)
61 # define atomic_add_16(X, Y) atomic_fetch_add(X, Y)
62 # define atomic_add_32(X, Y) atomic_fetch_add(X, Y)
63 # define atomic_add_size(X, Y) atomic_fetch_add(X, Y)
64 # define atomic_dec_8(X) atomic_fetch_sub(X, 1)
65 # define atomic_dec_16(X) atomic_fetch_sub(X, 1)
66 # define atomic_dec_32(X) atomic_fetch_sub(X, 1)
67 # define atomic_dec_size(X) atomic_fetch_sub(X, 1)
68 /* The same as above, but these return the new value instead of void */
69 # define ATOMIC_ADD_FETCH_DECL(T) \
70 static inline T atomic_add_fetch_##T(ATOMIC T *ptr, T add) { \
71 T des, cur = atomic_load(ptr); \
72 do { \
73 des = cur + add; \
74 } while (!atomic_compare_exchange_weak(ptr, &cur, des)); \
75 return des; \
76 }
77 # define ATOMIC_SUB_FETCH_DECL(T) \
78 T atomic_sub_fetch_##T(ATOMIC T *ptr) { \
79 T des, cur = atomic_load(ptr); \
80 do { \
81 des = cur - 1; \
82 } while (!atomic_compare_exchange_weak(ptr, &cur, des)); \
83 return des; \
84 }
85 ATOMIC_ADD_FETCH_DECL(uint8_t)
86 # define atomic_add_8_nv(X, Y) atomic_add_fetch_uint8_t(X, Y)
87 ATOMIC_ADD_FETCH_DECL(uint16_t)
88 # define atomic_add_16_nv(X, Y) atomic_add_fetch_uint16_t(X, Y)
89 ATOMIC_ADD_FETCH_DECL(uint32_t)
90 # define atomic_add_32_nv(X, Y) atomic_add_fetch_uint32_t(X, Y)
91 ATOMIC_ADD_FETCH_DECL(size_t)
92 # define atomic_add_size_nv(X, Y) atomic_add_fetch_size_t(X, Y)
93 # define atomic_dec_8_nv(X) atomic_sub_fetch<uint8_t>(X, Y)
94 # define atomic_dec_16_nv(X) atomic_sub_fetch<uint16_t>(X, Y)
95 # define atomic_dec_32_nv(X) atomic_sub_fetch<uint32_t>(X, Y)
96 # define atomic_dec_size_nv(X) atomic_sub_fetch<size_t>(X, Y)
97 #else
98 # warning "Atomic operators not found so memslap will not work correctly"
99 # define atomic_add_8(X, Y) 0
100 # define atomic_add_16(X, Y) 0
101 # define atomic_add_32(X, Y) 0
102 # define atomic_add_size(X, Y) 0
103 # define atomic_dec_8(X) 0
104 # define atomic_dec_16(X) 0
105 # define atomic_dec_32(X) 0
106 # define atomic_dec_size(X) 0
107 /* The same as above, but these return the new value instead of void */
108 # define atomic_add_8_nv(X, Y) 0
109 # define atomic_add_16_nv(X, Y) 0
110 # define atomic_add_32_nv(X, Y) 0
111 # define atomic_add_size_nv(X, Y) 0
112 # define atomic_dec_8_nv(X) 0
113 # define atomic_dec_16_nv(X) 0
114 # define atomic_dec_32_nv(X) 0
115 # define atomic_dec_size_nv(X) 0
116 #endif /* defined(__SUNPRO_C) */
117
118 #endif /* CLIENTS_MS_ATOMIC_H */