]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/sysdeps/unix/sysv/linux/s390/lowlevellock.h
Update.
[thirdparty/glibc.git] / nptl / sysdeps / unix / sysv / linux / s390 / lowlevellock.h
CommitLineData
a88c9263
UD
1/* Copyright (C) 2003 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Martin Schwidefsky <schwidefsky@de.ibm.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
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#ifndef _LOWLEVELLOCK_H
21#define _LOWLEVELLOCK_H 1
22
23#include <time.h>
24#include <sys/param.h>
25#include <bits/pthreadtypes.h>
26
27#define SYS_futex 238
28#define FUTEX_WAIT 0
29#define FUTEX_WAKE 1
284bdc42 30#define FUTEX_REQUEUE 3
a88c9263
UD
31
32/* Initializer for compatibility lock. */
33#define LLL_MUTEX_LOCK_INITIALIZER (0)
34
35#define lll_futex_wait(futex, val) \
36 ({ \
37 register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
38 register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \
39 register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \
40 register unsigned long int __r5 asm ("5") = 0ul; \
41 register unsigned long __result asm ("2"); \
42 \
43 __asm __volatile ("svc %b1" \
44 : "=d" (__result) \
45 : "i" (SYS_futex), "0" (__r2), "d" (__r3), \
46 "d" (__r4), "d" (__r5) \
47 : "cc", "memory" ); \
48 __result; \
49 })
50
51
52#define lll_futex_timed_wait(futex, val, timespec) \
53 ({ \
54 register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
55 register unsigned long int __r3 asm ("3") = FUTEX_WAIT; \
56 register unsigned long int __r4 asm ("4") = (unsigned long int) (val); \
57 register unsigned long int __r5 asm ("5") = (unsigned long int)(timespec);\
58 register unsigned long int __result asm ("2"); \
59 \
60 __asm __volatile ("svc %b1" \
61 : "=d" (__result) \
62 : "i" (SYS_futex), "0" (__r2), "d" (__r3), \
63 "d" (__r4), "d" (__r5) \
64 : "cc", "memory" ); \
65 __result; \
66 })
67
68
69#define lll_futex_wake(futex, nr) \
70 ({ \
71 register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
72 register unsigned long int __r3 asm ("3") = FUTEX_WAKE; \
73 register unsigned long int __r4 asm ("4") = (unsigned long int) (nr); \
74 register unsigned long int __result asm ("2"); \
75 \
76 __asm __volatile ("svc %b1" \
77 : "=d" (__result) \
78 : "i" (SYS_futex), "0" (__r2), "d" (__r3), "d" (__r4) \
79 : "cc", "memory" ); \
80 __result; \
81 })
82
83
284bdc42
UD
84#define lll_futex_requeue(futex, nr_wake, nr_move, mutex) \
85 ({ \
86 register unsigned long int __r2 asm ("2") = (unsigned long int) (futex); \
87 register unsigned long int __r3 asm ("3") = FUTEX_REQUEUE; \
88 register unsigned long int __r4 asm ("4") = (long int) (nr_wake); \
89 register unsigned long int __r5 asm ("5") = (long int) (nr_move); \
90 register unsigned long int __r6 asm ("6") = (unsigned long int) (mutex); \
91 register unsigned long __result asm ("2"); \
92 \
93 __asm __volatile ("svc %b1" \
94 : "=d" (__result) \
95 : "i" (SYS_futex), "0" (__r2), "d" (__r3), \
96 "d" (__r4), "d" (__r5), "d" (__r6) \
97 : "cc", "memory" ); \
98 __result; \
99 })
100
101
a88c9263
UD
102#define lll_compare_and_swap(futex, oldval, newval, operation) \
103 do { \
104 __typeof (futex) __futex = (futex); \
105 __asm __volatile (" l %1,%0\n" \
106 "0: " operation "\n" \
107 " cs %1,%2,%0\n" \
108 " jl 0b\n" \
109 "1:" \
110 : "=Q" (*__futex), "=&d" (oldval), "=&d" (newval) \
111 : "m" (*__futex) : "cc" ); \
112 } while (0)
113
114
115static inline int
116__attribute__ ((always_inline))
117__lll_mutex_trylock (int *futex)
118{
119 unsigned int old;
120
121 __asm __volatile ("cs %0,%3,%1"
122 : "=d" (old), "=Q" (*futex)
123 : "0" (0), "d" (1), "m" (*futex) : "cc" );
124 return old != 0;
125}
126#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
127
128
129extern void ___lll_mutex_lock (int *, int) attribute_hidden;
130
131
132static inline void
133__attribute__ ((always_inline))
134__lll_mutex_lock (int *futex)
135{
136 int oldval;
137 int newval;
138
139 lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
140 if (oldval > 0)
141 ___lll_mutex_lock (futex, newval);
142}
143#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex))
144
145
146extern int ___lll_mutex_timedlock (int *, const struct timespec *, int)
147 attribute_hidden;
148
149
150static inline int
151__attribute__ ((always_inline))
152__lll_mutex_timedlock (int *futex, struct timespec *abstime)
153{
154 int oldval;
155 int newval;
156 int result = 0;
157
158 lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
159 if (oldval > 0)
160 result = ___lll_mutex_timedlock (futex, abstime, newval);
161
162 return result;
163}
164#define lll_mutex_timedlock(futex, abstime) \
165 __lll_mutex_timedlock (&(futex), abstime)
166
167
168static inline void
169__attribute__ ((always_inline))
170__lll_mutex_unlock (int *futex)
171{
172 int oldval;
173 int newval;
174
175 lll_compare_and_swap (futex, oldval, newval, "slr %2,%2");
176 if (oldval > 1)
177 lll_futex_wake (futex, 1);
178}
284bdc42
UD
179#define lll_mutex_unlock(futex) \
180 __lll_mutex_unlock(&(futex))
181
182#define lll_mutex_unlock_force(futex) \
183 lll_futex_wake (&(futex), 1)
a88c9263
UD
184
185#define lll_mutex_islocked(futex) \
186 (futex != 0)
187
188
189/* We have a separate internal lock implementation which is not tied
190 to binary compatibility. */
191
192/* Type for lock object. */
193typedef int lll_lock_t;
194
195/* Initializers for lock. */
196#define LLL_LOCK_INITIALIZER (1)
197#define LLL_LOCK_INITIALIZER_LOCKED (0)
198
199
200extern int lll_unlock_wake_cb (int *__futex) attribute_hidden;
201
202/* The states of a lock are:
203 1 - untaken
204 0 - taken by one user
205 <0 - taken by more users */
206
207
208static inline int
209__attribute__ ((always_inline))
210__lll_trylock (int *futex)
211{
212 unsigned int old;
213
214 __asm __volatile ("cs %0,%3,%1"
215 : "=d" (old), "=Q" (*futex)
216 : "0" (1), "d" (0), "m" (*futex) : "cc" );
217 return old != 1;
218}
219#define lll_trylock(futex) __lll_trylock (&(futex))
220
221
222extern void ___lll_lock (int *, int) attribute_hidden;
223
224static inline void
225__attribute__ ((always_inline))
226__lll_lock (int *futex)
227{
228 int oldval;
229 int newval;
230
231 lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,-1");
232 if (newval < 0)
233 ___lll_lock (futex, newval);
234}
235#define lll_lock(futex) __lll_lock (&(futex))
236
237
238static inline void
239__attribute__ ((always_inline))
240__lll_unlock (int *futex)
241{
242 int oldval;
243 int newval;
244
245 lll_compare_and_swap (futex, oldval, newval, "lhi %2,1");
246 if (oldval < 0)
247 lll_futex_wake (futex, 1);
248}
249#define lll_unlock(futex) __lll_unlock(&(futex))
250
251
252#define lll_islocked(futex) \
253 (futex != 1)
254
255
256/* The kernel notifies a process with uses CLONE_CLEARTID via futex
257 wakeup when the clone terminates. The memory location contains the
258 thread ID while the clone is running and is reset to zero
259 afterwards. */
260static inline void
261__attribute__ ((always_inline))
262__lll_wait_tid (int *ptid)
263{
264 int tid;
265
266 while ((tid = *ptid) != 0)
267 lll_futex_wait (ptid, tid);
268}
269#define lll_wait_tid(tid) __lll_wait_tid(&(tid))
270
271
272extern int ___lll_timedwait_tid (int *, const struct timespec *)
273 attribute_hidden;
274static inline int
275__attribute__ ((always_inline))
276__lll_timedwait_tid (int *ptid, const struct timespec *abstime)
277{
278 if (*ptid == 0)
279 return 0;
280
281 return ___lll_timedwait_tid (ptid, abstime);
282}
283#define lll_timedwait_tid(tid, abstime) __lll_timedwait_tid (&(tid), abstime)
284
285
a88c9263
UD
286/* Conditional variable handling. */
287
288extern void __lll_cond_wait (pthread_cond_t *cond)
289 attribute_hidden;
290extern int __lll_cond_timedwait (pthread_cond_t *cond,
291 const struct timespec *abstime)
292 attribute_hidden;
293extern void __lll_cond_wake (pthread_cond_t *cond)
294 attribute_hidden;
295extern void __lll_cond_broadcast (pthread_cond_t *cond)
296 attribute_hidden;
297
298#define lll_cond_wait(cond) \
299 __lll_cond_wait (cond)
300#define lll_cond_timedwait(cond, abstime) \
301 __lll_cond_timedwait (cond, abstime)
302#define lll_cond_wake(cond) \
303 __lll_cond_wake (cond)
304#define lll_cond_broadcast(cond) \
305 __lll_cond_broadcast (cond)
306
307#endif /* lowlevellock.h */