OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / libpthread / nptl / sysdeps / unix / sysv / linux / arm / lowlevellock.c
1 /* low level locking for pthread library.  Generic futex-using version.
2    Copyright (C) 2003, 2005, 2007 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
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 #include <errno.h>
20 #include <sysdep.h>
21 #include <lowlevellock.h>
22 #include <sys/time.h>
23 #include <tls.h>
24
25 void
26 __lll_lock_wait_private (int *futex)
27 {
28   do
29     {
30       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
31       if (oldval != 0)
32         lll_futex_wait (futex, 2, LLL_PRIVATE);
33     }
34   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
35 }
36
37
38 /* These functions don't get included in libc.so  */
39 #ifdef IS_IN_libpthread
40 void
41 __lll_lock_wait (int *futex, int private)
42 {
43   do
44     {
45       int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1);
46       if (oldval != 0)
47         lll_futex_wait (futex, 2, private);
48     }
49   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
50 }
51
52
53 int
54 __lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
55 {
56   struct timespec rt;
57
58   /* Reject invalid timeouts.  */
59   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
60     return EINVAL;
61
62   /* Upgrade the lock.  */
63   if (atomic_exchange_acq (futex, 2) == 0)
64     return 0;
65
66   do
67     {
68       struct timeval tv;
69
70       /* Get the current time.  */
71       (void) gettimeofday (&tv, NULL);
72
73       /* Compute relative timeout.  */
74       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
75       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
76       if (rt.tv_nsec < 0)
77         {
78           rt.tv_nsec += 1000000000;
79           --rt.tv_sec;
80         }
81
82       /* Already timed out?  */
83       if (rt.tv_sec < 0)
84         return ETIMEDOUT;
85
86       // XYZ: Lost the lock to check whether it was private.
87       lll_futex_timed_wait (futex, 2, &rt, private);
88     }
89   while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0);
90
91   return 0;
92 }
93
94
95 int
96 __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
97 {
98   int tid;
99
100   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
101     return EINVAL;
102
103   /* Repeat until thread terminated.  */
104   while ((tid = *tidp) != 0)
105     {
106       struct timeval tv;
107       struct timespec rt;
108
109       /* Get the current time.  */
110       (void) gettimeofday (&tv, NULL);
111
112       /* Compute relative timeout.  */
113       rt.tv_sec = abstime->tv_sec - tv.tv_sec;
114       rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
115       if (rt.tv_nsec < 0)
116         {
117           rt.tv_nsec += 1000000000;
118           --rt.tv_sec;
119         }
120
121       /* Already timed out?  */
122       if (rt.tv_sec < 0)
123         return ETIMEDOUT;
124
125       /* Wait until thread terminates.  */
126       // XYZ: Lost the lock to check whether it was private.
127       if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
128         return ETIMEDOUT;
129     }
130
131   return 0;
132 }
133 #endif