annotate libatomic/libatomic_i.h @ 144:8f4e72ab4e11

fix segmentation fault caused by nothing next cur_op to end
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 21:23:56 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1 /* Copyright (C) 2012-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
2 Contributed by Richard Henderson <rth@redhat.com>.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of the GNU Atomic Library (libatomic).
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 Libatomic is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
7 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
8 the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
9 any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
kono
parents:
diff changeset
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kono
parents:
diff changeset
14 more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 /* This file contains data types and function declarations that are
kono
parents:
diff changeset
26 private to the implementation of libatomic. */
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #ifndef LIBATOMIC_H
kono
parents:
diff changeset
29 #define LIBATOMIC_H 1
kono
parents:
diff changeset
30
kono
parents:
diff changeset
31 #include "auto-config.h"
kono
parents:
diff changeset
32 #include <stdbool.h>
kono
parents:
diff changeset
33 #include <stdint.h>
kono
parents:
diff changeset
34 #include <stddef.h>
kono
parents:
diff changeset
35 #include <limits.h>
kono
parents:
diff changeset
36 #include <string.h>
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 /* Symbol concatenation macros. */
kono
parents:
diff changeset
40 #define C2_(X,Y) X ## Y
kono
parents:
diff changeset
41 #define C2(X,Y) C2_(X,Y)
kono
parents:
diff changeset
42 #define C3_(X,Y,Z) X ## Y ## Z
kono
parents:
diff changeset
43 #define C3(X,Y,Z) C3_(X,Y,Z)
kono
parents:
diff changeset
44 #define C4_(W,X,Y,Z) W ## X ## Y ## Z
kono
parents:
diff changeset
45 #define C4(W,X,Y,Z) C4_(W,X,Y,Z)
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 /* Stringification macros. */
kono
parents:
diff changeset
48 #define S2(X) #X
kono
parents:
diff changeset
49 #define S(X) S2(X)
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 /* All of the primitive types on which we operate. */
kono
parents:
diff changeset
52 typedef unsigned U_1 __attribute__((mode(QI)));
kono
parents:
diff changeset
53 #if HAVE_INT2
kono
parents:
diff changeset
54 typedef unsigned U_2 __attribute__((mode(HI)));
kono
parents:
diff changeset
55 #endif
kono
parents:
diff changeset
56 #if HAVE_INT4
kono
parents:
diff changeset
57 typedef unsigned U_4 __attribute__((mode(SI)));
kono
parents:
diff changeset
58 #endif
kono
parents:
diff changeset
59 #if HAVE_INT8
kono
parents:
diff changeset
60 typedef unsigned U_8 __attribute__((mode(DI)));
kono
parents:
diff changeset
61 #endif
kono
parents:
diff changeset
62 #if HAVE_INT16
kono
parents:
diff changeset
63 typedef unsigned U_16 __attribute__((mode(TI)));
kono
parents:
diff changeset
64 #endif
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 /* The widest type that we support. */
kono
parents:
diff changeset
67 #if HAVE_INT16
kono
parents:
diff changeset
68 # define MAX_SIZE 16
kono
parents:
diff changeset
69 #elif HAVE_INT8
kono
parents:
diff changeset
70 # define MAX_SIZE 8
kono
parents:
diff changeset
71 #elif HAVE_INT4
kono
parents:
diff changeset
72 # define MAX_SIZE 4
kono
parents:
diff changeset
73 #elif HAVE_INT2
kono
parents:
diff changeset
74 # define MAX_SIZE 2
kono
parents:
diff changeset
75 #else
kono
parents:
diff changeset
76 # define MAX_SIZE 1
kono
parents:
diff changeset
77 #endif
kono
parents:
diff changeset
78 typedef C2(U_,MAX_SIZE) U_MAX;
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 /* Provide dummy fallback types so that stuff is syntactically correct
kono
parents:
diff changeset
81 without having to overdo the ifdefs. The code using these should
kono
parents:
diff changeset
82 always be protected with the HAVE_INT{n} macros. */
kono
parents:
diff changeset
83 #if !HAVE_INT2
kono
parents:
diff changeset
84 typedef U_MAX U_2;
kono
parents:
diff changeset
85 #endif
kono
parents:
diff changeset
86 #if !HAVE_INT4
kono
parents:
diff changeset
87 typedef U_MAX U_4;
kono
parents:
diff changeset
88 #endif
kono
parents:
diff changeset
89 #if !HAVE_INT8
kono
parents:
diff changeset
90 typedef U_MAX U_8;
kono
parents:
diff changeset
91 #endif
kono
parents:
diff changeset
92 #if !HAVE_INT16
kono
parents:
diff changeset
93 typedef U_MAX U_16;
kono
parents:
diff changeset
94 #endif
kono
parents:
diff changeset
95
kono
parents:
diff changeset
96 union max_size_u
kono
parents:
diff changeset
97 {
kono
parents:
diff changeset
98 U_1 b[MAX_SIZE];
kono
parents:
diff changeset
99 U_2 i2;
kono
parents:
diff changeset
100 U_4 i4;
kono
parents:
diff changeset
101 U_8 i8;
kono
parents:
diff changeset
102 U_16 i16;
kono
parents:
diff changeset
103 };
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 /* The "word" size of the machine. */
kono
parents:
diff changeset
106 typedef unsigned UWORD __attribute__((mode(word)));
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 /* Macros for handing sub-word sized quantities. */
kono
parents:
diff changeset
109 #define MASK_1 ((UWORD)0xff)
kono
parents:
diff changeset
110 #define MASK_2 ((UWORD)0xffff)
kono
parents:
diff changeset
111 #define MASK_4 ((UWORD)0xffffffff)
kono
parents:
diff changeset
112 #define INVERT_MASK_1 ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 1) * CHAR_BIT))
kono
parents:
diff changeset
113 #define INVERT_MASK_2 ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 2) * CHAR_BIT))
kono
parents:
diff changeset
114 #define INVERT_MASK_4 ((UWORD)WORDS_BIGENDIAN << ((WORDSIZE - 4) * CHAR_BIT))
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 /* Most of the files in this library are compiled multiple times with
kono
parents:
diff changeset
117 N defined to be a power of 2 between 1 and 16. The SIZE macro is
kono
parents:
diff changeset
118 then used to append _N to the symbol being manipulated. */
kono
parents:
diff changeset
119 #define SIZE(X) C3(X,_,N)
kono
parents:
diff changeset
120 #define WSIZE(X) C3(X,_,WORDSIZE)
kono
parents:
diff changeset
121 #define PTR(N,X) ((C2(U_,N) *)X)
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 /* And thus, the type on which this compilation will be operating. */
kono
parents:
diff changeset
124 #define ITYPE SIZE(I)
kono
parents:
diff changeset
125 #define UTYPE SIZE(U)
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 /* Utility macros for GCC attributes. */
kono
parents:
diff changeset
128 #define UNUSED __attribute__((unused))
kono
parents:
diff changeset
129 #ifdef HAVE_ATTRIBUTE_VISIBILITY
kono
parents:
diff changeset
130 # define HIDDEN __attribute__((visibility("hidden")))
kono
parents:
diff changeset
131 #else
kono
parents:
diff changeset
132 # define HIDDEN
kono
parents:
diff changeset
133 #endif
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 /* Occasionally we have to play games with internal and external symbol
kono
parents:
diff changeset
136 names, in order to work around builtin functions of the same name.
kono
parents:
diff changeset
137 This macro sets the external name of the function appropriately. */
kono
parents:
diff changeset
138 #define ASMNAME(X) __asm__(S(C2(__USER_LABEL_PREFIX__,X)))
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 /* Locking for a "small" operation. In the bare-metal single processor
kono
parents:
diff changeset
141 cases this could be implemented by disabling interrupts. Thus the extra
kono
parents:
diff changeset
142 word passed between the two functions, saving the interrupt level.
kono
parents:
diff changeset
143 It is assumed that the object being locked does not cross the locking
kono
parents:
diff changeset
144 granularity.
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 Not actually declared here so that they can be defined static inline
kono
parents:
diff changeset
147 in a target-specfic <host-config.h>.
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 UWORD protect_start (void *ptr);
kono
parents:
diff changeset
150 void protect_end (void *ptr, UWORD);
kono
parents:
diff changeset
151 */
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 /* Locking for a "large' operation. This should always be some sort of
kono
parents:
diff changeset
154 test-and-set operation, as we assume that the interrupt latency would
kono
parents:
diff changeset
155 be unreasonably large. */
kono
parents:
diff changeset
156 void libat_lock_n (void *ptr, size_t n);
kono
parents:
diff changeset
157 void libat_unlock_n (void *ptr, size_t n);
kono
parents:
diff changeset
158
kono
parents:
diff changeset
159 /* We'll need to declare all of the sized functions a few times... */
kono
parents:
diff changeset
160 #define DECLARE_ALL_SIZED(N) DECLARE_ALL_SIZED_(N,C2(U_,N))
kono
parents:
diff changeset
161 #define DECLARE_ALL_SIZED_(N,T) \
kono
parents:
diff changeset
162 DECLARE_1(T, C2(load_,N), (T *mptr, int)); \
kono
parents:
diff changeset
163 DECLARE_1(void, C2(store_,N), (T *mptr, T val, int)); \
kono
parents:
diff changeset
164 DECLARE_1(T, C2(exchange_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
165 DECLARE_1(bool, C2(compare_exchange_,N), (T *mptr, T *, T, int, int)); \
kono
parents:
diff changeset
166 DECLARE_1(bool, C2(test_and_set_,N), (T *mptr, int)); \
kono
parents:
diff changeset
167 DECLARE_1(T, C2(fetch_add_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
168 DECLARE_1(T, C2(fetch_sub_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
169 DECLARE_1(T, C2(fetch_and_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
170 DECLARE_1(T, C2(fetch_xor_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
171 DECLARE_1(T, C2(fetch_or_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
172 DECLARE_1(T, C2(fetch_nand_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
173 DECLARE_1(T, C2(add_fetch_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
174 DECLARE_1(T, C2(sub_fetch_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
175 DECLARE_1(T, C2(and_fetch_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
176 DECLARE_1(T, C2(xor_fetch_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
177 DECLARE_1(T, C2(or_fetch_,N), (T *mptr, T, int)); \
kono
parents:
diff changeset
178 DECLARE_1(T, C2(nand_fetch_,N), (T *mptr, T, int))
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 /* All sized operations are implemented in hidden functions prefixed with
kono
parents:
diff changeset
181 "libat_". These are either renamed or aliased to the expected prefix
kono
parents:
diff changeset
182 of "__atomic". Some amount of renaming is required to avoid hiding or
kono
parents:
diff changeset
183 conflicting with the builtins of the same name, but this additional
kono
parents:
diff changeset
184 use of hidden symbols (where appropriate) avoids unnecessary PLT entries
kono
parents:
diff changeset
185 on relevant targets. */
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 #if IFUNC_ALT
kono
parents:
diff changeset
188 # define MAN(X) ASMNAME(C4(libat_,X,_i,IFUNC_ALT)) HIDDEN
kono
parents:
diff changeset
189 #elif defined(HAVE_ATTRIBUTE_ALIAS)
kono
parents:
diff changeset
190 # define MAN(X) HIDDEN
kono
parents:
diff changeset
191 #else
kono
parents:
diff changeset
192 # define MAN(X) ASMNAME(C2(__atomic_,X))
kono
parents:
diff changeset
193 #endif
kono
parents:
diff changeset
194
kono
parents:
diff changeset
195 #if !defined(N) && HAVE_IFUNC
kono
parents:
diff changeset
196 # define DECLARE_1(RET,NAME,ARGS) \
kono
parents:
diff changeset
197 RET C2(libat_,NAME) ARGS MAN(NAME); \
kono
parents:
diff changeset
198 RET C2(ifunc_,NAME) ARGS ASMNAME(C2(__atomic_,NAME))
kono
parents:
diff changeset
199 #else
kono
parents:
diff changeset
200 # define DECLARE_1(RET,NAME,ARGS) RET C2(libat_,NAME) ARGS MAN(NAME)
kono
parents:
diff changeset
201 #endif
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 /* Prefix to use when calling internal, possibly ifunc'ed functions. */
kono
parents:
diff changeset
204 #if HAVE_IFUNC
kono
parents:
diff changeset
205 # define local_ ifunc_
kono
parents:
diff changeset
206 #else
kono
parents:
diff changeset
207 # define local_ libat_
kono
parents:
diff changeset
208 #endif
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 DECLARE_ALL_SIZED(1);
kono
parents:
diff changeset
211 DECLARE_ALL_SIZED(2);
kono
parents:
diff changeset
212 DECLARE_ALL_SIZED(4);
kono
parents:
diff changeset
213 DECLARE_ALL_SIZED(8);
kono
parents:
diff changeset
214 DECLARE_ALL_SIZED(16);
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 #undef DECLARE_1
kono
parents:
diff changeset
217 #undef DECLARE_ALL_SIZED
kono
parents:
diff changeset
218 #undef DECLARE_ALL_SIZED_
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 /* And the generic sized versions. */
kono
parents:
diff changeset
221 void libat_load (size_t, void *, void *, int) MAN(load);
kono
parents:
diff changeset
222 void libat_store (size_t, void *, void *, int) MAN(store);
kono
parents:
diff changeset
223 void libat_exchange (size_t, void *, void *, void *, int) MAN(exchange);
kono
parents:
diff changeset
224 bool libat_compare_exchange (size_t, void *, void *, void *, int, int)
kono
parents:
diff changeset
225 MAN(compare_exchange);
kono
parents:
diff changeset
226 bool libat_is_lock_free (size_t, void *) MAN(is_lock_free);
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 #undef MAN
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 #include <host-config.h>
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* We don't have IFUNC_NCOND until after host-config.h. */
kono
parents:
diff changeset
233 #if !HAVE_IFUNC
kono
parents:
diff changeset
234 # define IFUNC_NCOND(N) 0
kono
parents:
diff changeset
235 #endif
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 #if IFUNC_ALT
kono
parents:
diff changeset
238 # define EXPORT_ALIAS(X) /* exported symbol in non-alternate file */
kono
parents:
diff changeset
239 #elif defined(N) && IFUNC_NCOND(N)
kono
parents:
diff changeset
240 # if IFUNC_NCOND(N) == 1
kono
parents:
diff changeset
241 # define GEN_SELECTOR(X) \
kono
parents:
diff changeset
242 extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN; \
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
243 static typeof(C2(libat_,X)) * C2(select_,X) (IFUNC_RESOLVER_ARGS) \
111
kono
parents:
diff changeset
244 { \
kono
parents:
diff changeset
245 if (IFUNC_COND_1) \
kono
parents:
diff changeset
246 return C3(libat_,X,_i1); \
kono
parents:
diff changeset
247 return C2(libat_,X); \
kono
parents:
diff changeset
248 }
kono
parents:
diff changeset
249 # elif IFUNC_NCOND(N) == 2
kono
parents:
diff changeset
250 # define GEN_SELECTOR(X) \
kono
parents:
diff changeset
251 extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN; \
kono
parents:
diff changeset
252 extern typeof(C2(libat_,X)) C3(libat_,X,_i2) HIDDEN; \
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
253 static typeof(C2(libat_,X)) * C2(select_,X) (IFUNC_RESOLVER_ARGS) \
111
kono
parents:
diff changeset
254 { \
kono
parents:
diff changeset
255 if (IFUNC_COND_1) \
kono
parents:
diff changeset
256 return C3(libat_,X,_i1); \
kono
parents:
diff changeset
257 if (IFUNC_COND_2) \
kono
parents:
diff changeset
258 return C3(libat_,X,_i2); \
kono
parents:
diff changeset
259 return C2(libat_,X); \
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261 # elif IFUNC_NCOND(N) == 3
kono
parents:
diff changeset
262 # define GEN_SELECTOR(X) \
kono
parents:
diff changeset
263 extern typeof(C2(libat_,X)) C3(libat_,X,_i1) HIDDEN; \
kono
parents:
diff changeset
264 extern typeof(C2(libat_,X)) C3(libat_,X,_i2) HIDDEN; \
kono
parents:
diff changeset
265 extern typeof(C2(libat_,X)) C3(libat_,X,_i3) HIDDEN; \
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
266 static typeof(C2(libat_,X)) * C2(select_,X) (IFUNC_RESOLVER_ARGS) \
111
kono
parents:
diff changeset
267 { \
kono
parents:
diff changeset
268 if (IFUNC_COND_1) \
kono
parents:
diff changeset
269 return C3(libat_,X,_i1); \
kono
parents:
diff changeset
270 if (IFUNC_COND_2) \
kono
parents:
diff changeset
271 return C3(libat_,X,_i2); \
kono
parents:
diff changeset
272 if (IFUNC_COND_3) \
kono
parents:
diff changeset
273 return C3(libat_,X,_i3); \
kono
parents:
diff changeset
274 return C2(libat_,X); \
kono
parents:
diff changeset
275 }
kono
parents:
diff changeset
276 # else
kono
parents:
diff changeset
277 # error "Unsupported number of ifunc alternatives."
kono
parents:
diff changeset
278 # endif
kono
parents:
diff changeset
279 # define EXPORT_ALIAS(X) \
kono
parents:
diff changeset
280 GEN_SELECTOR(X) \
kono
parents:
diff changeset
281 typeof(C2(libat_,X)) C2(ifunc_,X) \
kono
parents:
diff changeset
282 ASMNAME(C2(__atomic_,X)) \
kono
parents:
diff changeset
283 __attribute__((ifunc(S(C2(select_,X)))))
kono
parents:
diff changeset
284 #elif defined(HAVE_ATTRIBUTE_ALIAS)
kono
parents:
diff changeset
285 # define EXPORT_ALIAS(X) \
kono
parents:
diff changeset
286 extern typeof(C2(libat_,X)) C2(export_,X) \
kono
parents:
diff changeset
287 ASMNAME(C2(__atomic_,X)) \
kono
parents:
diff changeset
288 __attribute__((alias(S(C2(libat_,X)))))
kono
parents:
diff changeset
289 #else
kono
parents:
diff changeset
290 # define EXPORT_ALIAS(X) /* original symbol is exported */
kono
parents:
diff changeset
291 #endif
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 #endif /* LIBATOMIC_H */