Force eval for fma implementations
[platform/upstream/glibc.git] / sysdeps / unix / sysv / linux / arm / lowlevellock.h
1 /* Copyright (C) 2005-2014 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, see
16    <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 <kernel-features.h>
27
28 #define FUTEX_WAIT              0
29 #define FUTEX_WAKE              1
30 #define FUTEX_REQUEUE           3
31 #define FUTEX_CMP_REQUEUE       4
32 #define FUTEX_WAKE_OP           5
33 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE   ((4 << 24) | 1)
34 #define FUTEX_LOCK_PI           6
35 #define FUTEX_UNLOCK_PI         7
36 #define FUTEX_TRYLOCK_PI        8
37 #define FUTEX_WAIT_BITSET       9
38 #define FUTEX_WAKE_BITSET       10
39 #define FUTEX_WAIT_REQUEUE_PI   11
40 #define FUTEX_CMP_REQUEUE_PI    12
41 #define FUTEX_PRIVATE_FLAG      128
42 #define FUTEX_CLOCK_REALTIME    256
43
44 #define FUTEX_BITSET_MATCH_ANY  0xffffffff
45
46 /* Values for 'private' parameter of locking macros.  Yes, the
47    definition seems to be backwards.  But it is not.  The bit will be
48    reversed before passing to the system call.  */
49 #define LLL_PRIVATE     0
50 #define LLL_SHARED      FUTEX_PRIVATE_FLAG
51
52
53 #if !defined NOT_IN_libc || defined IS_IN_rtld
54 /* In libc.so or ld.so all futexes are private.  */
55 # ifdef __ASSUME_PRIVATE_FUTEX
56 #  define __lll_private_flag(fl, private) \
57   ((fl) | FUTEX_PRIVATE_FLAG)
58 # else
59 #  define __lll_private_flag(fl, private) \
60   ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
61 # endif
62 #else
63 # ifdef __ASSUME_PRIVATE_FUTEX
64 #  define __lll_private_flag(fl, private) \
65   (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
66 # else
67 #  define __lll_private_flag(fl, private) \
68   (__builtin_constant_p (private)                                             \
69    ? ((private) == 0                                                          \
70       ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))            \
71       : (fl))                                                                 \
72    : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG)                                \
73               & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
74 # endif
75 #endif
76
77
78 #define lll_futex_wait(futexp, val, private) \
79   lll_futex_timed_wait(futexp, val, NULL, private)
80
81 #define lll_futex_timed_wait(futexp, val, timespec, private) \
82   ({                                                                          \
83     INTERNAL_SYSCALL_DECL (__err);                                            \
84     long int __ret;                                                           \
85     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
86                               __lll_private_flag (FUTEX_WAIT, private),       \
87                               (val), (timespec));                             \
88     __ret;                                                                    \
89   })
90
91 #define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
92   ({                                                                    \
93     INTERNAL_SYSCALL_DECL (__err);                                      \
94     long int __ret;                                                     \
95     int __op = FUTEX_WAIT_BITSET | clockbit;                            \
96     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                \
97                               __lll_private_flag (__op, private),       \
98                               (val), (timespec), NULL /* Unused.  */,   \
99                               FUTEX_BITSET_MATCH_ANY);                  \
100     __ret;                                                              \
101   })
102
103 #define lll_futex_wake(futexp, nr, private) \
104   ({                                                                          \
105     INTERNAL_SYSCALL_DECL (__err);                                            \
106     long int __ret;                                                           \
107     __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp),                      \
108                               __lll_private_flag (FUTEX_WAKE, private),       \
109                               (nr), 0);                                       \
110     __ret;                                                                    \
111   })
112
113 /* Returns non-zero if error happened, zero if success.  */
114 #define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
115   ({                                                                          \
116     INTERNAL_SYSCALL_DECL (__err);                                            \
117     long int __ret;                                                           \
118     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
119                               __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
120                               (nr_wake), (nr_move), (mutex), (val));          \
121     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
122   })
123
124
125 /* Returns non-zero if error happened, zero if success.  */
126 #define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
127   ({                                                                          \
128     INTERNAL_SYSCALL_DECL (__err);                                            \
129     long int __ret;                                                           \
130     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
131                               __lll_private_flag (FUTEX_WAKE_OP, private),    \
132                               (nr_wake), (nr_wake2), (futexp2),               \
133                               FUTEX_OP_CLEAR_WAKE_IF_GT_ONE);                 \
134     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
135   })
136
137 /* Priority Inheritance support.  */
138 #define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
139   lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
140
141 #define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit,      \
142                                         mutex, private)                       \
143   ({                                                                          \
144     INTERNAL_SYSCALL_DECL (__err);                                            \
145     int __op = FUTEX_WAIT_REQUEUE_PI | clockbit;                              \
146                                                                               \
147     INTERNAL_SYSCALL (futex, __err, 5, (futexp),                              \
148                       __lll_private_flag (__op, private),                     \
149                       (val), (timespec), mutex);                              \
150   })
151
152 #define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv)  \
153   ({                                                                          \
154     INTERNAL_SYSCALL_DECL (__err);                                            \
155     long int __ret;                                                           \
156                                                                               \
157     __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp),                      \
158                               __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
159                               (nr_wake), (nr_move), (mutex), (val));          \
160     INTERNAL_SYSCALL_ERROR_P (__ret, __err);                                  \
161   })
162
163
164 #define lll_trylock(lock)       \
165   atomic_compare_and_exchange_val_acq(&(lock), 1, 0)
166
167 #define lll_cond_trylock(lock)  \
168   atomic_compare_and_exchange_val_acq(&(lock), 2, 0)
169
170 extern void __lll_lock_wait_private (int *futex) attribute_hidden;
171 extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
172 extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
173
174 #define __lll_lock(futex, private)                                            \
175   ((void) ({                                                                  \
176     int *__futex = (futex);                                                   \
177     if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex,       \
178                                                                 1, 0), 0))    \
179       {                                                                       \
180         if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)       \
181           __lll_lock_wait_private (__futex);                                  \
182         else                                                                  \
183           __lll_lock_wait (__futex, private);                                 \
184       }                                                                       \
185   }))
186 #define lll_lock(futex, private) __lll_lock (&(futex), private)
187
188
189 #define __lll_robust_lock(futex, id, private)                                 \
190   ({                                                                          \
191     int *__futex = (futex);                                                   \
192     int __val = 0;                                                            \
193                                                                               \
194     if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
195                                                                 0), 0))       \
196       __val = __lll_robust_lock_wait (__futex, private);                      \
197     __val;                                                                    \
198   })
199 #define lll_robust_lock(futex, id, private) \
200   __lll_robust_lock (&(futex), id, private)
201
202
203 #define __lll_cond_lock(futex, private)                                       \
204   ((void) ({                                                                  \
205     int *__futex = (futex);                                                   \
206     if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0))               \
207       __lll_lock_wait (__futex, private);                                     \
208   }))
209 #define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
210
211
212 #define lll_robust_cond_lock(futex, id, private) \
213   __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
214
215
216 extern int __lll_timedlock_wait (int *futex, const struct timespec *,
217                                  int private) attribute_hidden;
218 extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
219                                         int private) attribute_hidden;
220
221 #define __lll_timedlock(futex, abstime, private)                              \
222   ({                                                                          \
223      int *__futex = (futex);                                                  \
224      int __val = 0;                                                           \
225                                                                               \
226      if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0))              \
227        __val = __lll_timedlock_wait (__futex, abstime, private);              \
228      __val;                                                                   \
229   })
230 #define lll_timedlock(futex, abstime, private) \
231   __lll_timedlock (&(futex), abstime, private)
232
233
234 #define __lll_robust_timedlock(futex, abstime, id, private)                   \
235   ({                                                                          \
236     int *__futex = (futex);                                                   \
237     int __val = 0;                                                            \
238                                                                               \
239     if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id,  \
240                                                                 0), 0))       \
241       __val = __lll_robust_timedlock_wait (__futex, abstime, private);        \
242     __val;                                                                    \
243   })
244 #define lll_robust_timedlock(futex, abstime, id, private) \
245   __lll_robust_timedlock (&(futex), abstime, id, private)
246
247
248 #define __lll_unlock(futex, private) \
249   (void)                                                        \
250     ({ int *__futex = (futex);                                  \
251        int __oldval = atomic_exchange_rel (__futex, 0);         \
252        if (__builtin_expect (__oldval > 1, 0))                  \
253          lll_futex_wake (__futex, 1, private);                  \
254     })
255 #define lll_unlock(futex, private) __lll_unlock(&(futex), private)
256
257
258 #define __lll_robust_unlock(futex, private) \
259   (void)                                                        \
260     ({ int *__futex = (futex);                                  \
261        int __oldval = atomic_exchange_rel (__futex, 0);         \
262        if (__builtin_expect (__oldval & FUTEX_WAITERS, 0))      \
263          lll_futex_wake (__futex, 1, private);                  \
264     })
265 #define lll_robust_unlock(futex, private) \
266   __lll_robust_unlock(&(futex), private)
267
268
269 #define lll_islocked(futex) \
270   (futex != 0)
271
272
273 /* Our internal lock implementation is identical to the binary-compatible
274    mutex implementation. */
275
276 /* Initializers for lock.  */
277 #define LLL_LOCK_INITIALIZER            (0)
278 #define LLL_LOCK_INITIALIZER_LOCKED     (1)
279
280 /* The states of a lock are:
281     0  -  untaken
282     1  -  taken by one user
283    >1  -  taken by more users */
284
285 /* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
286    wakeup when the clone terminates.  The memory location contains the
287    thread ID while the clone is running and is reset to zero
288    afterwards.  */
289 #define lll_wait_tid(tid) \
290   do {                                  \
291     __typeof (tid) __tid;               \
292     while ((__tid = (tid)) != 0)        \
293       lll_futex_wait (&(tid), __tid, LLL_SHARED);\
294   } while (0)
295
296 extern int __lll_timedwait_tid (int *, const struct timespec *)
297      attribute_hidden;
298
299 #define lll_timedwait_tid(tid, abstime) \
300   ({                                                    \
301     int __res = 0;                                      \
302     if ((tid) != 0)                                     \
303       __res = __lll_timedwait_tid (&(tid), (abstime));  \
304     __res;                                              \
305   })
306
307 #endif  /* lowlevellock.h */