1 /* sem_waitcommon -- wait on a semaphore, shared code.
2 Copyright (C) 2003-2016 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/>. */
22 #include <futex-internal.h>
23 #include <internaltypes.h>
24 #include <semaphore.h>
28 #include <shlib-compat.h>
33 __sem_wait_32_finish (struct new_sem
*sem
);
36 __sem_wait_cleanup (void *arg
)
38 struct new_sem
*sem
= (struct new_sem
*) arg
;
40 __sem_wait_32_finish (sem
);
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. */
49 __attribute__ ((noinline
))
50 do_futex_wait (struct new_sem
*sem
, const struct timespec
*abstime
)
54 err
= futex_abstimed_wait_cancelable (&sem
->value
, SEM_NWAITERS_MASK
,
55 abstime
, sem
->private);
60 /* Fast path: Try to grab a token without blocking. */
62 __new_sem_wait_fast (struct new_sem
*sem
, int definitive_result
)
67 __sparc32_atomic_do_lock24(&sem
->pad
);
70 if ((v
>> SEM_VALUE_SHIFT
) == 0)
73 sem
->value
= v
- (1 << SEM_VALUE_SHIFT
);
75 __sparc32_atomic_do_unlock24(&sem
->pad
);
80 /* Slow path that blocks. */
82 __attribute__ ((noinline
))
83 __new_sem_wait_slow (struct new_sem
*sem
, const struct timespec
*abstime
)
88 __sparc32_atomic_do_lock24(&sem
->pad
);
92 pthread_cleanup_push (__sem_wait_cleanup
, sem
);
94 /* Wait for a token to be available. Retry until we can grab one. */
98 if (!(v
& SEM_NWAITERS_MASK
))
99 sem
->value
= v
| SEM_NWAITERS_MASK
;
101 /* If there is no token, wait. */
102 if ((v
>> SEM_VALUE_SHIFT
) == 0)
104 __sparc32_atomic_do_unlock24(&sem
->pad
);
106 err
= do_futex_wait(sem
, abstime
);
107 if (err
== ETIMEDOUT
|| err
== EINTR
)
115 __sparc32_atomic_do_lock24(&sem
->pad
);
117 /* We blocked, so there might be a token now. */
121 /* If there is no token, we must not try to grab one. */
122 while ((v
>> SEM_VALUE_SHIFT
) == 0);
124 sem
->value
= v
- (1 << SEM_VALUE_SHIFT
);
126 __sparc32_atomic_do_unlock24(&sem
->pad
);
129 pthread_cleanup_pop (0);
131 __sem_wait_32_finish (sem
);
136 /* Stop being a registered waiter (non-64b-atomics code only). */
138 __sem_wait_32_finish (struct new_sem
*sem
)
140 __sparc32_atomic_do_lock24(&sem
->pad
);
142 if (--sem
->nwaiters
== 0)
143 sem
->value
&= ~SEM_NWAITERS_MASK
;
145 __sparc32_atomic_do_unlock24(&sem
->pad
);