diff options
Diffstat (limited to 'REORG.TODO/sysdeps/sparc/sparc32/sem_waitcommon.c')
-rw-r--r-- | REORG.TODO/sysdeps/sparc/sparc32/sem_waitcommon.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/sparc/sparc32/sem_waitcommon.c b/REORG.TODO/sysdeps/sparc/sparc32/sem_waitcommon.c new file mode 100644 index 0000000000..08fd12ce50 --- /dev/null +++ b/REORG.TODO/sysdeps/sparc/sparc32/sem_waitcommon.c @@ -0,0 +1,146 @@ +/* sem_waitcommon -- wait on a semaphore, shared code. + Copyright (C) 2003-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <sysdep.h> +#include <futex-internal.h> +#include <internaltypes.h> +#include <semaphore.h> +#include <sys/time.h> + +#include <pthreadP.h> +#include <shlib-compat.h> +#include <atomic.h> + + +static void +__sem_wait_32_finish (struct new_sem *sem); + +static void +__sem_wait_cleanup (void *arg) +{ + struct new_sem *sem = (struct new_sem *) arg; + + __sem_wait_32_finish (sem); +} + +/* Wait until at least one token is available, possibly with a timeout. + This is in a separate function in order to make sure gcc + puts the call site into an exception region, and thus the + cleanups get properly run. TODO still necessary? Other futex_wait + users don't seem to need it. */ +static int +__attribute__ ((noinline)) +do_futex_wait (struct new_sem *sem, const struct timespec *abstime) +{ + int err; + + err = futex_abstimed_wait_cancelable (&sem->value, SEM_NWAITERS_MASK, + abstime, sem->private); + + return err; +} + +/* Fast path: Try to grab a token without blocking. */ +static int +__new_sem_wait_fast (struct new_sem *sem, int definitive_result) +{ + unsigned int v; + int ret = 0; + + __sparc32_atomic_do_lock24(&sem->pad); + + v = sem->value; + if ((v >> SEM_VALUE_SHIFT) == 0) + ret = -1; + else + sem->value = v - (1 << SEM_VALUE_SHIFT); + + __sparc32_atomic_do_unlock24(&sem->pad); + + return ret; +} + +/* Slow path that blocks. */ +static int +__attribute__ ((noinline)) +__new_sem_wait_slow (struct new_sem *sem, const struct timespec *abstime) +{ + unsigned int v; + int err = 0; + + __sparc32_atomic_do_lock24(&sem->pad); + + sem->nwaiters++; + + pthread_cleanup_push (__sem_wait_cleanup, sem); + + /* Wait for a token to be available. Retry until we can grab one. */ + v = sem->value; + do + { + if (!(v & SEM_NWAITERS_MASK)) + sem->value = v | SEM_NWAITERS_MASK; + + /* If there is no token, wait. */ + if ((v >> SEM_VALUE_SHIFT) == 0) + { + __sparc32_atomic_do_unlock24(&sem->pad); + + err = do_futex_wait(sem, abstime); + if (err == ETIMEDOUT || err == EINTR) + { + __set_errno (err); + err = -1; + goto error; + } + err = 0; + + __sparc32_atomic_do_lock24(&sem->pad); + + /* We blocked, so there might be a token now. */ + v = sem->value; + } + } + /* If there is no token, we must not try to grab one. */ + while ((v >> SEM_VALUE_SHIFT) == 0); + + sem->value = v - (1 << SEM_VALUE_SHIFT); + + __sparc32_atomic_do_unlock24(&sem->pad); + +error: + pthread_cleanup_pop (0); + + __sem_wait_32_finish (sem); + + return err; +} + +/* Stop being a registered waiter (non-64b-atomics code only). */ +static void +__sem_wait_32_finish (struct new_sem *sem) +{ + __sparc32_atomic_do_lock24(&sem->pad); + + if (--sem->nwaiters == 0) + sem->value &= ~SEM_NWAITERS_MASK; + + __sparc32_atomic_do_unlock24(&sem->pad); +} |