]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/sh/lowlevellock.h
* Fix SH specific compiler warnings which are for integer-pointer
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / sh / lowlevellock.h
1 /* Copyright (C) 2003-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifndef _LOWLEVELLOCK_H
19 #define _LOWLEVELLOCK_H 1
20
21 #ifndef __ASSEMBLER__
22 #include <time.h>
23 #include <sys/param.h>
24 #include <bits/pthreadtypes.h>
25 #include <kernel-features.h>
26 #endif
27
28 #define SYS_futex 240
29 #define FUTEX_WAIT 0
30 #define FUTEX_WAKE 1
31 #define FUTEX_CMP_REQUEUE 4
32 #define FUTEX_WAKE_OP 5
33 #define FUTEX_LOCK_PI 6
34 #define FUTEX_UNLOCK_PI 7
35 #define FUTEX_TRYLOCK_PI 8
36 #define FUTEX_WAIT_BITSET 9
37 #define FUTEX_WAKE_BITSET 10
38 #define FUTEX_PRIVATE_FLAG 128
39 #define FUTEX_CLOCK_REALTIME 256
40
41 #define FUTEX_BITSET_MATCH_ANY 0xffffffff
42
43 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
44
45 /* Values for 'private' parameter of locking macros. Yes, the
46 definition seems to be backwards. But it is not. The bit will be
47 reversed before passing to the system call. */
48 #define LLL_PRIVATE 0
49 #define LLL_SHARED FUTEX_PRIVATE_FLAG
50
51
52 #if IS_IN (libc) || IS_IN (rtld)
53 /* In libc.so or ld.so all futexes are private. */
54 # ifdef __ASSUME_PRIVATE_FUTEX
55 # define __lll_private_flag(fl, private) \
56 ((fl) | FUTEX_PRIVATE_FLAG)
57 # else
58 # define __lll_private_flag(fl, private) \
59 ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
60 # endif
61 #else
62 # ifdef __ASSUME_PRIVATE_FUTEX
63 # define __lll_private_flag(fl, private) \
64 (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
65 # else
66 # define __lll_private_flag(fl, private) \
67 (__builtin_constant_p (private) \
68 ? ((private) == 0 \
69 ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
70 : (fl)) \
71 : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
72 & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
73 # endif
74 #endif
75
76 #ifndef __ASSEMBLER__
77
78 /* Initializer for compatibility lock. */
79 #define LLL_LOCK_INITIALIZER (0)
80 #define LLL_LOCK_INITIALIZER_LOCKED (1)
81 #define LLL_LOCK_INITIALIZER_WAITERS (2)
82
83 extern int __lll_lock_wait_private (int val, int *__futex)
84 attribute_hidden;
85 extern int __lll_lock_wait (int val, int *__futex, int private)
86 attribute_hidden;
87 extern int __lll_timedlock_wait (int val, int *__futex,
88 const struct timespec *abstime, int private)
89 attribute_hidden;
90 extern int __lll_robust_lock_wait (int val, int *__futex, int private)
91 attribute_hidden;
92 extern int __lll_robust_timedlock_wait (int val, int *__futex,
93 const struct timespec *abstime,
94 int private)
95 attribute_hidden;
96 extern int __lll_unlock_wake_private (int *__futex) attribute_hidden;
97 extern int __lll_unlock_wake (int *__futex, int private) attribute_hidden;
98
99 #define lll_trylock(futex) \
100 ({ unsigned char __result; \
101 __asm __volatile ("\
102 .align 2\n\
103 mova 1f,r0\n\
104 nop\n\
105 mov r15,r1\n\
106 mov #-8,r15\n\
107 0: mov.l @%1,r2\n\
108 cmp/eq r2,%3\n\
109 bf 1f\n\
110 mov.l %2,@%1\n\
111 1: mov r1,r15\n\
112 mov #-1,%0\n\
113 negc %0,%0"\
114 : "=r" (__result) \
115 : "r" (&(futex)), \
116 "r" (LLL_LOCK_INITIALIZER_LOCKED), \
117 "r" (LLL_LOCK_INITIALIZER) \
118 : "r0", "r1", "r2", "t", "memory"); \
119 __result; })
120
121 #define lll_cond_trylock(futex) \
122 ({ unsigned char __result; \
123 __asm __volatile ("\
124 .align 2\n\
125 mova 1f,r0\n\
126 nop\n\
127 mov r15,r1\n\
128 mov #-8,r15\n\
129 0: mov.l @%1,r2\n\
130 cmp/eq r2,%3\n\
131 bf 1f\n\
132 mov.l %2,@%1\n\
133 1: mov r1,r15\n\
134 mov #-1,%0\n\
135 negc %0,%0"\
136 : "=r" (__result) \
137 : "r" (&(futex)), \
138 "r" (LLL_LOCK_INITIALIZER_WAITERS), \
139 "r" (LLL_LOCK_INITIALIZER) \
140 : "r0", "r1", "r2", "t", "memory"); \
141 __result; })
142
143 #define lll_lock(futex, private) \
144 (void) ({ int __result, *__futex = &(futex); \
145 __asm __volatile ("\
146 .align 2\n\
147 mova 1f,r0\n\
148 nop\n\
149 mov r15,r1\n\
150 mov #-8,r15\n\
151 0: mov.l @%2,%0\n\
152 tst %0,%0\n\
153 bf 1f\n\
154 mov.l %1,@%2\n\
155 1: mov r1,r15"\
156 : "=&r" (__result) : "r" (1), "r" (__futex) \
157 : "r0", "r1", "t", "memory"); \
158 if (__result) \
159 { \
160 if (__builtin_constant_p (private) \
161 && (private) == LLL_PRIVATE) \
162 __lll_lock_wait_private (__result, __futex); \
163 else \
164 __lll_lock_wait (__result, __futex, (private)); \
165 } \
166 })
167
168 #define lll_robust_lock(futex, id, private) \
169 ({ int __result, *__futex = &(futex); \
170 __asm __volatile ("\
171 .align 2\n\
172 mova 1f,r0\n\
173 nop\n\
174 mov r15,r1\n\
175 mov #-8,r15\n\
176 0: mov.l @%2,%0\n\
177 tst %0,%0\n\
178 bf 1f\n\
179 mov.l %1,@%2\n\
180 1: mov r1,r15"\
181 : "=&r" (__result) : "r" (id), "r" (__futex) \
182 : "r0", "r1", "t", "memory"); \
183 if (__result) \
184 __result = __lll_robust_lock_wait (__result, __futex, private); \
185 __result; })
186
187 /* Special version of lll_mutex_lock which causes the unlock function to
188 always wakeup waiters. */
189 #define lll_cond_lock(futex, private) \
190 (void) ({ int __result, *__futex = &(futex); \
191 __asm __volatile ("\
192 .align 2\n\
193 mova 1f,r0\n\
194 nop\n\
195 mov r15,r1\n\
196 mov #-8,r15\n\
197 0: mov.l @%2,%0\n\
198 tst %0,%0\n\
199 bf 1f\n\
200 mov.l %1,@%2\n\
201 1: mov r1,r15"\
202 : "=&r" (__result) : "r" (2), "r" (__futex) \
203 : "r0", "r1", "t", "memory"); \
204 if (__result) \
205 __lll_lock_wait (__result, __futex, private); })
206
207 #define lll_robust_cond_lock(futex, id, private) \
208 ({ int __result, *__futex = &(futex); \
209 __asm __volatile ("\
210 .align 2\n\
211 mova 1f,r0\n\
212 nop\n\
213 mov r15,r1\n\
214 mov #-8,r15\n\
215 0: mov.l @%2,%0\n\
216 tst %0,%0\n\
217 bf 1f\n\
218 mov.l %1,@%2\n\
219 1: mov r1,r15"\
220 : "=&r" (__result) : "r" (id | FUTEX_WAITERS), "r" (__futex) \
221 : "r0", "r1", "t", "memory"); \
222 if (__result) \
223 __result = __lll_robust_lock_wait (__result, __futex, private); \
224 __result; })
225
226 #define lll_timedlock(futex, timeout, private) \
227 ({ int __result, *__futex = &(futex); \
228 __asm __volatile ("\
229 .align 2\n\
230 mova 1f,r0\n\
231 nop\n\
232 mov r15,r1\n\
233 mov #-8,r15\n\
234 0: mov.l @%2,%0\n\
235 tst %0,%0\n\
236 bf 1f\n\
237 mov.l %1,@%2\n\
238 1: mov r1,r15"\
239 : "=&r" (__result) : "r" (1), "r" (__futex) \
240 : "r0", "r1", "t", "memory"); \
241 if (__result) \
242 __result = __lll_timedlock_wait (__result, __futex, timeout, private); \
243 __result; })
244
245 #define lll_robust_timedlock(futex, timeout, id, private) \
246 ({ int __result, *__futex = &(futex); \
247 __asm __volatile ("\
248 .align 2\n\
249 mova 1f,r0\n\
250 nop\n\
251 mov r15,r1\n\
252 mov #-8,r15\n\
253 0: mov.l @%2,%0\n\
254 tst %0,%0\n\
255 bf 1f\n\
256 mov.l %1,@%2\n\
257 1: mov r1,r15"\
258 : "=&r" (__result) : "r" (id), "r" (__futex) \
259 : "r0", "r1", "t", "memory"); \
260 if (__result) \
261 __result = __lll_robust_timedlock_wait (__result, __futex, \
262 timeout, private); \
263 __result; })
264
265 #define lll_unlock(futex, private) \
266 (void) ({ int __result, *__futex = &(futex); \
267 __asm __volatile ("\
268 .align 2\n\
269 mova 1f,r0\n\
270 mov r15,r1\n\
271 mov #-6,r15\n\
272 0: mov.l @%1,%0\n\
273 add #-1,%0\n\
274 mov.l %0,@%1\n\
275 1: mov r1,r15"\
276 : "=&r" (__result) : "r" (__futex) \
277 : "r0", "r1", "memory"); \
278 if (__result) \
279 { \
280 if (__builtin_constant_p (private) \
281 && (private) == LLL_PRIVATE) \
282 __lll_unlock_wake_private (__futex); \
283 else \
284 __lll_unlock_wake (__futex, (private)); \
285 } \
286 })
287
288 #define lll_robust_unlock(futex, private) \
289 (void) ({ int __result, *__futex = &(futex); \
290 __asm __volatile ("\
291 .align 2\n\
292 mova 1f,r0\n\
293 mov r15,r1\n\
294 mov #-6,r15\n\
295 0: mov.l @%1,%0\n\
296 and %2,%0\n\
297 mov.l %0,@%1\n\
298 1: mov r1,r15"\
299 : "=&r" (__result) : "r" (__futex), "r" (FUTEX_WAITERS) \
300 : "r0", "r1", "memory"); \
301 if (__result) \
302 __lll_unlock_wake (__futex, private); })
303
304 # ifdef NEED_SYSCALL_INST_PAD
305 # define SYSCALL_WITH_INST_PAD "\
306 trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0"
307 # else
308 # define SYSCALL_WITH_INST_PAD "\
309 trapa #0x14"
310 # endif
311
312 #define lll_futex_wait(futex, val, private) \
313 lll_futex_timed_wait (futex, val, NULL, private)
314
315
316 #define lll_futex_timed_wait(futex, val, timeout, private) \
317 ({ \
318 int __status; \
319 register unsigned long __r3 asm ("r3") = SYS_futex; \
320 register unsigned long __r4 asm ("r4") = (unsigned long) (futex); \
321 register unsigned long __r5 asm ("r5") \
322 = __lll_private_flag (FUTEX_WAIT, private); \
323 register unsigned long __r6 asm ("r6") = (unsigned long) (val); \
324 register unsigned long __r7 asm ("r7") = (unsigned long) (timeout); \
325 __asm __volatile (SYSCALL_WITH_INST_PAD \
326 : "=z" (__status) \
327 : "r" (__r3), "r" (__r4), "r" (__r5), \
328 "r" (__r6), "r" (__r7) \
329 : "memory", "t"); \
330 __status; \
331 })
332
333
334 #define lll_futex_wake(futex, nr, private) \
335 do { \
336 int __ignore; \
337 register unsigned long __r3 asm ("r3") = SYS_futex; \
338 register unsigned long __r4 asm ("r4") = (unsigned long) (futex); \
339 register unsigned long __r5 asm ("r5") \
340 = __lll_private_flag (FUTEX_WAKE, private); \
341 register unsigned long __r6 asm ("r6") = (unsigned long) (nr); \
342 register unsigned long __r7 asm ("r7") = 0; \
343 __asm __volatile (SYSCALL_WITH_INST_PAD \
344 : "=z" (__ignore) \
345 : "r" (__r3), "r" (__r4), "r" (__r5), \
346 "r" (__r6), "r" (__r7) \
347 : "memory", "t"); \
348 } while (0)
349
350
351 #define lll_islocked(futex) \
352 (futex != LLL_LOCK_INITIALIZER)
353
354 /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
355 wakeup when the clone terminates. The memory location contains the
356 thread ID while the clone is running and is reset to zero
357 afterwards. */
358
359 #define lll_wait_tid(tid) \
360 do { \
361 __typeof (tid) *__tid = &(tid); \
362 while (*__tid != 0) \
363 lll_futex_wait (__tid, *__tid, LLL_SHARED); \
364 } while (0)
365
366 extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
367 attribute_hidden;
368 #define lll_timedwait_tid(tid, abstime) \
369 ({ \
370 int __result = 0; \
371 if (tid != 0) \
372 { \
373 if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \
374 __result = EINVAL; \
375 else \
376 __result = __lll_timedwait_tid (&tid, abstime); \
377 } \
378 __result; })
379
380 #endif /* !__ASSEMBLER__ */
381
382 #endif /* lowlevellock.h */