Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / sparc / sparc32 / sem_wait.c
blob9495e5ea88a7ddaa5c68fea4bb1e7c152b93c731
1 /* sem_wait -- wait on a semaphore. Generic futex-using version.
2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
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.
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.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
20 #include <errno.h>
21 #include <sysdep.h>
22 #include <lowlevellock.h>
23 #include <internaltypes.h>
24 #include <semaphore.h>
26 #include <pthreadP.h>
27 #include <shlib-compat.h>
28 #include <sparc-nptl.h>
30 void
31 attribute_hidden
32 __sem_wait_cleanup (void *arg)
34 struct sparc_new_sem *isem = (struct sparc_new_sem *) arg;
36 if (__atomic_is_v9)
37 atomic_decrement (&isem->nwaiters);
38 else
40 __sparc32_atomic_do_lock24 (&isem->lock);
41 isem->nwaiters--;
42 __sparc32_atomic_do_unlock24 (&isem->lock);
46 /* This is in a seperate function in order to make sure gcc
47 puts the call site into an exception region, and thus the
48 cleanups get properly run. */
49 static int
50 __attribute__ ((noinline))
51 do_futex_wait (struct sparc_new_sem *isem)
53 int err, oldtype = __pthread_enable_asynccancel ();
55 err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
57 __pthread_disable_asynccancel (oldtype);
58 return err;
61 int
62 __new_sem_wait (sem_t *sem)
64 struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
65 int err;
66 int val;
68 if (__atomic_is_v9)
69 val = atomic_decrement_if_positive (&isem->value);
70 else
72 __sparc32_atomic_do_lock24 (&isem->lock);
73 val = isem->value;
74 if (val > 0)
75 isem->value = val - 1;
76 else
77 isem->nwaiters++;
78 __sparc32_atomic_do_unlock24 (&isem->lock);
81 if (val > 0)
82 return 0;
84 if (__atomic_is_v9)
85 atomic_increment (&isem->nwaiters);
86 else
87 /* Already done above while still holding isem->lock. */;
89 pthread_cleanup_push (__sem_wait_cleanup, isem);
91 while (1)
93 err = do_futex_wait(isem);
94 if (err != 0 && err != -EWOULDBLOCK)
96 __set_errno (-err);
97 err = -1;
98 break;
101 if (__atomic_is_v9)
102 val = atomic_decrement_if_positive (&isem->value);
103 else
105 __sparc32_atomic_do_lock24 (&isem->lock);
106 val = isem->value;
107 if (val > 0)
108 isem->value = val - 1;
109 __sparc32_atomic_do_unlock24 (&isem->lock);
112 if (val > 0)
114 err = 0;
115 break;
119 pthread_cleanup_pop (0);
121 if (__atomic_is_v9)
122 atomic_decrement (&isem->nwaiters);
123 else
125 __sparc32_atomic_do_lock24 (&isem->lock);
126 isem->nwaiters--;
127 __sparc32_atomic_do_unlock24 (&isem->lock);
130 return err;
132 versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
135 #if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
137 attribute_compat_text_section
138 __old_sem_wait (sem_t *sem)
140 struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
141 int err;
142 int val;
146 if (__atomic_is_v9)
147 val = atomic_decrement_if_positive (&isem->value);
148 else
150 __sparc32_atomic_do_lock24 (&isem->lock);
151 val = isem->value;
152 if (val > 0)
153 isem->value = val - 1;
154 __sparc32_atomic_do_unlock24 (&isem->lock);
157 if (val > 0)
158 return 0;
160 /* Enable asynchronous cancellation. Required by the standard. */
161 int oldtype = __pthread_enable_asynccancel ();
163 err = lll_futex_wait (&isem->value, 0,
164 isem->private ^ FUTEX_PRIVATE_FLAG);
166 /* Disable asynchronous cancellation. */
167 __pthread_disable_asynccancel (oldtype);
169 while (err == 0 || err == -EWOULDBLOCK);
171 __set_errno (-err);
172 return -1;
175 compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
176 #endif