diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-08-15 20:47:43 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2007-08-15 20:47:43 +0000 |
commit | e4720b0e594f4599d0256dfb713ddd4d2281ddbc (patch) | |
tree | 361c259b576fbbda177da526e1f248e0c6830749 /nptl/sysdeps/unix/sysv/linux/sparc | |
parent | d13f4a43865051177cb6bb084f64dbc5b62c97c7 (diff) | |
download | glibc-e4720b0e594f4599d0256dfb713ddd4d2281ddbc.tar.gz glibc-e4720b0e594f4599d0256dfb713ddd4d2281ddbc.tar.xz glibc-e4720b0e594f4599d0256dfb713ddd4d2281ddbc.zip |
* sysdeps/sparc/fpu/fraiseexcpt.c (__feraiseexcept): Fix raising cvs/fedora-glibc-20070815T2049
FE_UNDERFLOW on Niagara CPUs. * sysdeps/sparc/fpu/feholdexcpt.c (feholdexcept): Clear all exceptions. * sysdeps/unix/sysv/linux/sparc/internaltypes.h (sparc_new_sem, sparc_old_sem): New structs. * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c (__sem_wait_cleanup): New function. (__new_sem_wait): Use sparc_new_sem structure. Bump and afterwards decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to lll_futex_wait. (__old_sem_wait): New function. * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: Include nptl/sysdeps/unix/sysv/linux/sparc version. * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c (__new_sem_trywait): Use sparc_old_sem structure. * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c (sem_timedwait): Use sparc_new_sem structure. Bump and afterwards decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to lll_futex_timed_wait. * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c (__new_sem_post): Use sparc_new_sem structure. Only wake if nwaiters > 0. Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to lll_futex_wake. (__old_sem_post): New function. * sysdeps/unix/sysv/linux/sparc/sem_wait.c: New file. * sysdeps/unix/sysv/linux/sparc/sem_init.c: New file. * sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: New file. * sysdeps/unix/sysv/linux/sparc/sem_post.c: New file. * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: Remove. * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: Remove. 2007-08-15 Jakub Jelinek <jakub@redhat.com> * sysdeps/sparc/fpu/fraiseexcpt.c (__feraiseexcept): Fix raising FE_UNDERFLOW on Niagara CPUs. * sysdeps/sparc/fpu/feholdexcpt.c (feholdexcept): Clear all exceptions.
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/sparc')
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h | 16 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c (renamed from nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c) | 60 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c | 69 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c | 112 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c | 117 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c | 51 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c | 100 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c | 16 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c | 127 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c | 1 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c | 2 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c | 2 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c | 2 |
13 files changed, 588 insertions, 87 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h index 4d0ea51723..4f400a3fe3 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h @@ -15,4 +15,20 @@ union sparc_pthread_barrier } s; }; +struct sparc_new_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; + unsigned char pad[2]; + unsigned long int nwaiters; +}; + +struct sparc_old_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; +}; + #endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c index dffd8c7efa..840032a08c 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -18,20 +18,50 @@ 02111-1307 USA. */ #include <errno.h> +#include <string.h> #include <semaphore.h> #include <lowlevellock.h> #include <shlib-compat.h> #include "semaphoreP.h" +#include <kernel-features.h> -struct sparc_sem + +int +__new_sem_init (sem, pshared, value) + sem_t *sem; + int pshared; + unsigned int value; { - struct sem s; - unsigned char lock; -}; + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + /* Map to the internal type. */ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + /* Use the values the user provided. */ + memset (isem, '\0', sizeof (*isem)); + isem->value = value; +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + + return 0; +} +versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1); + + + +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) int -__new_sem_init (sem, pshared, value) +attribute_compat_text_section +__old_sem_init (sem, pshared, value) sem_t *sem; int pshared; unsigned int value; @@ -44,20 +74,20 @@ __new_sem_init (sem, pshared, value) } /* Map to the internal type. */ - struct sparc_sem *isem = (struct sparc_sem *) sem; + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; /* Use the value the user provided. */ - isem->s.count = value; - - isem->lock = 0; + memset (isem, '\0', sizeof (*isem)); + isem->value = value; - /* We can completely ignore the PSHARED parameter since inter-process - use needs no special preparation. */ +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif 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/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c new file mode 100644 index 0000000000..95964d0744 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_post.c @@ -0,0 +1,69 @@ +/* sem_post -- post to a POSIX semaphore. SPARC version. + Copyright (C) 2003, 2004, 2007 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) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + + int nr = atomic_increment_val (&isem->value); + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + 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) +int +attribute_compat_text_section +__old_sem_post (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; + + int nr = atomic_increment_val (&isem->value); + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + return 0; +} +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c new file mode 100644 index 0000000000..01952f3f9a --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_timedwait.c @@ -0,0 +1,112 @@ +/* sem_timedwait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 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> + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + 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) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* 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 (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c new file mode 100644 index 0000000000..a846f20601 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sem_wait.c @@ -0,0 +1,117 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 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> + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + + +int +__new_sem_wait (sem_t *sem) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +int +attribute_compat_text_section +__old_sem_wait (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; + int err; + + do + { + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + } + while (err == 0 || err == -EWOULDBLOCK); + + __set_errno (-err); + return -1; +} + +compat_symbol (libpthread, __old_sem_wait, sem_wait, 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 index 527aedfdc7..dbd34f2210 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c @@ -29,19 +29,51 @@ int __new_sem_post (sem_t *sem) { - int *futex = (int *) sem, nr; + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int nr; if (__atomic_is_v9) - nr = atomic_increment_val (futex); + nr = atomic_increment_val (&isem->value); else { - __sparc32_atomic_do_lock24 (futex + 1); - nr = ++*futex; - __sparc32_atomic_do_unlock24 (futex + 1); + __sparc32_atomic_do_lock24 (&isem->lock); + nr = ++(isem->value); + __sparc32_atomic_do_unlock24 (&isem->lock); } - int err = lll_futex_wake (futex, nr, - // XYZ check mutex flag - LLL_SHARED); + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + 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) +int +attribute_compat_text_section +__old_sem_post (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; + int nr; + + if (__atomic_is_v9) + nr = atomic_increment_val (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + nr = ++(isem->value); + __sparc32_atomic_do_unlock24 (&isem->lock); + } + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); if (__builtin_expect (err, 0) < 0) { __set_errno (-err); @@ -49,8 +81,5 @@ __new_sem_post (sem_t *sem) } 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 index efcc9e9aa8..55f3e2e075 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c @@ -1,5 +1,5 @@ /* sem_timedwait -- wait on a semaphore. SPARC version. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -28,37 +28,48 @@ #include <shlib-compat.h> +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + int sem_timedwait (sem_t *sem, const struct timespec *abstime) { - /* First check for cancellation. */ - CANCELLATION_P (THREAD_SELF); - - int *futex = (int *) sem; - int val; + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; int err; + int val; - if (*futex > 0) + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else { - 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); - } + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; if (val > 0) - return 0; + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); } - err = -EINVAL; + if (val > 0) + return 0; + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - goto error_return; + { + __set_errno (EINVAL); + return -1; + } + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } - do + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) { struct timeval tv; struct timespec rt; @@ -79,7 +90,11 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime) /* Already timed out? */ err = -ETIMEDOUT; if (sec < 0) - goto error_return; + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } /* Do wait. */ rt.tv_sec = sec; @@ -88,30 +103,47 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime) /* Enable asynchronous cancellation. Required by the standard. */ int oldtype = __pthread_enable_asynccancel (); - err = lll_futex_timed_wait (futex, 0, &rt); + err = lll_futex_timed_wait (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (oldtype); if (err != 0 && err != -EWOULDBLOCK) - goto error_return; + { + __set_errno (-err); + err = -1; + break; + } if (__atomic_is_v9) - val = atomic_decrement_if_positive (futex); + val = atomic_decrement_if_positive (&isem->value); else { - __sparc32_atomic_do_lock24 (futex + 1); - val = *futex; + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; if (val > 0) - *futex = val - 1; - __sparc32_atomic_do_unlock24 (futex + 1); + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; } } - while (val <= 0); - return 0; + pthread_cleanup_pop (0); + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } - error_return: - __set_errno (-err); - return -1; + return err; } diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c index 429494e257..4db89727a7 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c @@ -1,5 +1,5 @@ /* sem_trywait -- wait on a semaphore. SPARC version. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -30,20 +30,20 @@ int __new_sem_trywait (sem_t *sem) { - int *futex = (int *) sem; + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; int val; - if (*futex > 0) + if (isem->value > 0) { if (__atomic_is_v9) - val = atomic_decrement_if_positive (futex); + val = atomic_decrement_if_positive (&isem->value); else { - __sparc32_atomic_do_lock24 (futex + 1); - val = *futex; + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; if (val > 0) - *futex = val - 1; - __sparc32_atomic_do_unlock24 (futex + 1); + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); } if (val > 0) return 0; diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c index d9fcdcd4ee..3c71c969b8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c @@ -1,5 +1,5 @@ -/* sem_wait -- wait on a semaphore. SPARC version. - Copyright (C) 2003, 2006 Free Software Foundation, Inc. +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -28,35 +28,135 @@ #include <shlib-compat.h> +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) arg; + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } +} + + int __new_sem_wait (sem_t *sem) { - /* First check for cancellation. */ - CANCELLATION_P (THREAD_SELF); + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + int val; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + else + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + return 0; + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + /* Already done above while still holding isem->lock. */; + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); - int *futex = (int *) sem; + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + return err; +} +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +int +attribute_compat_text_section +__old_sem_wait (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; int err; + int val; do { - int val; if (__atomic_is_v9) - val = atomic_decrement_if_positive (futex); + val = atomic_decrement_if_positive (&isem->value); else { - __sparc32_atomic_do_lock24 (futex + 1); - val = *futex; + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; if (val > 0) - *futex = val - 1; - __sparc32_atomic_do_unlock24 (futex + 1); + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); } + if (val > 0) return 0; /* Enable asynchronous cancellation. Required by the standard. */ int oldtype = __pthread_enable_asynccancel (); - err = lll_futex_wait (futex, 0); + err = lll_futex_wait (futex, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); /* Disable asynchronous cancellation. */ __pthread_disable_asynccancel (oldtype); @@ -67,8 +167,5 @@ __new_sem_wait (sem_t *sem) 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/sem_init.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c deleted file mode 100644 index b2ebc4cbb5..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c +++ /dev/null @@ -1 +0,0 @@ -#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 index 4a6eac88f5..73d7c56675 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c @@ -1 +1 @@ -#include "../../../sem_post.c" +#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 index b2526db02c..03945b7279 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c @@ -1 +1 @@ -#include "../../../sem_timedwait.c" +#include "../../sem_timedwait.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 index 31157f636f..a5dbc5a4b8 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c @@ -1 +1 @@ -#include "../../../sem_wait.c" +#include "../../sem_wait.c" |