]>
Commit | Line | Data |
---|---|---|
04277e02 | 1 | /* Copyright (C) 2003-2019 Free Software Foundation, Inc. |
cd2fbe58 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Jakub Jelinek <jakub@redhat.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/>. */ | |
cd2fbe58 UD |
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> | |
25 | #include <atomic.h> | |
f8de5057 | 26 | #include <kernel-features.h> |
cd2fbe58 | 27 | |
f7092599 | 28 | #include <lowlevellock-futex.h> |
2b7ae1b2 | 29 | |
cd2fbe58 UD |
30 | static inline int |
31 | __attribute__ ((always_inline)) | |
e51deae7 | 32 | __lll_trylock (int *futex) |
cd2fbe58 | 33 | { |
b01fe5f7 | 34 | return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; |
cd2fbe58 | 35 | } |
e51deae7 | 36 | #define lll_trylock(futex) __lll_trylock (&(futex)) |
cd2fbe58 | 37 | |
2c0b891a UD |
38 | static inline int |
39 | __attribute__ ((always_inline)) | |
e51deae7 | 40 | __lll_cond_trylock (int *futex) |
2c0b891a | 41 | { |
b01fe5f7 | 42 | return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; |
2c0b891a | 43 | } |
e51deae7 | 44 | #define lll_cond_trylock(futex) __lll_cond_trylock (&(futex)) |
2c0b891a | 45 | |
a334319f | 46 | |
e51deae7 UD |
47 | extern void __lll_lock_wait_private (int *futex) attribute_hidden; |
48 | extern void __lll_lock_wait (int *futex, int private) attribute_hidden; | |
cd2fbe58 UD |
49 | |
50 | static inline void | |
51 | __attribute__ ((always_inline)) | |
e51deae7 | 52 | __lll_lock (int *futex, int private) |
cd2fbe58 | 53 | { |
b01fe5f7 | 54 | int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); |
cd2fbe58 | 55 | |
a1ffb40e | 56 | if (__glibc_unlikely (val != 0)) |
e51deae7 UD |
57 | { |
58 | if (__builtin_constant_p (private) && private == LLL_PRIVATE) | |
59 | __lll_lock_wait_private (futex); | |
60 | else | |
61 | __lll_lock_wait (futex, private); | |
62 | } | |
cd2fbe58 | 63 | } |
e51deae7 | 64 | #define lll_lock(futex, private) __lll_lock (&(futex), private) |
cd2fbe58 | 65 | |
cd2fbe58 UD |
66 | static inline void |
67 | __attribute__ ((always_inline)) | |
e51deae7 | 68 | __lll_cond_lock (int *futex, int private) |
cd2fbe58 | 69 | { |
b01fe5f7 | 70 | int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); |
cd2fbe58 | 71 | |
a1ffb40e | 72 | if (__glibc_unlikely (val != 0)) |
e51deae7 | 73 | __lll_lock_wait (futex, private); |
cd2fbe58 | 74 | } |
e51deae7 | 75 | #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) |
cd2fbe58 UD |
76 | |
77 | ||
e51deae7 UD |
78 | extern int __lll_timedlock_wait (int *futex, const struct timespec *, |
79 | int private) attribute_hidden; | |
cd2fbe58 UD |
80 | |
81 | static inline int | |
82 | __attribute__ ((always_inline)) | |
e51deae7 | 83 | __lll_timedlock (int *futex, const struct timespec *abstime, int private) |
cd2fbe58 | 84 | { |
b01fe5f7 | 85 | int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); |
cd2fbe58 | 86 | int result = 0; |
2c0b891a | 87 | |
a1ffb40e | 88 | if (__glibc_unlikely (val != 0)) |
e51deae7 | 89 | result = __lll_timedlock_wait (futex, abstime, private); |
cd2fbe58 UD |
90 | return result; |
91 | } | |
e51deae7 UD |
92 | #define lll_timedlock(futex, abstime, private) \ |
93 | __lll_timedlock (&(futex), abstime, private) | |
cd2fbe58 | 94 | |
e51deae7 | 95 | #define lll_unlock(lock, private) \ |
0ecb606c JJ |
96 | ((void) ({ \ |
97 | int *__futex = &(lock); \ | |
389fdf78 | 98 | int __private = (private); \ |
b01fe5f7 | 99 | int __val = atomic_exchange_24_rel (__futex, 0); \ |
a1ffb40e | 100 | if (__glibc_unlikely (__val > 1)) \ |
389fdf78 | 101 | lll_futex_wake (__futex, 1, __private); \ |
0ecb606c JJ |
102 | })) |
103 | ||
e51deae7 | 104 | #define lll_islocked(futex) \ |
cd2fbe58 UD |
105 | (futex != 0) |
106 | ||
cd2fbe58 UD |
107 | /* Initializers for lock. */ |
108 | #define LLL_LOCK_INITIALIZER (0) | |
109 | #define LLL_LOCK_INITIALIZER_LOCKED (1) | |
110 | ||
adcdc775 | 111 | /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex |
cd2fbe58 UD |
112 | wakeup when the clone terminates. The memory location contains the |
113 | thread ID while the clone is running and is reset to zero | |
114 | afterwards. */ | |
115 | #define lll_wait_tid(tid) \ | |
085a4412 UD |
116 | do \ |
117 | { \ | |
118 | __typeof (tid) __tid; \ | |
119 | while ((__tid = (tid)) != 0) \ | |
120 | lll_futex_wait (&(tid), __tid, LLL_SHARED); \ | |
121 | } \ | |
cd2fbe58 UD |
122 | while (0) |
123 | ||
124 | extern int __lll_timedwait_tid (int *, const struct timespec *) | |
125 | attribute_hidden; | |
126 | ||
127 | #define lll_timedwait_tid(tid, abstime) \ | |
128 | ({ \ | |
129 | int __res = 0; \ | |
130 | if ((tid) != 0) \ | |
131 | __res = __lll_timedwait_tid (&(tid), (abstime)); \ | |
132 | __res; \ | |
133 | }) | |
134 | ||
cd2fbe58 | 135 | #endif /* lowlevellock.h */ |