Lowlevel lock support for libpthread on Linux/s390.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / s390 / lowlevellock.c
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 #include <errno.h>
21 #include <sysdep.h>
22 #include <lowlevellock.h>
23
24
25 void
26 ___lll_lock (futex, newval)
27      int *futex;
28      int newval;
29 {
30   do
31     {
32       int oldval;
33
34       lll_futex_wait (futex, newval);
35       lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,-1");
36     }
37   while (newval != 0);
38
39   *futex = -1;
40 }
41 hidden_proto (___lll_lock)
42
43
44 /* XXX Should not be in libc.so  */
45 int
46 lll_unlock_wake_cb (futex)
47      int *futex;
48 {
49   int oldval;
50   int newval;
51
52   lll_compare_and_swap (futex, oldval, newval, "lr %2,%1; ahi %2,1");
53   if (oldval < 0)
54     lll_futex_wake (futex, 1);
55   return 0;
56 }
57 hidden_proto (lll_unlock_wake_cb)
58
59
60 /* XXX Should not be in libc.so  */
61 int
62 ___lll_timedwait_tid (ptid, abstime)
63      int *ptid;
64      const struct timespec *abstime;
65 {
66   int tid;
67
68   if (abstime == NULL || abstime->tv_nsec >= 1000000000)
69     return EINVAL;
70
71   /* Repeat until thread terminated.  */
72   while ((tid = *ptid) != 0)
73     {
74       /* Get current time.  */
75       struct timeval tv;
76       gettimeofday (&tv, NULL);
77
78       /* Determine relative timeout.  */
79       struct timespec rt;
80       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
81       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
82       if (rt.tv_nsec < 0)
83         {
84           rt.tv_nsec += 1000000000;
85           rt.tv_sec--;
86         }
87       /* Already timed out?  */
88       if (rt.tv_sec < 0)
89         return ETIMEDOUT;
90
91       /* Wait until thread terminates.  */
92       int err = lll_futex_timed_wait (ptid, tid, &rt);
93
94       /* Woken due to timeout?  */
95       if (err == -ETIMEDOUT)
96         /* Yes.  */
97         return ETIMEDOUT;
98     }
99
100   return 0;
101 }
102
103 hidden_proto (___lll_timedwait_tid)