]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/metag/lowlevellock.h
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libpthread / nptl / sysdeps / unix / sysv / linux / metag / lowlevellock.h
1 /* Copyright (C) 2005, 2006, 2007, 2008, 2009 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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
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>
26 #include <sysdep.h>
27 #include <bits/kernel-features.h>
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     __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     __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
121 /* Returns non-zero if error happened, zero if success.  */
122 #define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
123   ({                                                                          \
124     INTERNAL_SYSCALL_DECL (__err);                                            \
125     long int __ret;                                                           \
126     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
127                               __lll_private_flag (FUTEX_WAKE_OP, private),    \
128                               (nr_wake), (nr_wake2), (futexp2),               \
129                               FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
130     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
131   })
132
133
134 #define lll_trylock(lock)       \
135   atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
136
137 #define lll_cond_trylock(lock)  \
138   atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
139
140 #define __lll_robust_trylock(futex, id) \
141   (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0)
142 #define lll_robust_trylock(lock, id) \
143   __lll_robust_trylock (&(lock), id)
144
145 extern void __lll_lock_wait_private (int *futex) attribute_hidden;
146 extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
147 extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
148
149 #define __lll_lock(futex, private)                                            \
150   ((void) ({                                                                  \
151     int *__futex = (futex);                                                   \
152     if (unlikely(atomic_compare_and_exchange_val_acq (__futex, 1, 0)))        \
153       {                                                                       \
154         if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)       \
155           __lll_lock_wait_private (__futex);                                  \
156         else                                                                  \
157           __lll_lock_wait (__futex, private);                                 \
158       }                                                                       \
159   }))
160 #define lll_lock(futex, private) __lll_lock (&(futex), private)
161
162
163 #define __lll_robust_lock(futex, id, private)                                 \
164   ({                                                                          \
165     int *__futex = (futex);                                                   \
166     int __val = 0;                                                            \
167                                                                               \
168     if (unlikely(atomic_compare_and_exchange_bool_acq (__futex, id, 0)))      \
169       __val = __lll_robust_lock_wait (__futex, private);                      \
170     __val;                                                                    \
171   })
172 #define lll_robust_lock(futex, id, private) \
173   __lll_robust_lock (&(futex), id, private)
174
175
176 #define __lll_cond_lock(futex, private)                                       \
177   ((void) ({                                                                  \
178     int *__futex = (futex);                                                   \
179     if (unlikely(atomic_exchange_acq (__futex, 2)))                           \
180       __lll_lock_wait (__futex, private);                                     \
181   }))
182 #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
183
184
185 #define lll_robust_cond_lock(futex, id, private) \
186   __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
187
188
189 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
190                                  int private) attribute_hidden;
191 extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
192                                         int private) attribute_hidden;
193
194 #define __lll_timedlock(futex, abstime, private)                              \
195   ({                                                                          \
196      int *__futex = (futex);                                                  \
197      int __val = 0;                                                           \
198                                                                               \
199      if (unlikely(atomic_exchange_acq (__futex, 1)))                          \
200        __val = __lll_timedlock_wait (__futex, abstime, private);              \
201      __val;                                                                   \
202   })
203 #define lll_timedlock(futex, abstime, private) \
204   __lll_timedlock (&(futex), abstime, private)
205
206
207 #define __lll_robust_timedlock(futex, abstime, id, private)                   \
208   ({                                                                          \
209     int *__futex = (futex);                                                   \
210     int __val = 0;                                                            \
211                                                                               \
212     if (unlikely(atomic_compare_and_exchange_bool_acq (__futex, id, 0)))      \
213       __val = __lll_robust_timedlock_wait (__futex, abstime, private);        \
214     __val;                                                                    \
215   })
216 #define lll_robust_timedlock(futex, abstime, id, private) \
217   __lll_robust_timedlock (&(futex), abstime, id, private)
218
219
220 #define __lll_unlock(futex, private) \
221   (void)                                                        \
222     ({ int *__futex = (futex);                                  \
223        int __oldval = atomic_exchange_rel (__futex, 0);         \
224        if (unlikely(__oldval > 1))                              \
225          lll_futex_wake (__futex, 1, private);                  \
226     })
227 #define lll_unlock(futex, private) __lll_unlock(&(futex), private)
228
229
230 #define __lll_robust_unlock(futex, private) \
231   (void)                                                        \
232     ({ int *__futex = (futex);                                  \
233        int __oldval = atomic_exchange_rel (__futex, 0);         \
234        if (unlikely(__oldval & FUTEX_WAITERS))                  \
235          lll_futex_wake (__futex, 1, private);                  \
236     })
237 #define lll_robust_unlock(futex, private) \
238   __lll_robust_unlock(&(futex), private)
239
240
241 #define lll_islocked(futex) \
242   (futex != 0)
243
244
245 /* Our internal lock implementation is identical to the binary-compatible
246    mutex implementation. */
247
248 /* Initializers for lock.  */
249 #define LLL_LOCK_INITIALIZER            (0)
250 #define LLL_LOCK_INITIALIZER_LOCKED     (1)
251
252 /* The states of a lock are:
253     0  -  untaken
254     1  -  taken by one user
255    >1  -  taken by more users */
256
257 /* The kernel notifies a process which uses CLONE_CLEARTID via futex
258    wakeup when the clone terminates.  The memory location contains the
259    thread ID while the clone is running and is reset to zero
260    afterwards.  */
261 #define lll_wait_tid(tid) \
262   do {                                  \
263     __typeof (tid) __tid;               \
264     while ((__tid = (tid)) != 0)        \
265       lll_futex_wait (&(tid), __tid, LLL_SHARED);\
266   } while (0)
267
268 extern int __lll_timedwait_tid (int *, const struct timespec *)
269      attribute_hidden;
270
271 #define lll_timedwait_tid(tid, abstime) \
272   ({                                                    \
273     int __res = 0;                                      \
274     if ((tid) != 0)                                     \
275       __res = __lll_timedwait_tid (&(tid), (abstime));  \
276     __res;                                              \
277   })
278
279 #endif  /* lowlevellock.h */