MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_atomic.h
1 #ifndef MY_ATOMIC_INCLUDED
2 #define MY_ATOMIC_INCLUDED
3 
4 /* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; version 2 of the License.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
18 
19 /*
20  This header defines five atomic operations:
21 
22  my_atomic_add#(&var, what)
23  'Fetch and Add'
24  add 'what' to *var, and return the old value of *var
25 
26  my_atomic_fas#(&var, what)
27  'Fetch And Store'
28  store 'what' in *var, and return the old value of *var
29 
30  my_atomic_cas#(&var, &old, new)
31  An odd variation of 'Compare And Set/Swap'
32  if *var is equal to *old, then store 'new' in *var, and return TRUE
33  otherwise store *var in *old, and return FALSE
34  Usually, &old should not be accessed if the operation is successful.
35 
36  my_atomic_load#(&var)
37  return *var
38 
39  my_atomic_store#(&var, what)
40  store 'what' in *var
41 
42  '#' is substituted by a size suffix - 8, 16, 32, 64, or ptr
43  (e.g. my_atomic_add8, my_atomic_fas32, my_atomic_casptr).
44 
45  NOTE This operations are not always atomic, so they always must be
46  enclosed in my_atomic_rwlock_rdlock(lock)/my_atomic_rwlock_rdunlock(lock)
47  or my_atomic_rwlock_wrlock(lock)/my_atomic_rwlock_wrunlock(lock).
48  Hint: if a code block makes intensive use of atomic ops, it make sense
49  to take/release rwlock once for the whole block, not for every statement.
50 
51  On architectures where these operations are really atomic, rwlocks will
52  be optimized away.
53  8- and 16-bit atomics aren't implemented for windows (see generic-msvc.h),
54  but can be added, if necessary.
55 */
56 
57 #ifndef my_atomic_rwlock_init
58 
59 #define intptr void *
60 
64 #undef MY_ATOMIC_HAS_8_16
65 
66 #ifndef MY_ATOMIC_MODE_RWLOCKS
67 /*
68  * Attempt to do atomic ops without locks
69  */
70 #include "atomic/nolock.h"
71 #endif
72 
73 #ifndef make_atomic_cas_body
74 /* nolock.h was not able to generate even a CAS function, fall back */
75 #include "atomic/rwlock.h"
76 #endif
77 
78 /* define missing functions by using the already generated ones */
79 #ifndef make_atomic_add_body
80 #define make_atomic_add_body(S) \
81  int ## S tmp=*a; \
82  while (!my_atomic_cas ## S(a, &tmp, tmp+v)) ; \
83  v=tmp;
84 #endif
85 #ifndef make_atomic_fas_body
86 #define make_atomic_fas_body(S) \
87  int ## S tmp=*a; \
88  while (!my_atomic_cas ## S(a, &tmp, v)) ; \
89  v=tmp;
90 #endif
91 #ifndef make_atomic_load_body
92 #define make_atomic_load_body(S) \
93  ret= 0; /* avoid compiler warning */ \
94  (void)(my_atomic_cas ## S(a, &ret, ret));
95 #endif
96 #ifndef make_atomic_store_body
97 #define make_atomic_store_body(S) \
98  (void)(my_atomic_fas ## S (a, v));
99 #endif
100 
101 /*
102  transparent_union doesn't work in g++
103  Bug ?
104 
105  Darwin's gcc doesn't want to put pointers in a transparent_union
106  when built with -arch ppc64. Complains:
107  warning: 'transparent_union' attribute ignored
108 */
109 #if defined(__GNUC__) && !defined(__cplusplus) && \
110  ! (defined(__APPLE__) && (defined(_ARCH_PPC64) ||defined (_ARCH_PPC)))
111 /*
112  we want to be able to use my_atomic_xxx functions with
113  both signed and unsigned integers. But gcc will issue a warning
114  "passing arg N of `my_atomic_XXX' as [un]signed due to prototype"
115  if the signedness of the argument doesn't match the prototype, or
116  "pointer targets in passing argument N of my_atomic_XXX differ in signedness"
117  if int* is used where uint* is expected (or vice versa).
118  Let's shut these warnings up
119 */
120 #define make_transparent_unions(S) \
121  typedef union { \
122  int ## S i; \
123  uint ## S u; \
124  } U_ ## S __attribute__ ((transparent_union)); \
125  typedef union { \
126  int ## S volatile *i; \
127  uint ## S volatile *u; \
128  } Uv_ ## S __attribute__ ((transparent_union));
129 #define uintptr intptr
130 make_transparent_unions(8)
131 make_transparent_unions(16)
132 make_transparent_unions(32)
133 make_transparent_unions(64)
134 make_transparent_unions(ptr)
135 #undef uintptr
136 #undef make_transparent_unions
137 #define a U_a.i
138 #define cmp U_cmp.i
139 #define v U_v.i
140 #define set U_set.i
141 #else
142 #define U_8 int8
143 #define U_16 int16
144 #define U_32 int32
145 #define U_64 int64
146 #define U_ptr intptr
147 #define Uv_8 int8
148 #define Uv_16 int16
149 #define Uv_32 int32
150 #define Uv_64 int64
151 #define Uv_ptr intptr
152 #define U_a volatile *a
153 #define U_cmp *cmp
154 #define U_v v
155 #define U_set set
156 #endif /* __GCC__ transparent_union magic */
157 
158 #define make_atomic_cas(S) \
159 static inline int my_atomic_cas ## S(Uv_ ## S U_a, \
160  Uv_ ## S U_cmp, U_ ## S U_set) \
161 { \
162  int8 ret; \
163  make_atomic_cas_body(S); \
164  return ret; \
165 }
166 
167 #define make_atomic_add(S) \
168 static inline int ## S my_atomic_add ## S( \
169  Uv_ ## S U_a, U_ ## S U_v) \
170 { \
171  make_atomic_add_body(S); \
172  return v; \
173 }
174 
175 #define make_atomic_fas(S) \
176 static inline int ## S my_atomic_fas ## S( \
177  Uv_ ## S U_a, U_ ## S U_v) \
178 { \
179  make_atomic_fas_body(S); \
180  return v; \
181 }
182 
183 #define make_atomic_load(S) \
184 static inline int ## S my_atomic_load ## S(Uv_ ## S U_a) \
185 { \
186  int ## S ret; \
187  make_atomic_load_body(S); \
188  return ret; \
189 }
190 
191 #define make_atomic_store(S) \
192 static inline void my_atomic_store ## S( \
193  Uv_ ## S U_a, U_ ## S U_v) \
194 { \
195  make_atomic_store_body(S); \
196 }
197 
198 #ifdef MY_ATOMIC_HAS_8_16
199 make_atomic_cas(8)
200 make_atomic_cas(16)
201 #endif
202 make_atomic_cas(32)
203 make_atomic_cas(64)
204 make_atomic_cas(ptr)
205 
206 #ifdef MY_ATOMIC_HAS_8_16
207 make_atomic_add(8)
208 make_atomic_add(16)
209 #endif
210 make_atomic_add(32)
211 make_atomic_add(64)
212 
213 #ifdef MY_ATOMIC_HAS_8_16
214 make_atomic_load(8)
215 make_atomic_load(16)
216 #endif
217 make_atomic_load(32)
218 make_atomic_load(64)
219 make_atomic_load(ptr)
220 
221 #ifdef MY_ATOMIC_HAS_8_16
222 make_atomic_fas(8)
223 make_atomic_fas(16)
224 #endif
225 make_atomic_fas(32)
226 make_atomic_fas(64)
227 make_atomic_fas(ptr)
228 
229 #ifdef MY_ATOMIC_HAS_8_16
230 make_atomic_store(8)
231 make_atomic_store(16)
232 #endif
233 make_atomic_store(32)
234 make_atomic_store(64)
235 make_atomic_store(ptr)
236 
237 #ifdef _atomic_h_cleanup_
238 #include _atomic_h_cleanup_
239 #undef _atomic_h_cleanup_
240 #endif
241 
242 #undef U_8
243 #undef U_16
244 #undef U_32
245 #undef U_64
246 #undef U_ptr
247 #undef Uv_8
248 #undef Uv_16
249 #undef Uv_32
250 #undef Uv_64
251 #undef Uv_ptr
252 #undef a
253 #undef cmp
254 #undef v
255 #undef set
256 #undef U_a
257 #undef U_cmp
258 #undef U_v
259 #undef U_set
260 #undef make_atomic_add
261 #undef make_atomic_cas
262 #undef make_atomic_load
263 #undef make_atomic_store
264 #undef make_atomic_fas
265 #undef make_atomic_add_body
266 #undef make_atomic_cas_body
267 #undef make_atomic_load_body
268 #undef make_atomic_store_body
269 #undef make_atomic_fas_body
270 #undef intptr
271 
272 /*
273  the macro below defines (as an expression) the code that
274  will be run in spin-loops. Intel manuals recummend to have PAUSE there.
275  It is expected to be defined in include/atomic/ *.h files
276 */
277 #ifndef LF_BACKOFF
278 #define LF_BACKOFF (1)
279 #endif
280 
281 #define MY_ATOMIC_OK 0
282 #define MY_ATOMIC_NOT_1CPU 1
283 C_MODE_START
284 extern int my_atomic_initialize();
285 C_MODE_END
286 
287 #endif
288 
289 #endif /* MY_ATOMIC_INCLUDED */