]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/sparc/sparc32/sem_waitcommon.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / sparc / sparc32 / sem_waitcommon.c
CommitLineData
d4abeca5 1/* sem_waitcommon -- wait on a semaphore, shared code.
f7a9f785 2 Copyright (C) 2003-2016 Free Software Foundation, Inc.
d4abeca5
DM
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, see
18 <http://www.gnu.org/licenses/>. */
19
20#include <errno.h>
21#include <sysdep.h>
a2f0363f 22#include <futex-internal.h>
d4abeca5
DM
23#include <internaltypes.h>
24#include <semaphore.h>
25#include <sys/time.h>
26
27#include <pthreadP.h>
28#include <shlib-compat.h>
29#include <atomic.h>
30
d4abeca5
DM
31
32static void
33__sem_wait_32_finish (struct new_sem *sem);
34
35static void
36__sem_wait_cleanup (void *arg)
37{
38 struct new_sem *sem = (struct new_sem *) arg;
39
40 __sem_wait_32_finish (sem);
41}
42
43/* Wait until at least one token is available, possibly with a timeout.
44 This is in a separate function in order to make sure gcc
45 puts the call site into an exception region, and thus the
46 cleanups get properly run. TODO still necessary? Other futex_wait
47 users don't seem to need it. */
48static int
49__attribute__ ((noinline))
50do_futex_wait (struct new_sem *sem, const struct timespec *abstime)
51{
52 int err;
53
a2f0363f
TR
54 err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK,
55 abstime, sem->private);
d4abeca5
DM
56
57 return err;
58}
59
60/* Fast path: Try to grab a token without blocking. */
61static int
62__new_sem_wait_fast (struct new_sem *sem, int definitive_result)
63{
64 unsigned int v;
65 int ret = 0;
66
67 __sparc32_atomic_do_lock24(&sem->pad);
68
69 v = sem->value;
70 if ((v >> SEM_VALUE_SHIFT) == 0)
71 ret = -1;
72 else
73 sem->value = v - (1 << SEM_VALUE_SHIFT);
74
75 __sparc32_atomic_do_unlock24(&sem->pad);
76
77 return ret;
78}
79
80/* Slow path that blocks. */
81static int
82__attribute__ ((noinline))
83__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime)
84{
85 unsigned int v;
86 int err = 0;
87
88 __sparc32_atomic_do_lock24(&sem->pad);
89
90 sem->nwaiters++;
91
92 pthread_cleanup_push (__sem_wait_cleanup, sem);
93
94 /* Wait for a token to be available. Retry until we can grab one. */
95 v = sem->value;
96 do
97 {
98 if (!(v & SEM_NWAITERS_MASK))
99 sem->value = v | SEM_NWAITERS_MASK;
100
101 /* If there is no token, wait. */
102 if ((v >> SEM_VALUE_SHIFT) == 0)
103 {
104 __sparc32_atomic_do_unlock24(&sem->pad);
105
106 err = do_futex_wait(sem, abstime);
a2f0363f 107 if (err == ETIMEDOUT || err == EINTR)
d4abeca5
DM
108 {
109 __set_errno (err);
110 err = -1;
111 goto error;
112 }
113 err = 0;
114
115 __sparc32_atomic_do_lock24(&sem->pad);
116
117 /* We blocked, so there might be a token now. */
118 v = sem->value;
119 }
120 }
121 /* If there is no token, we must not try to grab one. */
122 while ((v >> SEM_VALUE_SHIFT) == 0);
123
124 sem->value = v - (1 << SEM_VALUE_SHIFT);
125
126 __sparc32_atomic_do_unlock24(&sem->pad);
127
128error:
129 pthread_cleanup_pop (0);
130
131 __sem_wait_32_finish (sem);
132
133 return err;
134}
135
136/* Stop being a registered waiter (non-64b-atomics code only). */
137static void
138__sem_wait_32_finish (struct new_sem *sem)
139{
140 __sparc32_atomic_do_lock24(&sem->pad);
141
142 if (--sem->nwaiters == 0)
143 sem->value &= ~SEM_NWAITERS_MASK;
144
145 __sparc32_atomic_do_unlock24(&sem->pad);
146}