diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-01-04 00:20:45 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2006-01-04 00:20:45 +0000 |
commit | b01fe5f792564a4f6606f33f7827b649bdfbd1f4 (patch) | |
tree | 968a10dc426c94e9ad8cbf522d19bd1999761641 /nptl | |
parent | 6d3aff23e2c64b64fe68fe88360185e17b3e936a (diff) | |
download | glibc-b01fe5f792564a4f6606f33f7827b649bdfbd1f4.tar.gz |
* sysdeps/unix/sysv/linux/m68k/fchownat.c: Include string.h.
* sysdeps/sparc/sparc32/dl-machine.h (LD_SO_PRELOAD): Remove unused
define.
* sysdeps/sparc/sparc32/bits/atomic.h: Include stdint.h, add
{,u}atomic*_t typedefs.
(__sparc32_atomic_do_lock): Add __volatile and memory clobber.
(__sparc32_atomic_do_unlock): Add memory barrier.
(__sparc32_atomic_do_lock24, __sparc32_atomic_do_unlock24): Define.
[!SHARED] (__v9_compare_and_exchange_val_32_acq): Define.
(__v7_compare_and_exchange_val_acq, __v7_compare_and_exchange_bool_acq,
__v7_exchange_acq, __v7_exchange_and_add, __v7_exchange_24_rel,
__v7_compare_and_exchange_val_24_acq, __atomic_is_v9,
atomic_exchange_acq, atomic_compare_and_exchange_val_24_acq,
atomic_exchange_24_rel): Define.
[SHARED] (atomic_exchange_and_add): Define.
[!SHARED] (__ATOMIC_HWCAP_SPARC_V9): Define.
[!SHARED] (_dl_hwcap): New weak decl.
* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h (atomic_exchange_24_rel,
atomic_compare_and_exchange_val_24_acq): Define.
* sysdeps/sparc/sparc64/bits/atomic.h (atomic_exchange_24_rel,
atomic_compare_and_exchange_val_24_acq): Define.
Diffstat (limited to 'nptl')
17 files changed, 713 insertions, 12 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index f7a770f15a..65de3506a8 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,36 @@ +2006-01-03 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Remove #error for + sparc-linux configured glibc. + (lll_futex_wake_unlock): Define to 1 for sparc-linux configured glibc. + (__lll_mutex_trylock, __lll_mutex_cond_trylock, __lll_mutex_lock, + __lll_mutex_cond_lock, __lll_mutex_timedlock): Use + atomic_compare_and_exchange_val_24_acq instead of + atomic_compare_and_exchange_val_acq. + (lll_mutex_unlock, lll_mutex_unlock_force): Use atomic_exchange_24_rel + instead of atomic_exchange_rel. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: New file. + 2006-01-03 Ulrich Drepper <drepper@redhat.com> * sysdeps/pthread/pthread.h [__WORDSIZE==64]: Don't use cast in diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h index 8d12db3a16..ad82aa3ea4 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. @@ -79,7 +79,11 @@ }) /* Returns non-zero if error happened, zero if success. */ -#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ +#ifdef __sparc32_atomic_do_lock +/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */ +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1 +#else +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \ ({ \ INTERNAL_SYSCALL_DECL (__err); \ long int __ret; \ @@ -90,16 +94,13 @@ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ }) - -#ifdef __sparc32_atomic_do_lock -#error SPARC < v9 does not support compare and swap which is essential for futex based locking #endif static inline int __attribute__ ((always_inline)) __lll_mutex_trylock (int *futex) { - return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; + return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; } #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex)) @@ -107,7 +108,7 @@ static inline int __attribute__ ((always_inline)) __lll_mutex_cond_trylock (int *futex) { - return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; + return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; } #define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex)) @@ -119,7 +120,7 @@ static inline void __attribute__ ((always_inline)) __lll_mutex_lock (int *futex) { - int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); if (__builtin_expect (val != 0, 0)) __lll_lock_wait (futex); @@ -131,7 +132,7 @@ static inline void __attribute__ ((always_inline)) __lll_mutex_cond_lock (int *futex) { - int val = atomic_compare_and_exchange_val_acq (futex, 2, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); if (__builtin_expect (val != 0, 0)) __lll_lock_wait (futex); @@ -147,7 +148,7 @@ static inline int __attribute__ ((always_inline)) __lll_mutex_timedlock (int *futex, const struct timespec *abstime) { - int val = atomic_compare_and_exchange_val_acq (futex, 1, 0); + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); int result = 0; if (__builtin_expect (val != 0, 0)) @@ -160,7 +161,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime) #define lll_mutex_unlock(lock) \ ((void) ({ \ int *__futex = &(lock); \ - int __val = atomic_exchange_rel (__futex, 0); \ + int __val = atomic_exchange_24_rel (__futex, 0); \ if (__builtin_expect (__val > 1, 0)) \ lll_futex_wake (__futex, 1); \ })) @@ -168,7 +169,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime) #define lll_mutex_unlock_force(lock) \ ((void) ({ \ int *__futex = &(lock); \ - (void) atomic_exchange_rel (__futex, 0); \ + (void) atomic_exchange_24_rel (__futex, 0); \ lll_futex_wake (__futex, 1); \ })) diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c new file mode 100644 index 0000000000..a7611d6a88 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c @@ -0,0 +1,131 @@ +/* low level locking for pthread library. SPARC version. + Copyright (C) 2003, 2006 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <sys/time.h> + + +void +__lll_lock_wait (int *futex) +{ + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + do + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_timed_wait (futex, 2, &rt); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); + + return 0; +} + + +/* These don't get included in libc.so */ +#ifdef IS_IN_libpthread +int +lll_unlock_wake_cb (int *futex) +{ + int val = atomic_exchange_24_rel (futex, 0); + + if (__builtin_expect (val > 1, 0)) + lll_futex_wake (futex, 1); + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. */ + if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} + +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c new file mode 100644 index 0000000000..bbd08d0041 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include "pthreadP.h" +#include <lowlevellock.h> + +struct sparc_pthread_barrier +{ + struct pthread_barrier b; + unsigned char left_lock; + unsigned char pshared; +}; + +int +pthread_barrier_init (barrier, attr, count) + pthread_barrier_t *barrier; + const pthread_barrierattr_t *attr; + unsigned int count; +{ + struct sparc_pthread_barrier *ibarrier; + + if (__builtin_expect (count == 0, 0)) + return EINVAL; + + struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr; + if (iattr != NULL) + { + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) + /* Invalid attribute. */ + return EINVAL; + } + + ibarrier = (struct sparc_pthread_barrier *) barrier; + + /* Initialize the individual fields. */ + ibarrier->b.lock = LLL_LOCK_INITIALIZER; + ibarrier->b.left = count; + ibarrier->b.init_count = count; + ibarrier->b.curr_event = 0; + ibarrier->left_lock = 0; + ibarrier->pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED); + + return 0; +} diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c new file mode 100644 index 0000000000..4dfd11dcbe --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky <schwidefsky@de.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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <pthreadP.h> + +struct sparc_pthread_barrier +{ + struct pthread_barrier b; + unsigned char left_lock; + unsigned char pshared; +}; + +/* Wait on barrier. */ +int +pthread_barrier_wait (barrier) + pthread_barrier_t *barrier; +{ + struct sparc_pthread_barrier *ibarrier + = (struct sparc_pthread_barrier *) barrier; + int result = 0; + + /* Make sure we are alone. */ + lll_lock (ibarrier->b.lock); + + /* One more arrival. */ + --ibarrier->b.left; + + /* Are these all? */ + if (ibarrier->b.left == 0) + { + /* Yes. Increment the event counter to avoid invalid wake-ups and + tell the current waiters that it is their turn. */ + ++ibarrier->b.curr_event; + + /* Wake up everybody. */ + lll_futex_wake (&ibarrier->b.curr_event, INT_MAX); + + /* This is the thread which finished the serialization. */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* The number of the event we are waiting for. The barrier's event + number must be bumped before we continue. */ + unsigned int event = ibarrier->b.curr_event; + + /* Before suspending, make the barrier available to others. */ + lll_unlock (ibarrier->b.lock); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->b.curr_event, event); + while (event == ibarrier->b.curr_event); + } + + /* Make sure the init_count is stored locally or in a register. */ + unsigned int init_count = ibarrier->b.init_count; + + /* If this was the last woken thread, unlock. */ + if (__atomic_is_v9 || ibarrier->pshared == 0) + { + if (atomic_increment_val (&ibarrier->b.left) == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock); + } + else + { + unsigned int left; + /* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val + is only atomic for threads within the same process, not for + multiple processes. */ + __sparc32_atomic_do_lock24 (&ibarrier->left_lock); + left = ++ibarrier->b.left; + __sparc32_atomic_do_unlock24 (&ibarrier->left_lock); + if (left == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock); + } + + return result; +} diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c new file mode 100644 index 0000000000..dffd8c7efa --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <semaphore.h> +#include <lowlevellock.h> +#include <shlib-compat.h> +#include "semaphoreP.h" + +struct sparc_sem +{ + struct sem s; + unsigned char lock; +}; + + +int +__new_sem_init (sem, pshared, value) + sem_t *sem; + int pshared; + unsigned int value; +{ + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + + /* Map to the internal type. */ + struct sparc_sem *isem = (struct sparc_sem *) sem; + + /* Use the value the user provided. */ + isem->s.count = value; + + isem->lock = 0; + + /* We can completely ignore the PSHARED parameter since inter-process + use needs no special preparation. */ + + return 0; +} +versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1); +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_init, __old_sem_init) +compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c new file mode 100644 index 0000000000..be1cc60b11 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c @@ -0,0 +1,54 @@ +/* sem_post -- post to a POSIX semaphore. SPARC version. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <shlib-compat.h> + +int +__new_sem_post (sem_t *sem) +{ + int *futex = (int *) sem, nr; + + if (__atomic_is_v9) + nr = atomic_increment_val (futex); + else + { + __sparc32_atomic_do_lock24 (futex + 1); + nr = ++*futex; + __sparc32_atomic_do_unlock24 (futex + 1); + } + int err = lll_futex_wake (futex, nr); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + return 0; +} +versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_post, __old_sem_post) +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c new file mode 100644 index 0000000000..efcc9e9aa8 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c @@ -0,0 +1,117 @@ +/* sem_timedwait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> +#include <shlib-compat.h> + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + /* First check for cancellation. */ + CANCELLATION_P (THREAD_SELF); + + int *futex = (int *) sem; + int val; + int err; + + if (*futex > 0) + { + if (__atomic_is_v9) + val = atomic_decrement_if_positive (futex); + else + { + __sparc32_atomic_do_lock24 (futex + 1); + val = *futex; + if (val > 0) + *futex = val - 1; + __sparc32_atomic_do_unlock24 (futex + 1); + } + if (val > 0) + return 0; + } + + err = -EINVAL; + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + goto error_return; + + do + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + err = -ETIMEDOUT; + if (sec < 0) + goto error_return; + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (futex, 0, &rt); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + goto error_return; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (futex); + else + { + __sparc32_atomic_do_lock24 (futex + 1); + val = *futex; + if (val > 0) + *futex = val - 1; + __sparc32_atomic_do_unlock24 (futex + 1); + } + } + while (val <= 0); + + return 0; + + error_return: + __set_errno (-err); + return -1; +} diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c new file mode 100644 index 0000000000..429494e257 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c @@ -0,0 +1,59 @@ +/* sem_trywait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <shlib-compat.h> + + +int +__new_sem_trywait (sem_t *sem) +{ + int *futex = (int *) sem; + int val; + + if (*futex > 0) + { + if (__atomic_is_v9) + val = atomic_decrement_if_positive (futex); + else + { + __sparc32_atomic_do_lock24 (futex + 1); + val = *futex; + if (val > 0) + *futex = val - 1; + __sparc32_atomic_do_unlock24 (futex + 1); + } + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_trywait, __old_sem_trywait) +compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c new file mode 100644 index 0000000000..d9fcdcd4ee --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c @@ -0,0 +1,74 @@ +/* sem_wait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <sysdep.h> +#include <lowlevellock.h> +#include <internaltypes.h> +#include <semaphore.h> + +#include <pthreadP.h> +#include <shlib-compat.h> + + +int +__new_sem_wait (sem_t *sem) +{ + /* First check for cancellation. */ + CANCELLATION_P (THREAD_SELF); + + int *futex = (int *) sem; + int err; + + do + { + int val; + if (__atomic_is_v9) + val = atomic_decrement_if_positive (futex); + else + { + __sparc32_atomic_do_lock24 (futex + 1); + val = *futex; + if (val > 0) + *futex = val - 1; + __sparc32_atomic_do_unlock24 (futex + 1); + } + if (val > 0) + return 0; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (futex, 0); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + } + while (err == 0 || err == -EWOULDBLOCK); + + __set_errno (-err); + return -1; +} + +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_wait, __old_sem_wait) +compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c new file mode 100644 index 0000000000..b2b842336e --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c @@ -0,0 +1 @@ +#include "../../../../../../../pthread_barrier_init.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c new file mode 100644 index 0000000000..7613863bba --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c @@ -0,0 +1 @@ +#include "../../../../../../pthread/pthread_barrier_wait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c new file mode 100644 index 0000000000..b2ebc4cbb5 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c @@ -0,0 +1 @@ +#include "../../../../../../../sem_init.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c new file mode 100644 index 0000000000..4a6eac88f5 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c @@ -0,0 +1 @@ +#include "../../../sem_post.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c new file mode 100644 index 0000000000..b2526db02c --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c @@ -0,0 +1 @@ +#include "../../../sem_timedwait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c new file mode 100644 index 0000000000..aae46f725e --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c @@ -0,0 +1 @@ +#include "../../../sem_trywait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c new file mode 100644 index 0000000000..31157f636f --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c @@ -0,0 +1 @@ +#include "../../../sem_wait.c" |