]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / libpthread / nptl / sysdeps / unix / sysv / linux / alpha / lowlevellock.h
1 /* Copyright (C) 2003, 2004, 2006, 2007 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; see the file COPYING.LIB.  If
16    not, see <http://www.gnu.org/licenses/>.  */
17
18 #ifndef _LOWLEVELLOCK_H
19 #define _LOWLEVELLOCK_H 1
20
21 #include <time.h>
22 #include <sys/param.h>
23 #include <bits/pthreadtypes.h>
24 #include <atomic.h>
25 #include <sysdep.h>
26 #include <bits/kernel-features.h>
27
28
29 #define FUTEX_WAIT              0
30 #define FUTEX_WAKE              1
31 #define FUTEX_REQUEUE           3
32 #define FUTEX_CMP_REQUEUE       4
33 #define FUTEX_WAKE_OP           5
34 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE   ((4 << 24) | 1)
35 #define FUTEX_LOCK_PI           6
36 #define FUTEX_UNLOCK_PI         7
37 #define FUTEX_TRYLOCK_PI        8
38 #define FUTEX_WAIT_BITSET       9
39 #define FUTEX_WAKE_BITSET       10
40 #define FUTEX_PRIVATE_FLAG      128
41 #define FUTEX_CLOCK_REALTIME    256
42
43 #define FUTEX_BITSET_MATCH_ANY  0xffffffff
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 !defined NOT_IN_libc || defined 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
77 #define lll_futex_wait(futexp, val, private) \
78   lll_futex_timed_wait (futexp, val, NULL, private)
79
80 #define lll_futex_timed_wait(futexp, val, timespec, private) \
81   ({                                                                          \
82     INTERNAL_SYSCALL_DECL (__err);                                            \
83     long int __ret;                                                           \
84     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
85                               __lll_private_flag (FUTEX_WAIT, private),       \
86                               (val), (timespec));                             \
87     INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;                  \
88   })
89
90 #define lll_futex_wake(futexp, nr, private) \
91   ({                                                                          \
92     INTERNAL_SYSCALL_DECL (__err);                                            \
93     long int __ret;                                                           \
94     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
95                               __lll_private_flag (FUTEX_WAKE, private),       \
96                               (nr), 0);                                       \
97     INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;                  \
98   })
99
100 #define lll_robust_dead(futexv, private) \
101   do                                                                          \
102     {                                                                         \
103       int *__futexp = &(futexv);                                              \
104       atomic_or (__futexp, FUTEX_OWNER_DIED);                                 \
105       lll_futex_wake (__futexp, 1, private);                                  \
106     }                                                                         \
107   while (0)
108
109 /* Returns non-zero if error happened, zero if success.  */
110 #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
111   ({                                                                          \
112     INTERNAL_SYSCALL_DECL (__err);                                            \
113     long int __ret;                                                           \
114     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
115                               __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
116                               (nr_wake), (nr_move), (mutex), (val));          \
117     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
118   })
119
120 /* Returns non-zero if error happened, zero if success.  */
121 #define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
122   ({                                                                          \
123     INTERNAL_SYSCALL_DECL (__err);                                            \
124     long int __ret;                                                           \
125     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
126                               __lll_private_flag (FUTEX_WAKE_OP, private),    \
127                               (nr_wake), (nr_wake2), (futexp2),               \
128                               FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
129     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
130   })
131
132
133
134
135 static inline int __attribute__((always_inline))
136 __lll_trylock(int *futex)
137 {
138   return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
139 }
140 #define lll_trylock(lock)       __lll_trylock (&(lock))
141
142
143 static inline int __attribute__((always_inline))
144 __lll_cond_trylock(int *futex)
145 {
146   return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
147 }
148 #define lll_cond_trylock(lock)  __lll_cond_trylock (&(lock))
149
150
151 static inline int __attribute__((always_inline))
152 __lll_robust_trylock(int *futex, int id)
153 {
154   return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0;
155 }
156 #define lll_robust_trylock(lock, id) \
157   __lll_robust_trylock (&(lock), id)
158
159 extern void __lll_lock_wait_private (int *futex) attribute_hidden;
160 extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
161 extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
162
163 static inline void __attribute__((always_inline))
164 __lll_lock(int *futex, int private)
165 {
166   if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0)
167     {
168       if (__builtin_constant_p (private) && private == LLL_PRIVATE)
169         __lll_lock_wait_private (futex);
170       else
171         __lll_lock_wait (futex, private);
172     }
173 }
174 #define lll_lock(futex, private) __lll_lock (&(futex), private)
175
176
177 static inline int __attribute__ ((always_inline))
178 __lll_robust_lock (int *futex, int id, int private)
179 {
180   int result = 0;
181   if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
182     result = __lll_robust_lock_wait (futex, private);
183   return result;
184 }
185 #define lll_robust_lock(futex, id, private) \
186   __lll_robust_lock (&(futex), id, private)
187
188
189 static inline void __attribute__ ((always_inline))
190 __lll_cond_lock (int *futex, int private)
191 {
192   if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0)
193     __lll_lock_wait (futex, private);
194 }
195 #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
196
197
198 #define lll_robust_cond_lock(futex, id, private) \
199   __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
200
201
202 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
203                                  int private) attribute_hidden;
204 extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
205                                         int private) attribute_hidden;
206
207 static inline int __attribute__ ((always_inline))
208 __lll_timedlock (int *futex, const struct timespec *abstime, int private)
209 {
210   int result = 0;
211   if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0)
212     result = __lll_timedlock_wait (futex, abstime, private);
213   return result;
214 }
215 #define lll_timedlock(futex, abstime, private) \
216   __lll_timedlock (&(futex), abstime, private)
217
218
219 static inline int __attribute__ ((always_inline))
220 __lll_robust_timedlock (int *futex, const struct timespec *abstime,
221                         int id, int private)
222 {
223   int result = 0;
224   if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
225     result = __lll_robust_timedlock_wait (futex, abstime, private);
226   return result;
227 }
228 #define lll_robust_timedlock(futex, abstime, id, private) \
229   __lll_robust_timedlock (&(futex), abstime, id, private)
230
231
232 #define __lll_unlock(futex, private) \
233   (void)                                                        \
234     ({ int *__futex = (futex);                                  \
235        int __oldval = atomic_exchange_rel (__futex, 0);         \
236        if (__builtin_expect (__oldval > 1, 0))                  \
237          lll_futex_wake (__futex, 1, private);                  \
238     })
239 #define lll_unlock(futex, private) __lll_unlock(&(futex), private)
240
241
242 #define __lll_robust_unlock(futex, private) \
243   (void)                                                        \
244     ({ int *__futex = (futex);                                  \
245        int __oldval = atomic_exchange_rel (__futex, 0);         \
246        if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))      \
247          lll_futex_wake (__futex, 1, private);                  \
248     })
249 #define lll_robust_unlock(futex, private) \
250   __lll_robust_unlock(&(futex), private)
251
252
253 #define lll_islocked(futex) \
254   (futex != 0)
255
256 /* Initializers for lock.  */
257 #define LLL_LOCK_INITIALIZER            (0)
258 #define LLL_LOCK_INITIALIZER_LOCKED     (1)
259
260
261 /* The kernel notifies a process which uses CLONE_CLEARTID via futex
262    wakeup when the clone terminates.  The memory location contains the
263    thread ID while the clone is running and is reset to zero
264    afterwards.  */
265 #define lll_wait_tid(tid) \
266   do {                                                  \
267     __typeof (tid) __tid;                               \
268     while ((__tid = (tid)) != 0)                        \
269       lll_futex_wait (&(tid), __tid, LLL_SHARED);       \
270   } while (0)
271
272 extern int __lll_timedwait_tid (int *, const struct timespec *)
273      attribute_hidden;
274
275 #define lll_timedwait_tid(tid, abstime) \
276   ({                                                    \
277     int __res = 0;                                      \
278     if ((tid) != 0)                                     \
279       __res = __lll_timedwait_tid (&(tid), (abstime));  \
280     __res;                                              \
281   })
282
283 #endif  /* lowlevellock.h */