6ec990c0551930c8e03e6e7f8cbe454fc9da9080
[m6w6/libmemcached] / src / bin / memaslap / ms_atomic.h
1 /* LibMemcached
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 *
8 * Summary:
9 *
10 */
11
12 #ifndef CLIENTS_MS_ATOMIC_H
13 #define CLIENTS_MS_ATOMIC_H
14
15 #if HAVE_C_STDATOMIC
16 # define ATOMIC _Atomic
17 #else
18 # define ATOMIC volatile
19 #endif
20
21 #if defined(__SUNPRO_C)
22 # define _KERNEL
23 # include <atomic.h>
24 # if SIZEOF_SIZE_T == 8
25 # define atomic_add_size(X, Y) atomic_add_64((X), (Y))
26 # define atomic_add_size_nv(X, Y) atomic_add_64((X), (Y))
27 # define atomic_dec_size(X, Y) atomic_add_64((X), (Y))
28 # define atomic_dec_size_nv(X, Y) atomic_add_64((X), (Y))
29 # else
30 # define atomic_add_size(X, Y) atomic_add_32((X), (Y))
31 # define atomic_add_size_nv(X, Y) atomic_add_32((X), (Y))
32 # define atomic_dec_size(X, Y) atomic_add_32((X), (Y))
33 # define atomic_dec_size_nv(X, Y) atomic_add_32((X), (Y))
34 # endif
35 # undef _KERNEL
36 #elif HAVE_GCC_ATOMIC_BUILTINS
37 # define atomic_add_8(X, Y) __sync_fetch_and_add((X), (Y))
38 # define atomic_add_16(X, Y) __sync_fetch_and_add((X), (Y))
39 # define atomic_add_32(X, Y) __sync_fetch_and_add((X), (Y))
40 # define atomic_add_size(X, Y) __sync_fetch_and_add((X), (Y))
41 # define atomic_dec_8(X) __sync_fetch_and_sub((X), 1)
42 # define atomic_dec_16(X) __sync_fetch_and_sub((X), 1)
43 # define atomic_dec_32(X) __sync_fetch_and_sub((X), 1)
44 # define atomic_dec_size(X) __sync_fetch_and_sub((X), 1)
45 /* The same as above, but these return the new value instead of void */
46 # define atomic_add_8_nv(X, Y) __sync_fetch_and_add((X), (Y))
47 # define atomic_add_16_nv(X, Y) __sync_fetch_and_add((X), (Y))
48 # define atomic_add_32_nv(X, Y) __sync_fetch_and_add((X), (Y))
49 # define atomic_add_size_nv(X, Y) __sync_fetch_and_add((X), (Y))
50 # define atomic_dec_8_nv(X) __sync_fetch_and_sub((X), 1)
51 # define atomic_dec_16_nv(X) __sync_fetch_and_sub((X), 1)
52 # define atomic_dec_32_nv(X) __sync_fetch_and_sub((X), 1)
53 # define atomic_dec_size_nv(X) __sync_fetch_and_sub((X), 1)
54 #elif HAVE_C_STDATOMIC
55 # include <stdatomic.h>
56 # define atomic_add_8(X, Y) atomic_fetch_add(X, Y)
57 # define atomic_add_16(X, Y) atomic_fetch_add(X, Y)
58 # define atomic_add_32(X, Y) atomic_fetch_add(X, Y)
59 # define atomic_add_size(X, Y) atomic_fetch_add(X, Y)
60 # define atomic_dec_8(X) atomic_fetch_sub(X, 1)
61 # define atomic_dec_16(X) atomic_fetch_sub(X, 1)
62 # define atomic_dec_32(X) atomic_fetch_sub(X, 1)
63 # define atomic_dec_size(X) atomic_fetch_sub(X, 1)
64 /* The same as above, but these return the new value instead of void */
65 # define ATOMIC_ADD_FETCH_DECL(T) \
66 static inline T atomic_add_fetch_##T(ATOMIC T *ptr, T add) { \
67 T des, cur = atomic_load(ptr); \
68 do { \
69 des = cur + add; \
70 } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
71 return des; \
72 }
73 # define ATOMIC_SUB_FETCH_DECL(T) \
74 T atomic_sub_fetch_##T(ATOMIC T *ptr) { \
75 T des, cur = atomic_load(ptr); \
76 do { \
77 des = cur - 1; \
78 } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
79 return des; \
80 }
81 ATOMIC_ADD_FETCH_DECL(uint8_t)
82 # define atomic_add_8_nv(X, Y) atomic_add_fetch_uint8_t(X, Y)
83 ATOMIC_ADD_FETCH_DECL(uint16_t)
84 # define atomic_add_16_nv(X, Y) atomic_add_fetch_uint16_t(X, Y)
85 ATOMIC_ADD_FETCH_DECL(uint32_t)
86 # define atomic_add_32_nv(X, Y) atomic_add_fetch_uint32_t(X, Y)
87 ATOMIC_ADD_FETCH_DECL(size_t)
88 # define atomic_add_size_nv(X, Y) atomic_add_fetch_size_t(X, Y)
89 # define atomic_dec_8_nv(X) atomic_sub_fetch<uint8_t>(X, Y)
90 # define atomic_dec_16_nv(X) atomic_sub_fetch<uint16_t>(X, Y)
91 # define atomic_dec_32_nv(X) atomic_sub_fetch<uint32_t>(X, Y)
92 # define atomic_dec_size_nv(X) atomic_sub_fetch<size_t>(X, Y)
93 #else
94 #warning "Atomic operators not found so memslap will not work correctly"
95 # define atomic_add_8(X, Y) 0
96 # define atomic_add_16(X, Y) 0
97 # define atomic_add_32(X, Y) 0
98 # define atomic_add_size(X, Y) 0
99 # define atomic_dec_8(X) 0
100 # define atomic_dec_16(X) 0
101 # define atomic_dec_32(X) 0
102 # define atomic_dec_size(X) 0
103 /* The same as above, but these return the new value instead of void */
104 # define atomic_add_8_nv(X, Y) 0
105 # define atomic_add_16_nv(X, Y) 0
106 # define atomic_add_32_nv(X, Y) 0
107 # define atomic_add_size_nv(X, Y) 0
108 # define atomic_dec_8_nv(X) 0
109 # define atomic_dec_16_nv(X) 0
110 # define atomic_dec_32_nv(X) 0
111 # define atomic_dec_size_nv(X) 0
112 #endif /* defined(__SUNPRO_C) */
113
114 #endif /* CLIENTS_MS_ATOMIC_H */