Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / ia64 / lowlevellock.h
blob19a06a258fa100ee04dc315d4f06e3d1dab05917
1 /* Copyright (C) 2003-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #ifndef _LOWLEVELLOCK_H
20 #define _LOWLEVELLOCK_H 1
22 #include <time.h>
23 #include <sys/param.h>
24 #include <bits/pthreadtypes.h>
25 #include <ia64intrin.h>
26 #include <atomic.h>
27 #include <kernel-features.h>
29 #define __NR_futex 1230
30 #define FUTEX_WAIT 0
31 #define FUTEX_WAKE 1
32 #define FUTEX_REQUEUE 3
33 #define FUTEX_CMP_REQUEUE 4
34 #define FUTEX_WAKE_OP 5
35 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
36 #define FUTEX_LOCK_PI 6
37 #define FUTEX_UNLOCK_PI 7
38 #define FUTEX_TRYLOCK_PI 8
39 #define FUTEX_WAIT_BITSET 9
40 #define FUTEX_WAKE_BITSET 10
41 #define FUTEX_WAIT_REQUEUE_PI 11
42 #define FUTEX_CMP_REQUEUE_PI 12
43 #define FUTEX_PRIVATE_FLAG 128
44 #define FUTEX_CLOCK_REALTIME 256
46 #define FUTEX_BITSET_MATCH_ANY 0xffffffff
48 /* Values for 'private' parameter of locking macros. Yes, the
49 definition seems to be backwards. But it is not. The bit will be
50 reversed before passing to the system call. */
51 #define LLL_PRIVATE 0
52 #define LLL_SHARED FUTEX_PRIVATE_FLAG
55 #if IS_IN (libc) || 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))))
76 # endif
77 #endif
80 /* Delay in spinlock loop. */
81 #define BUSY_WAIT_NOP asm ("hint @pause")
83 #define lll_futex_wait(futex, val, private) \
84 lll_futex_timed_wait (futex, val, NULL, private)
86 #define lll_futex_timed_wait(ftx, val, timespec, private) \
87 ({ \
88 DO_INLINE_SYSCALL(futex, 4, (long) (ftx), \
89 __lll_private_flag (FUTEX_WAIT, private), \
90 (int) (val), (long) (timespec)); \
91 _r10 == -1 ? -_retval : _retval; \
94 #define lll_futex_timed_wait_bitset(ftx, val, timespec, clockbit, private) \
95 ({ \
96 int __op = FUTEX_WAIT_BITSET | (clockbit); \
98 DO_INLINE_SYSCALL(futex, 6, (long) (ftx), \
99 __lll_private_flag (__op, private), \
100 (int) (val), (long) (timespec), NULL /* Unused. */, \
101 FUTEX_BITSET_MATCH_ANY); \
102 _r10 == -1 ? -_retval : _retval; \
105 #define lll_futex_wake(ftx, nr, private) \
106 ({ \
107 DO_INLINE_SYSCALL(futex, 3, (long) (ftx), \
108 __lll_private_flag (FUTEX_WAKE, private), \
109 (int) (nr)); \
110 _r10 == -1 ? -_retval : _retval; \
113 /* Returns non-zero if error happened, zero if success. */
114 #define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val, private) \
115 ({ \
116 DO_INLINE_SYSCALL(futex, 6, (long) (ftx), \
117 __lll_private_flag (FUTEX_CMP_REQUEUE, private), \
118 (int) (nr_wake), (int) (nr_move), (long) (mutex), \
119 (int) val); \
120 _r10 == -1; \
123 /* Returns non-zero if error happened, zero if success. */
124 #define lll_futex_wake_unlock(ftx, nr_wake, nr_wake2, ftx2, private) \
125 ({ \
126 DO_INLINE_SYSCALL(futex, 6, (long) (ftx), \
127 __lll_private_flag (FUTEX_WAKE_OP, private), \
128 (int) (nr_wake), (int) (nr_wake2), (long) (ftx2), \
129 FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
130 _r10 == -1; \
133 /* Priority Inheritance support. */
134 #define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
135 lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
137 #define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
138 mutex, private) \
139 ({ \
140 int __op = FUTEX_WAIT_REQUEUE_PI | (clockbit); \
142 DO_INLINE_SYSCALL(futex, 5, (long) (futexp), \
143 __lll_private_flag (__op, private), \
144 (val), (timespec), mutex); \
145 _r10 == -1; \
148 #define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
149 ({ \
150 DO_INLINE_SYSCALL(futex, 6, (long) (futexp), \
151 __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv), \
152 (nr_wake), (nr_move), (mutex), (val)); \
153 _r10 == -1 ? -_retval : _retval; \
157 #define __lll_trylock(futex) \
158 (atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0)
159 #define lll_trylock(futex) __lll_trylock (&(futex))
162 #define __lll_cond_trylock(futex) \
163 (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0)
164 #define lll_cond_trylock(futex) __lll_cond_trylock (&(futex))
167 extern void __lll_lock_wait_private (int *futex) attribute_hidden;
168 extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
169 extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
172 #define __lll_lock(futex, private) \
173 ((void) ({ \
174 int *__futex = (futex); \
175 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, \
176 1, 0), 0)) \
178 if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \
179 __lll_lock_wait_private (__futex); \
180 else \
181 __lll_lock_wait (__futex, private); \
184 #define lll_lock(futex, private) __lll_lock (&(futex), private)
187 #define __lll_robust_lock(futex, id, private) \
188 ({ \
189 int *__futex = (futex); \
190 int __val = 0; \
192 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
193 0), 0)) \
194 __val = __lll_robust_lock_wait (__futex, private); \
195 __val; \
197 #define lll_robust_lock(futex, id, private) \
198 __lll_robust_lock (&(futex), id, private)
201 #define __lll_cond_lock(futex, private) \
202 ((void) ({ \
203 int *__futex = (futex); \
204 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, 2, \
205 0), 0)) \
206 __lll_lock_wait (__futex, private); \
208 #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
211 #define __lll_robust_cond_lock(futex, id, private) \
212 ({ \
213 int *__futex = (futex); \
214 int __val = 0; \
215 int __id = (id) | FUTEX_WAITERS; \
217 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, \
218 __id, 0), 0)) \
219 __val = __lll_robust_lock_wait (__futex, private); \
220 __val; \
222 #define lll_robust_cond_lock(futex, id, private) \
223 __lll_robust_cond_lock (&(futex), id, private)
226 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
227 int private) attribute_hidden;
228 extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
229 int private) attribute_hidden;
232 #define __lll_timedlock(futex, abstime, private) \
233 ({ \
234 int *__futex = (futex); \
235 int __val = 0; \
237 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, 1, \
238 0), 0)) \
239 __val = __lll_timedlock_wait (__futex, abstime, private); \
240 __val; \
242 #define lll_timedlock(futex, abstime, private) \
243 __lll_timedlock (&(futex), abstime, private)
246 #define __lll_robust_timedlock(futex, abstime, id, private) \
247 ({ \
248 int *__futex = (futex); \
249 int __val = 0; \
251 if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \
252 0), 0)) \
253 __val = __lll_robust_timedlock_wait (__futex, abstime, private); \
254 __val; \
256 #define lll_robust_timedlock(futex, abstime, id, private) \
257 __lll_robust_timedlock (&(futex), abstime, id, private)
260 #define __lll_unlock(futex, private) \
261 ((void) ({ \
262 int *__futex = (futex); \
263 int __val = atomic_exchange_rel (__futex, 0); \
265 if (__builtin_expect (__val > 1, 0)) \
266 lll_futex_wake (__futex, 1, private); \
268 #define lll_unlock(futex, private) __lll_unlock(&(futex), private)
271 #define __lll_robust_unlock(futex, private) \
272 ((void) ({ \
273 int *__futex = (futex); \
274 int __val = atomic_exchange_rel (__futex, 0); \
276 if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \
277 lll_futex_wake (__futex, 1, private); \
279 #define lll_robust_unlock(futex, private) \
280 __lll_robust_unlock(&(futex), private)
283 #define lll_islocked(futex) \
284 (futex != 0)
286 /* Initializers for lock. */
287 #define LLL_LOCK_INITIALIZER (0)
288 #define LLL_LOCK_INITIALIZER_LOCKED (1)
290 /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
291 wakeup when the clone terminates. The memory location contains the
292 thread ID while the clone is running and is reset to zero
293 afterwards. */
294 #define lll_wait_tid(tid) \
295 do \
297 __typeof (tid) __tid; \
298 while ((__tid = (tid)) != 0) \
299 lll_futex_wait (&(tid), __tid, LLL_SHARED); \
301 while (0)
303 extern int __lll_timedwait_tid (int *, const struct timespec *)
304 attribute_hidden;
306 #define lll_timedwait_tid(tid, abstime) \
307 ({ \
308 int __res = 0; \
309 if ((tid) != 0) \
310 __res = __lll_timedwait_tid (&(tid), (abstime)); \
311 __res; \
314 #endif /* lowlevellock.h */