chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / ports / sysdeps / unix / sysv / linux / hppa / nptl / lowlevellock.c
1 /* low level locking for pthread library.  Generic futex-using version.
2    Copyright (C) 2003, 2007 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #include <errno.h>
22 #include <sysdep.h>
23 #include <lowlevellock.h>
24 #include <sys/time.h>
25
26 void
27 __lll_lock_wait (lll_lock_t *futex, int private)
28 {
29   do
30     {
31       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
32       if (oldval != 0)
33         lll_futex_wait (futex, 2, private);
34     }
35   while (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0);
36 }
37
38 void
39 __lll_lock_wait_private (lll_lock_t *futex)
40 {
41   do
42     {
43       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
44       if (oldval != 0)
45         lll_futex_wait (futex, 2, LLL_PRIVATE);
46     }
47   while (atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0);
48 }
49
50 int
51 __lll_timedlock_wait (lll_lock_t *futex, const struct timespec *abstime, int private)
52 {
53   /* Reject invalid timeouts.  */
54   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
55     return EINVAL;
56
57   do
58     {
59       struct timeval tv;
60       struct timespec rt;
61
62       /* Get the current time.  */
63       (void) __gettimeofday (&tv, NULL);
64
65       /* Compute relative timeout.  */
66       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
67       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
68       if (rt.tv_nsec < 0)
69         {
70           rt.tv_nsec += 1000000000;
71           --rt.tv_sec;
72         }
73
74       /* Already timed out?  */
75       if (rt.tv_sec < 0)
76         return ETIMEDOUT;
77
78       /* Wait.  */
79       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
80       if (oldval != 0)
81         lll_futex_timed_wait (futex, 2, &rt, private);
82     }
83   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
84   return 0;
85 }
86
87
88 /* These don't get included in libc.so  */
89 #ifdef IS_IN_libpthread
90 int
91 lll_unlock_wake_cb (lll_lock_t *futex)
92 {
93   int val = atomic_exchange_rel (futex, 0);
94
95   if (__builtin_expect (val > 1, 0))
96     lll_private_futex_wake (futex, 1);
97   return 0;
98 }
99
100
101 int
102 __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
103 {
104   int tid;
105
106   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
107     return EINVAL;
108
109   /* Repeat until thread terminated.  */
110   while ((tid = *tidp) != 0)
111     {
112       struct timeval tv;
113       struct timespec rt;
114
115       /* Get the current time.  */
116       (void) __gettimeofday (&tv, NULL);
117
118       /* Compute relative timeout.  */
119       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
120       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
121       if (rt.tv_nsec < 0)
122         {
123           rt.tv_nsec += 1000000000;
124           --rt.tv_sec;
125         }
126
127       /* Already timed out?  */
128       if (rt.tv_sec < 0)
129         return ETIMEDOUT;
130
131       /* Wait until thread terminates.  */
132       if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
133         return ETIMEDOUT;
134     }
135
136   return 0;
137 }
138
139 #endif
140