]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/sparc/sparc32/sem_wait.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / sparc / sparc32 / sem_wait.c
CommitLineData
e4720b0e 1/* sem_wait -- wait on a semaphore. Generic futex-using version.
b168057a 2 Copyright (C) 2003-2015 Free Software Foundation, Inc.
b01fe5f7
UD
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
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
b01fe5f7
UD
19
20#include <errno.h>
21#include <sysdep.h>
22#include <lowlevellock.h>
23#include <internaltypes.h>
24#include <semaphore.h>
25
26#include <pthreadP.h>
27#include <shlib-compat.h>
7000d82e 28#include <sparc-nptl.h>
b01fe5f7 29
e4720b0e
JJ
30void
31attribute_hidden
32__sem_wait_cleanup (void *arg)
33{
34 struct sparc_new_sem *isem = (struct sparc_new_sem *) arg;
35
36 if (__atomic_is_v9)
37 atomic_decrement (&isem->nwaiters);
38 else
39 {
40 __sparc32_atomic_do_lock24 (&isem->lock);
41 isem->nwaiters--;
42 __sparc32_atomic_do_unlock24 (&isem->lock);
43 }
44}
45
39c4451c
DM
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. */
49static int
50__attribute__ ((noinline))
51do_futex_wait (struct sparc_new_sem *isem)
52{
53 int err, oldtype = __pthread_enable_asynccancel ();
54
55 err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
56
57 __pthread_disable_asynccancel (oldtype);
58 return err;
59}
e4720b0e 60
b01fe5f7
UD
61int
62__new_sem_wait (sem_t *sem)
63{
e4720b0e
JJ
64 struct sparc_new_sem *isem = (struct sparc_new_sem *) sem;
65 int err;
66 int val;
67
68 if (__atomic_is_v9)
69 val = atomic_decrement_if_positive (&isem->value);
70 else
71 {
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);
79 }
80
81 if (val > 0)
82 return 0;
83
84 if (__atomic_is_v9)
85 atomic_increment (&isem->nwaiters);
86 else
87 /* Already done above while still holding isem->lock. */;
88
89 pthread_cleanup_push (__sem_wait_cleanup, isem);
90
91 while (1)
92 {
39c4451c 93 err = do_futex_wait(isem);
e4720b0e
JJ
94 if (err != 0 && err != -EWOULDBLOCK)
95 {
96 __set_errno (-err);
97 err = -1;
98 break;
99 }
100
101 if (__atomic_is_v9)
102 val = atomic_decrement_if_positive (&isem->value);
103 else
104 {
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);
110 }
111
112 if (val > 0)
113 {
114 err = 0;
115 break;
116 }
117 }
118
119 pthread_cleanup_pop (0);
b01fe5f7 120
e4720b0e
JJ
121 if (__atomic_is_v9)
122 atomic_decrement (&isem->nwaiters);
123 else
124 {
125 __sparc32_atomic_do_lock24 (&isem->lock);
126 isem->nwaiters--;
127 __sparc32_atomic_do_unlock24 (&isem->lock);
128 }
129
130 return err;
131}
132versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
133
134
135#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
136int
137attribute_compat_text_section
138__old_sem_wait (sem_t *sem)
139{
140 struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
b01fe5f7 141 int err;
e4720b0e 142 int val;
b01fe5f7
UD
143
144 do
145 {
b01fe5f7 146 if (__atomic_is_v9)
e4720b0e 147 val = atomic_decrement_if_positive (&isem->value);
b01fe5f7
UD
148 else
149 {
e4720b0e
JJ
150 __sparc32_atomic_do_lock24 (&isem->lock);
151 val = isem->value;
b01fe5f7 152 if (val > 0)
e4720b0e
JJ
153 isem->value = val - 1;
154 __sparc32_atomic_do_unlock24 (&isem->lock);
b01fe5f7 155 }
e4720b0e 156
b01fe5f7
UD
157 if (val > 0)
158 return 0;
159
160 /* Enable asynchronous cancellation. Required by the standard. */
161 int oldtype = __pthread_enable_asynccancel ();
162
2313c48f 163 err = lll_futex_wait (&isem->value, 0,
e4720b0e 164 isem->private ^ FUTEX_PRIVATE_FLAG);
b01fe5f7
UD
165
166 /* Disable asynchronous cancellation. */
167 __pthread_disable_asynccancel (oldtype);
168 }
169 while (err == 0 || err == -EWOULDBLOCK);
170
171 __set_errno (-err);
172 return -1;
173}
174
b01fe5f7
UD
175compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
176#endif