]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h
Use glibc_likely instead __builtin_expect.
[thirdparty/glibc.git] / nptl / sysdeps / unix / sysv / linux / powerpc / lowlevellock.h
CommitLineData
d4697bc9 1/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
f3c13160
RM
2 This file is part of the GNU C Library.
3 Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
f3c13160
RM
18
19#ifndef _LOWLEVELLOCK_H
20#define _LOWLEVELLOCK_H 1
21
22#include <time.h>
23#include <sys/param.h>
24#include <bits/pthreadtypes.h>
b1aea098 25#include <atomic.h>
f8de5057 26#include <kernel-features.h>
b1aea098 27
ce6e047f
UD
28#ifndef __NR_futex
29# define __NR_futex 221
30#endif
f3c13160
RM
31#define FUTEX_WAIT 0
32#define FUTEX_WAKE 1
b8ba4a27 33#define FUTEX_REQUEUE 3
75fccede 34#define FUTEX_CMP_REQUEUE 4
b9b8cf03
UD
35#define FUTEX_WAKE_OP 5
36#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
d5ba53f9
UD
37#define FUTEX_LOCK_PI 6
38#define FUTEX_UNLOCK_PI 7
39#define FUTEX_TRYLOCK_PI 8
da5ac135
UD
40#define FUTEX_WAIT_BITSET 9
41#define FUTEX_WAKE_BITSET 10
8313cb99
SP
42#define FUTEX_WAIT_REQUEUE_PI 11
43#define FUTEX_CMP_REQUEUE_PI 12
e59660bc 44#define FUTEX_PRIVATE_FLAG 128
7dd650d7
UD
45#define FUTEX_CLOCK_REALTIME 256
46
47#define FUTEX_BITSET_MATCH_ANY 0xffffffff
e59660bc 48
eb7721f2
UD
49/* Values for 'private' parameter of locking macros. Yes, the
50 definition seems to be backwards. But it is not. The bit will be
51 reversed before passing to the system call. */
52#define LLL_PRIVATE 0
53#define LLL_SHARED FUTEX_PRIVATE_FLAG
54
b5f13526
UD
55#if !defined NOT_IN_libc || defined IS_IN_rtld
56/* In libc.so or ld.so all futexes are private. */
57# ifdef __ASSUME_PRIVATE_FUTEX
58# define __lll_private_flag(fl, private) \
59 ((fl) | FUTEX_PRIVATE_FLAG)
60# else
61# define __lll_private_flag(fl, private) \
62 ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
63# endif
64#else
65# ifdef __ASSUME_PRIVATE_FUTEX
66# define __lll_private_flag(fl, private) \
67 (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
68# else
69# define __lll_private_flag(fl, private) \
70 (__builtin_constant_p (private) \
71 ? ((private) == 0 \
72 ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
73 : (fl)) \
74 : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
75 & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
da5ac135 76# endif
b5f13526 77#endif
f3c13160 78
eb7721f2 79#define lll_futex_wait(futexp, val, private) \
b5f13526 80 lll_futex_timed_wait (futexp, val, NULL, private)
f3c13160 81
eb7721f2 82#define lll_futex_timed_wait(futexp, val, timespec, private) \
bd0fa4ce
UD
83 ({ \
84 INTERNAL_SYSCALL_DECL (__err); \
85 long int __ret; \
86 \
b5f13526
UD
87 __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
88 __lll_private_flag (FUTEX_WAIT, private), \
89 (val), (timespec)); \
9bdabb94 90 INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \
f3c13160
RM
91 })
92
8f861542
SP
93#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
94 ({ \
95 INTERNAL_SYSCALL_DECL (__err); \
96 long int __ret; \
97 int __op = FUTEX_WAIT_BITSET | clockbit; \
98 \
99 __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
100 __lll_private_flag (__op, private), \
101 (val), (timespec), NULL /* Unused. */, \
102 FUTEX_BITSET_MATCH_ANY); \
103 INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \
104 })
105
eb7721f2 106#define lll_futex_wake(futexp, nr, private) \
bd0fa4ce
UD
107 ({ \
108 INTERNAL_SYSCALL_DECL (__err); \
109 long int __ret; \
110 \
b5f13526
UD
111 __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
112 __lll_private_flag (FUTEX_WAKE, private), \
113 (nr), 0); \
9bdabb94 114 INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \
f3c13160
RM
115 })
116
e51deae7 117#define lll_robust_dead(futexv, private) \
f1740bc4
UD
118 do \
119 { \
120 INTERNAL_SYSCALL_DECL (__err); \
121 int *__futexp = &(futexv); \
122 \
123 atomic_or (__futexp, FUTEX_OWNER_DIED); \
e51deae7
UD
124 INTERNAL_SYSCALL (futex, __err, 4, __futexp, \
125 __lll_private_flag (FUTEX_WAKE, private), 1, 0); \
f1740bc4
UD
126 } \
127 while (0)
128
75fccede 129/* Returns non-zero if error happened, zero if success. */
5bd8a249 130#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
b8ba4a27
UD
131 ({ \
132 INTERNAL_SYSCALL_DECL (__err); \
133 long int __ret; \
134 \
5bd8a249
UD
135 __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
136 __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
137 (nr_wake), (nr_move), (mutex), (val)); \
75fccede 138 INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
b8ba4a27
UD
139 })
140
b9b8cf03 141/* Returns non-zero if error happened, zero if success. */
eb7721f2 142#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
b9b8cf03
UD
143 ({ \
144 INTERNAL_SYSCALL_DECL (__err); \
145 long int __ret; \
146 \
b5f13526
UD
147 __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
148 __lll_private_flag (FUTEX_WAKE_OP, private), \
149 (nr_wake), (nr_wake2), (futexp2), \
150 FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
b9b8cf03
UD
151 INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
152 })
da5ac135 153
8313cb99
SP
154/* Priority Inheritance support. */
155#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
156 lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
157
158#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
159 mutex, private) \
160 ({ \
161 INTERNAL_SYSCALL_DECL (__err); \
162 long int __ret; \
163 int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
164 \
165 __ret = INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
166 __lll_private_flag (__op, private), \
167 (val), (timespec), mutex); \
168 INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \
169 })
170
171#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
172 ({ \
173 INTERNAL_SYSCALL_DECL (__err); \
174 long int __ret; \
175 \
176 __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
177 __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
178 (nr_wake), (nr_move), (mutex), (val)); \
179 INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
180 })
181
da5ac135 182
f3c13160 183#ifdef UP
bd0fa4ce
UD
184# define __lll_acq_instr ""
185# define __lll_rel_instr ""
f3c13160 186#else
bd0fa4ce 187# define __lll_acq_instr "isync"
f9d35bb9
RM
188# ifdef _ARCH_PWR4
189/*
190 * Newer powerpc64 processors support the new "light weight" sync (lwsync)
191 * So if the build is using -mcpu=[power4,power5,power5+,970] we can
192 * safely use lwsync.
193 */
194# define __lll_rel_instr "lwsync"
195# else
196/*
197 * Older powerpc32 processors don't support the new "light weight"
198 * sync (lwsync). So the only safe option is to use normal sync
199 * for all powerpc32 applications.
200 */
201# define __lll_rel_instr "sync"
202# endif
f3c13160
RM
203#endif
204
f1740bc4
UD
205/* Set *futex to ID if it is 0, atomically. Returns the old value */
206#define __lll_robust_trylock(futex, id) \
bd0fa4ce 207 ({ int __val; \
fa6e3bc3 208 __asm __volatile ("1: lwarx %0,0,%2" MUTEX_HINT_ACQ "\n" \
bd0fa4ce
UD
209 " cmpwi 0,%0,0\n" \
210 " bne 2f\n" \
211 " stwcx. %3,0,%2\n" \
212 " bne- 1b\n" \
213 "2: " __lll_acq_instr \
214 : "=&r" (__val), "=m" (*futex) \
f1740bc4 215 : "r" (futex), "r" (id), "m" (*futex) \
bd0fa4ce
UD
216 : "cr0", "memory"); \
217 __val; \
f3c13160
RM
218 })
219
e51deae7 220#define lll_robust_trylock(lock, id) __lll_robust_trylock (&(lock), id)
f1740bc4
UD
221
222/* Set *futex to 1 if it is 0, atomically. Returns the old value */
223#define __lll_trylock(futex) __lll_robust_trylock (futex, 1)
224
e51deae7 225#define lll_trylock(lock) __lll_trylock (&(lock))
043ad426 226
2c0b891a 227/* Set *futex to 2 if it is 0, atomically. Returns the old value */
f1740bc4
UD
228#define __lll_cond_trylock(futex) __lll_robust_trylock (futex, 2)
229
e51deae7 230#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock))
2c0b891a 231
043ad426 232
e51deae7
UD
233extern void __lll_lock_wait_private (int *futex) attribute_hidden;
234extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
235extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
f3c13160 236
e51deae7 237#define lll_lock(lock, private) \
bd0fa4ce
UD
238 (void) ({ \
239 int *__futex = &(lock); \
39358e8b
UD
240 if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\
241 0) != 0) \
e51deae7
UD
242 { \
243 if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
244 __lll_lock_wait_private (__futex); \
245 else \
246 __lll_lock_wait (__futex, private); \
247 } \
f3c13160
RM
248 })
249
e51deae7 250#define lll_robust_lock(lock, id, private) \
f1740bc4
UD
251 ({ \
252 int *__futex = &(lock); \
253 int __val = 0; \
254 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
255 0), 0)) \
e51deae7 256 __val = __lll_robust_lock_wait (__futex, private); \
f1740bc4
UD
257 __val; \
258 })
259
e51deae7 260#define lll_cond_lock(lock, private) \
b8ba4a27
UD
261 (void) ({ \
262 int *__futex = &(lock); \
39358e8b
UD
263 if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 2, 0),\
264 0) != 0) \
e51deae7 265 __lll_lock_wait (__futex, private); \
b8ba4a27
UD
266 })
267
e51deae7 268#define lll_robust_cond_lock(lock, id, private) \
f1740bc4
UD
269 ({ \
270 int *__futex = &(lock); \
271 int __val = 0; \
272 int __id = id | FUTEX_WAITERS; \
273 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, __id,\
274 0), 0)) \
e51deae7 275 __val = __lll_robust_lock_wait (__futex, private); \
f1740bc4
UD
276 __val; \
277 })
278
279
f3c13160 280extern int __lll_timedlock_wait
e51deae7 281 (int *futex, const struct timespec *, int private) attribute_hidden;
f1740bc4 282extern int __lll_robust_timedlock_wait
e51deae7 283 (int *futex, const struct timespec *, int private) attribute_hidden;
f3c13160 284
e51deae7 285#define lll_timedlock(lock, abstime, private) \
39358e8b 286 ({ \
bc1989aa 287 int *__futex = &(lock); \
39358e8b
UD
288 int __val = 0; \
289 if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\
290 0) != 0) \
e51deae7 291 __val = __lll_timedlock_wait (__futex, abstime, private); \
39358e8b 292 __val; \
f3c13160
RM
293 })
294
e51deae7 295#define lll_robust_timedlock(lock, abstime, id, private) \
f1740bc4
UD
296 ({ \
297 int *__futex = &(lock); \
298 int __val = 0; \
299 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
300 0), 0)) \
e51deae7 301 __val = __lll_robust_timedlock_wait (__futex, abstime, private); \
f1740bc4
UD
302 __val; \
303 })
304
e51deae7 305#define lll_unlock(lock, private) \
94659495 306 ((void) ({ \
bd0fa4ce 307 int *__futex = &(lock); \
7158eae4 308 int __val = atomic_exchange_rel (__futex, 0); \
a1ffb40e 309 if (__glibc_unlikely (__val > 1)) \
e51deae7 310 lll_futex_wake (__futex, 1, private); \
94659495 311 }))
f3c13160 312
e51deae7 313#define lll_robust_unlock(lock, private) \
f1740bc4
UD
314 ((void) ({ \
315 int *__futex = &(lock); \
316 int __val = atomic_exchange_rel (__futex, 0); \
a1ffb40e 317 if (__glibc_unlikely (__val & FUTEX_WAITERS)) \
e51deae7 318 lll_futex_wake (__futex, 1, private); \
b8ba4a27
UD
319 }))
320
e51deae7 321#define lll_islocked(futex) \
f3c13160
RM
322 (futex != 0)
323
324
f3c13160
RM
325/* Initializers for lock. */
326#define LLL_LOCK_INITIALIZER (0)
327#define LLL_LOCK_INITIALIZER_LOCKED (1)
328
f3c13160
RM
329/* The states of a lock are:
330 0 - untaken
331 1 - taken by one user
332 >1 - taken by more users */
333
adcdc775 334/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
f3c13160
RM
335 wakeup when the clone terminates. The memory location contains the
336 thread ID while the clone is running and is reset to zero
337 afterwards. */
bd0fa4ce
UD
338#define lll_wait_tid(tid) \
339 do { \
340 __typeof (tid) __tid; \
341 while ((__tid = (tid)) != 0) \
eb7721f2 342 lll_futex_wait (&(tid), __tid, LLL_SHARED); \
f3c13160
RM
343 } while (0)
344
345extern int __lll_timedwait_tid (int *, const struct timespec *)
346 attribute_hidden;
347
bd0fa4ce
UD
348#define lll_timedwait_tid(tid, abstime) \
349 ({ \
350 int __res = 0; \
351 if ((tid) != 0) \
352 __res = __lll_timedwait_tid (&(tid), (abstime)); \
353 __res; \
f3c13160
RM
354 })
355
f3c13160 356#endif /* lowlevellock.h */