Move m68k from ports to libc
[jlayton/glibc.git] / sysdeps / unix / sysv / linux / m68k / nptl / lowlevellock.h
1 /* Copyright (C) 2010-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
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
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 /* Borrowed from ARM's version.  */
20
21 #ifndef _LOWLEVELLOCK_H
22 #define _LOWLEVELLOCK_H 1
23
24 #include <time.h>
25 #include <sys/param.h>
26 #include <bits/pthreadtypes.h>
27 #include <atomic.h>
28 #include <kernel-features.h>
29
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_REQEUE_PI    11
42 #define FUTEX_CMP_REQEUE_PI     12
43 #define FUTEX_PRIVATE_FLAG      128
44 #define FUTEX_CLOCK_REALTIME    256
45
46 #define FUTEX_BITSET_MATCH_ANY  0xffffffff
47
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
53
54
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))))
76 # endif
77 #endif
78
79
80 #define lll_futex_wait(futexp, val, private) \
81   lll_futex_timed_wait(futexp, val, NULL, private)
82
83 #define lll_futex_timed_wait(futexp, val, timespec, private) \
84   ({                                                                          \
85     INTERNAL_SYSCALL_DECL (__err);                                            \
86     long int __ret;                                                           \
87     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
88                               __lll_private_flag (FUTEX_WAIT, private),       \
89                               (val), (timespec));                             \
90     __ret;                                                                    \
91   })
92
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     __ret = INTERNAL_SYSCALL (futex, __err, 6, (long) (futexp),               \
99                               __lll_private_flag (__op, private),             \
100                               (val), (timespec), NULL /* Unused.  */,         \
101                               FUTEX_BITSET_MATCH_ANY);                        \
102     __ret;                                                                    \
103   })
104
105 #define lll_futex_wake(futexp, nr, private) \
106   ({                                                                          \
107     INTERNAL_SYSCALL_DECL (__err);                                            \
108     long int __ret;                                                           \
109     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
110                               __lll_private_flag (FUTEX_WAKE, private),       \
111                               (nr), 0);                                       \
112     __ret;                                                                    \
113   })
114
115 #define lll_robust_dead(futexv, private) \
116   do                                                                          \
117     {                                                                         \
118       int *__futexp = &(futexv);                                              \
119       atomic_or (__futexp, FUTEX_OWNER_DIED);                                 \
120       lll_futex_wake (__futexp, 1, private);                                  \
121     }                                                                         \
122   while (0)
123
124 /* Returns non-zero if error happened, zero if success.  */
125 #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
126   ({                                                                          \
127     INTERNAL_SYSCALL_DECL (__err);                                            \
128     long int __ret;                                                           \
129     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
130                               __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
131                               (nr_wake), (nr_move), (mutex), (val));          \
132     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
133   })
134
135 /* Returns non-zero if error happened, zero if success.  */
136 #define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
137   ({                                                                          \
138     INTERNAL_SYSCALL_DECL (__err);                                            \
139     long int __ret;                                                           \
140     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
141                               __lll_private_flag (FUTEX_WAKE_OP, private),    \
142                               (nr_wake), (nr_wake2), (futexp2),               \
143                               FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
144     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
145   })
146
147 /* Priority Inheritance support.  */
148 #define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
149   lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
150
151 #define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit,      \
152                                         mutex, private)                       \
153   ({                                                                          \
154     INTERNAL_SYSCALL_DECL (__err);                                            \
155     long int __ret;                                                           \
156     int __op = FUTEX_WAIT_REQUEUE_PI | clockbit;                              \
157                                                                               \
158     __ret = INTERNAL_SYSCALL (futex, __err, 5, (futexp),                      \
159                               __lll_private_flag (__op, private),             \
160                               (val), (timespec), mutex);                      \
161     __ret;                                                                    \
162   })
163
164 #define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv)  \
165   ({                                                                          \
166     INTERNAL_SYSCALL_DECL (__err);                                            \
167     long int __ret;                                                           \
168     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
169                               __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
170                               (nr_wake), (nr_move), (mutex), (val));          \
171     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
172   })
173
174 #define lll_trylock(lock)                               \
175   atomic_compare_and_exchange_val_acq (&(lock), 1, 0)
176
177 #define lll_cond_trylock(lock)                          \
178   atomic_compare_and_exchange_val_acq (&(lock), 2, 0)
179
180 #define lll_robust_trylock(lock, id)                    \
181   atomic_compare_and_exchange_val_acq (&(lock), id, 0)
182
183 extern void __lll_lock_wait_private (int *futex) attribute_hidden;
184 extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
185 extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
186
187 #define __lll_lock(futex, private)                                            \
188   ((void) ({                                                                  \
189     int *__futex = (futex);                                                   \
190     if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
191                                                                 1, 0), 0))    \
192       {                                                                       \
193         if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)       \
194           __lll_lock_wait_private (__futex);                                  \
195         else                                                                  \
196           __lll_lock_wait (__futex, private);                                 \
197       }                                                                       \
198   }))
199 #define lll_lock(futex, private) __lll_lock (&(futex), private)
200
201
202 #define __lll_robust_lock(futex, id, private)                                 \
203   ({                                                                          \
204     int *__futex = (futex);                                                   \
205     int __val = 0;                                                            \
206                                                                               \
207     if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
208                                                                 0), 0))       \
209       __val = __lll_robust_lock_wait (__futex, private);                      \
210     __val;                                                                    \
211   })
212 #define lll_robust_lock(futex, id, private) \
213   __lll_robust_lock (&(futex), id, private)
214
215
216 #define __lll_cond_lock(futex, private)                                       \
217   ((void) ({                                                                  \
218     int *__futex = (futex);                                                   \
219     if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))               \
220       __lll_lock_wait (__futex, private);                                     \
221   }))
222 #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
223
224
225 #define lll_robust_cond_lock(futex, id, private) \
226   __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
227
228
229 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
230                                  int private) attribute_hidden;
231 extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
232                                         int private) attribute_hidden;
233
234 #define __lll_timedlock(futex, abstime, private)                              \
235   ({                                                                          \
236      int *__futex = (futex);                                                  \
237      int __val = 0;                                                           \
238                                                                               \
239      if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))              \
240        __val = __lll_timedlock_wait (__futex, abstime, private);              \
241      __val;                                                                   \
242   })
243 #define lll_timedlock(futex, abstime, private) \
244   __lll_timedlock (&(futex), abstime, private)
245
246
247 #define __lll_robust_timedlock(futex, abstime, id, private)                   \
248   ({                                                                          \
249     int *__futex = (futex);                                                   \
250     int __val = 0;                                                            \
251                                                                               \
252     if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
253                                                                 0), 0))       \
254       __val = __lll_robust_timedlock_wait (__futex, abstime, private);        \
255     __val;                                                                    \
256   })
257 #define lll_robust_timedlock(futex, abstime, id, private) \
258   __lll_robust_timedlock (&(futex), abstime, id, private)
259
260
261 #define __lll_unlock(futex, private) \
262   (void)                                                        \
263     ({ int *__futex = (futex);                                  \
264        int __oldval = atomic_exchange_rel (__futex, 0);         \
265        if (__builtin_expect (__oldval > 1, 0))                  \
266          lll_futex_wake (__futex, 1, private);                  \
267     })
268 #define lll_unlock(futex, private) __lll_unlock(&(futex), private)
269
270
271 #define __lll_robust_unlock(futex, private) \
272   (void)                                                        \
273     ({ int *__futex = (futex);                                  \
274        int __oldval = atomic_exchange_rel (__futex, 0);         \
275        if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))      \
276          lll_futex_wake (__futex, 1, private);                  \
277     })
278 #define lll_robust_unlock(futex, private) \
279   __lll_robust_unlock(&(futex), private)
280
281
282 #define lll_islocked(futex) \
283   (futex != 0)
284
285
286 /* Our internal lock implementation is identical to the binary-compatible
287    mutex implementation. */
288
289 /* Initializers for lock.  */
290 #define LLL_LOCK_INITIALIZER            (0)
291 #define LLL_LOCK_INITIALIZER_LOCKED     (1)
292
293 /* The states of a lock are:
294     0  -  untaken
295     1  -  taken by one user
296    >1  -  taken by more users */
297
298 /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
299    wakeup when the clone terminates.  The memory location contains the
300    thread ID while the clone is running and is reset to zero
301    afterwards.  */
302 #define lll_wait_tid(tid) \
303   do {                                                  \
304     __typeof (tid) __tid;                               \
305     while ((__tid = (tid)) != 0)                        \
306       lll_futex_wait (&(tid), __tid, LLL_SHARED);       \
307   } while (0)
308
309 extern int __lll_timedwait_tid (int *, const struct timespec *)
310      attribute_hidden;
311
312 #define lll_timedwait_tid(tid, abstime) \
313   ({                                                    \
314     int __res = 0;                                      \
315     if ((tid) != 0)                                     \
316       __res = __lll_timedwait_tid (&(tid), (abstime));  \
317     __res;                                              \
318   })
319
320 #endif  /* lowlevellock.h */