aboutsummaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorRoland McGrath <roland@hack.frob.com>2014-06-20 17:13:47 -0700
committerRoland McGrath <roland@hack.frob.com>2014-06-20 17:13:47 -0700
commit4b88139b6f22b70048793725a6c3f67bddc7baee (patch)
treec686a38eb7cb9540d217a077a258713f3bf8304f /sysdeps
parent9bc6103d0460686a92105410a306252238d952d8 (diff)
downloadglibc-4b88139b6f22b70048793725a6c3f67bddc7baee.zip
glibc-4b88139b6f22b70048793725a6c3f67bddc7baee.tar.gz
glibc-4b88139b6f22b70048793725a6c3f67bddc7baee.tar.bz2
Move remaining SPARC code out of nptl/.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/sparc/nptl/internaltypes.h35
-rw-r--r--sysdeps/sparc/nptl/pthread_barrier_destroy.c44
-rw-r--r--sysdeps/sparc/nptl/pthread_barrier_init.c54
-rw-r--r--sysdeps/sparc/nptl/pthread_barrier_wait.c77
-rw-r--r--sysdeps/sparc/nptl/sem_init.c92
-rw-r--r--sysdeps/sparc/nptl/sem_post.c69
-rw-r--r--sysdeps/sparc/nptl/sem_timedwait.c116
-rw-r--r--sysdeps/sparc/nptl/sem_wait.c122
-rw-r--r--sysdeps/sparc/sparc32/nptl/lowlevellock.c131
-rw-r--r--sysdeps/sparc/sparc32/nptl/pthread_barrier_wait.c93
-rw-r--r--sysdeps/sparc/sparc32/nptl/sem_post.c84
-rw-r--r--sysdeps/sparc/sparc32/nptl/sem_timedwait.c153
-rw-r--r--sysdeps/sparc/sparc32/nptl/sem_trywait.c58
-rw-r--r--sysdeps/sparc/sparc32/nptl/sem_wait.c176
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/Makefile4
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/cpu_relax.S1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/pthread_barrier_wait.c1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/sem_post.c1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/sem_timedwait.c1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/sem_trywait.c1
-rw-r--r--sysdeps/sparc/sparc32/sparcv9/nptl/sem_wait.c1
-rw-r--r--sysdeps/sparc/sparc64/nptl/cpu_relax.S67
-rw-r--r--sysdeps/unix/sysv/linux/sparc/Makefile5
-rw-r--r--sysdeps/unix/sysv/linux/sparc/Versions8
-rw-r--r--sysdeps/unix/sysv/linux/sparc/aio_cancel.c33
-rw-r--r--sysdeps/unix/sysv/linux/sparc/lowlevellock.h342
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h111
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/Makefile5
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/Versions8
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h109
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c1
35 files changed, 2007 insertions, 0 deletions
diff --git a/sysdeps/sparc/nptl/internaltypes.h b/sysdeps/sparc/nptl/internaltypes.h
new file mode 100644
index 0000000..e5c2740
--- /dev/null
+++ b/sysdeps/sparc/nptl/internaltypes.h
@@ -0,0 +1,35 @@
+#ifndef _INTERNALTYPES_H
+
+#include_next <internaltypes.h>
+
+union sparc_pthread_barrier
+{
+ struct pthread_barrier b;
+ struct sparc_pthread_barrier_s
+ {
+ unsigned int curr_event;
+ int lock;
+ unsigned int left;
+ unsigned int init_count;
+ unsigned char left_lock;
+ unsigned char pshared;
+ } 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/sysdeps/sparc/nptl/pthread_barrier_destroy.c b/sysdeps/sparc/nptl/pthread_barrier_destroy.c
new file mode 100644
index 0000000..2221a27
--- /dev/null
+++ b/sysdeps/sparc/nptl/pthread_barrier_destroy.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2002-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+int
+pthread_barrier_destroy (barrier)
+ pthread_barrier_t *barrier;
+{
+ union sparc_pthread_barrier *ibarrier;
+ int result = EBUSY;
+
+ ibarrier = (union sparc_pthread_barrier *) barrier;
+
+ int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE;
+
+ lll_lock (ibarrier->b.lock, private);
+
+ if (__glibc_likely (ibarrier->b.left == ibarrier->b.init_count))
+ /* The barrier is not used anymore. */
+ result = 0;
+ else
+ /* Still used, return with an error. */
+ lll_unlock (ibarrier->b.lock, private);
+
+ return result;
+}
diff --git a/sysdeps/sparc/nptl/pthread_barrier_init.c b/sysdeps/sparc/nptl/pthread_barrier_init.c
new file mode 100644
index 0000000..6af6863
--- /dev/null
+++ b/sysdeps/sparc/nptl/pthread_barrier_init.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include "pthreadP.h"
+#include <lowlevellock.h>
+
+int
+pthread_barrier_init (barrier, attr, count)
+ pthread_barrier_t *barrier;
+ const pthread_barrierattr_t *attr;
+ unsigned int count;
+{
+ union sparc_pthread_barrier *ibarrier;
+
+ if (__glibc_unlikely (count == 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 = (union 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->s.left_lock = 0;
+ ibarrier->s.pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED);
+
+ return 0;
+}
diff --git a/sysdeps/sparc/nptl/pthread_barrier_wait.c b/sysdeps/sparc/nptl/pthread_barrier_wait.c
new file mode 100644
index 0000000..ed5c1f7
--- /dev/null
+++ b/sysdeps/sparc/nptl/pthread_barrier_wait.c
@@ -0,0 +1,77 @@
+/* Copyright (C) 2003-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthreadP.h>
+
+/* Wait on barrier. */
+int
+pthread_barrier_wait (barrier)
+ pthread_barrier_t *barrier;
+{
+ union sparc_pthread_barrier *ibarrier
+ = (union sparc_pthread_barrier *) barrier;
+ int result = 0;
+ int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE;
+
+ /* Make sure we are alone. */
+ lll_lock (ibarrier->b.lock, private);
+
+ /* 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, private);
+
+ /* 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, private);
+
+ /* Wait for the event counter of the barrier to change. */
+ do
+ lll_futex_wait (&ibarrier->b.curr_event, event, private);
+ 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_increment_val (&ibarrier->b.left) == init_count)
+ /* We are done. */
+ lll_unlock (ibarrier->b.lock, private);
+
+ return result;
+}
diff --git a/sysdeps/sparc/nptl/sem_init.c b/sysdeps/sparc/nptl/sem_init.c
new file mode 100644
index 0000000..cbefdc4
--- /dev/null
+++ b/sysdeps/sparc/nptl/sem_init.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2002-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <string.h>
+#include <semaphore.h>
+#include <lowlevellock.h>
+#include <shlib-compat.h>
+#include "semaphoreP.h"
+#include <kernel-features.h>
+
+
+int
+__new_sem_init (sem, pshared, value)
+ sem_t *sem;
+ int pshared;
+ unsigned int value;
+{
+ /* Parameter sanity check. */
+ if (__glibc_unlikely (value > SEM_VALUE_MAX))
+ {
+ __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
+attribute_compat_text_section
+__old_sem_init (sem, pshared, value)
+ sem_t *sem;
+ int pshared;
+ unsigned int value;
+{
+ /* Parameter sanity check. */
+ if (__glibc_unlikely (value > SEM_VALUE_MAX))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ /* Map to the internal type. */
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
+
+ /* Use the value 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;
+}
+compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
+#endif
diff --git a/sysdeps/sparc/nptl/sem_post.c b/sysdeps/sparc/nptl/sem_post.c
new file mode 100644
index 0000000..d83b9d8
--- /dev/null
+++ b/sysdeps/sparc/nptl/sem_post.c
@@ -0,0 +1,69 @@
+/* sem_post -- post to a POSIX semaphore. SPARC version.
+ Copyright (C) 2003-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ atomic_increment (&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 err;
+
+ atomic_increment (&isem->value);
+ 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/sysdeps/sparc/nptl/sem_timedwait.c b/sysdeps/sparc/nptl/sem_timedwait.c
new file mode 100644
index 0000000..0557e4e
--- /dev/null
+++ b/sysdeps/sparc/nptl/sem_timedwait.c
@@ -0,0 +1,116 @@
+/* sem_timedwait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003-2014 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 <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+/* This is in a seperate function in order to make sure gcc
+ puts the call site into an exception region, and thus the
+ cleanups get properly run. */
+static int
+__attribute__ ((noinline))
+do_futex_timed_wait (struct sparc_new_sem *isem, struct timespec *rt)
+{
+ int err, oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_timed_wait (&isem->value, 0, rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ __pthread_disable_asynccancel (oldtype);
+ return err;
+}
+
+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? */
+ if (sec < 0)
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
+
+ /* Do wait. */
+ rt.tv_sec = sec;
+ rt.tv_nsec = nsec;
+ err = do_futex_timed_wait(isem, &rt);
+ 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/sysdeps/sparc/nptl/sem_wait.c b/sysdeps/sparc/nptl/sem_wait.c
new file mode 100644
index 0000000..cfa1ef3
--- /dev/null
+++ b/sysdeps/sparc/nptl/sem_wait.c
@@ -0,0 +1,122 @@
+/* sem_wait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003-2014 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 <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);
+}
+
+/* This is in a seperate function in order to make sure gcc
+ puts the call site into an exception region, and thus the
+ cleanups get properly run. */
+static int
+__attribute__ ((noinline))
+do_futex_wait (struct sparc_new_sem *isem)
+{
+ int err, oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ __pthread_disable_asynccancel (oldtype);
+ return err;
+}
+
+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)
+ {
+ err = do_futex_wait(isem);
+ 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/sysdeps/sparc/sparc32/nptl/lowlevellock.c b/sysdeps/sparc/sparc32/nptl/lowlevellock.c
new file mode 100644
index 0000000..8384281
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/lowlevellock.c
@@ -0,0 +1,131 @@
+/* low level locking for pthread library. SPARC version.
+ Copyright (C) 2003-2014 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 <lowlevellock.h>
+#include <sys/time.h>
+
+
+void
+__lll_lock_wait_private (int *futex)
+{
+ do
+ {
+ int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
+ if (oldval != 0)
+ lll_futex_wait (futex, 2, LLL_PRIVATE);
+ }
+ while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
+}
+
+
+/* These functions don't get included in libc.so */
+#ifdef IS_IN_libpthread
+void
+__lll_lock_wait (int *futex, int private)
+{
+ do
+ {
+ int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
+ if (oldval != 0)
+ lll_futex_wait (futex, 2, private);
+ }
+ while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
+}
+
+
+int
+__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
+{
+ /* 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, private);
+ }
+ while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
+
+ 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. The kernel so far does not use
+ the private futex operations for this. */
+ if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT)
+ return ETIMEDOUT;
+ }
+
+ return 0;
+}
+#endif
diff --git a/sysdeps/sparc/sparc32/nptl/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/nptl/pthread_barrier_wait.c
new file mode 100644
index 0000000..0fed908
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/pthread_barrier_wait.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2003-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <pthreadP.h>
+
+/* Wait on barrier. */
+int
+pthread_barrier_wait (barrier)
+ pthread_barrier_t *barrier;
+{
+ union sparc_pthread_barrier *ibarrier
+ = (union sparc_pthread_barrier *) barrier;
+ int result = 0;
+ int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE;
+
+ /* Make sure we are alone. */
+ lll_lock (ibarrier->b.lock, private);
+
+ /* 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, private);
+
+ /* 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, private);
+
+ /* Wait for the event counter of the barrier to change. */
+ do
+ lll_futex_wait (&ibarrier->b.curr_event, event, private);
+ 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->s.pshared == 0)
+ {
+ if (atomic_increment_val (&ibarrier->b.left) == init_count)
+ /* We are done. */
+ lll_unlock (ibarrier->b.lock, private);
+ }
+ 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->s.left_lock);
+ left = ++ibarrier->b.left;
+ __sparc32_atomic_do_unlock24 (&ibarrier->s.left_lock);
+ if (left == init_count)
+ /* We are done. */
+ lll_unlock (ibarrier->b.lock, private);
+ }
+
+ return result;
+}
diff --git a/sysdeps/sparc/sparc32/nptl/sem_post.c b/sysdeps/sparc/sparc32/nptl/sem_post.c
new file mode 100644
index 0000000..d3846c0
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/sem_post.c
@@ -0,0 +1,84 @@
+/* sem_post -- post to a POSIX semaphore. SPARC version.
+ Copyright (C) 2003-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#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;
+
+ 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);
+ }
+ 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);
+ return -1;
+ }
+ return 0;
+}
+compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
+#endif
diff --git a/sysdeps/sparc/sparc32/nptl/sem_timedwait.c b/sysdeps/sparc/sparc32/nptl/sem_timedwait.c
new file mode 100644
index 0000000..5c48cb3
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/sem_timedwait.c
@@ -0,0 +1,153 @@
+/* sem_timedwait -- wait on a semaphore. SPARC version.
+ Copyright (C) 2003-2014 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 <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <pthreadP.h>
+#include <shlib-compat.h>
+
+
+extern void __sem_wait_cleanup (void *arg) attribute_hidden;
+
+/* This is in a seperate function in order to make sure gcc
+ puts the call site into an exception region, and thus the
+ cleanups get properly run. */
+static int
+__attribute__ ((noinline))
+do_futex_timed_wait (struct sparc_new_sem *isem, struct timespec *rt)
+{
+ int err, oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_timed_wait (&isem->value, 0, rt,
+ isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ __pthread_disable_asynccancel (oldtype);
+ return err;
+}
+
+int
+sem_timedwait (sem_t *sem, const struct timespec *abstime)
+{
+ 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;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+
+ if (val > 0)
+ return 0;
+
+ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+ {
+ __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);
+ }
+
+ 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? */
+ if (sec < 0)
+ {
+ __set_errno (ETIMEDOUT);
+ err = -1;
+ break;
+ }
+
+ /* Do wait. */
+ rt.tv_sec = sec;
+ rt.tv_nsec = nsec;
+ err = do_futex_timed_wait(isem, &rt);
+ 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);
+
+ 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;
+}
diff --git a/sysdeps/sparc/sparc32/nptl/sem_trywait.c b/sysdeps/sparc/sparc32/nptl/sem_trywait.c
new file mode 100644
index 0000000..7d0fc55
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/sem_trywait.c
@@ -0,0 +1,58 @@
+/* sem_trywait -- wait on a semaphore. SPARC version.
+ Copyright (C) 2003-2014 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 <lowlevellock.h>
+#include <internaltypes.h>
+#include <semaphore.h>
+
+#include <shlib-compat.h>
+
+
+int
+__new_sem_trywait (sem_t *sem)
+{
+ struct sparc_old_sem *isem = (struct sparc_old_sem *) sem;
+ int val;
+
+ if (isem->value > 0)
+ {
+ 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)
+ 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/sysdeps/sparc/sparc32/nptl/sem_wait.c b/sysdeps/sparc/sparc32/nptl/sem_wait.c
new file mode 100644
index 0000000..8c072fe
--- /dev/null
+++ b/sysdeps/sparc/sparc32/nptl/sem_wait.c
@@ -0,0 +1,176 @@
+/* sem_wait -- wait on a semaphore. Generic futex-using version.
+ Copyright (C) 2003-2014 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 <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;
+
+ if (__atomic_is_v9)
+ atomic_decrement (&isem->nwaiters);
+ else
+ {
+ __sparc32_atomic_do_lock24 (&isem->lock);
+ isem->nwaiters--;
+ __sparc32_atomic_do_unlock24 (&isem->lock);
+ }
+}
+
+/* This is in a seperate function in order to make sure gcc
+ puts the call site into an exception region, and thus the
+ cleanups get properly run. */
+static int
+__attribute__ ((noinline))
+do_futex_wait (struct sparc_new_sem *isem)
+{
+ int err, oldtype = __pthread_enable_asynccancel ();
+
+ err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG);
+
+ __pthread_disable_asynccancel (oldtype);
+ return err;
+}
+
+int
+__new_sem_wait (sem_t *sem)
+{
+ 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)
+ {
+ err = do_futex_wait(isem);
+ 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);
+
+ 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
+ {
+ 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)
+ 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/sysdeps/sparc/sparc32/sparcv9/Makefile b/sysdeps/sparc/sparc32/sparcv9/Makefile
index 7d475b0..36f889e 100644
--- a/sysdeps/sparc/sparc32/sparcv9/Makefile
+++ b/sysdeps/sparc/sparc32/sparcv9/Makefile
@@ -18,3 +18,7 @@ ASFLAGS-.op += -Wa,-Av9a
ASFLAGS-.og += -Wa,-Av9a
ASFLAGS-.oS += -Wa,-Av9a
endif
+
+ifeq ($(subdir), nptl)
+libpthread-routines += cpu_relax
+endif
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/cpu_relax.S b/sysdeps/sparc/sparc32/sparcv9/nptl/cpu_relax.S
new file mode 100644
index 0000000..fa88647
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/cpu_relax.S
@@ -0,0 +1 @@
+#include <sysdeps/sparc/sparc64/nptl/cpu_relax.S>
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/pthread_barrier_wait.c b/sysdeps/sparc/sparc32/sparcv9/nptl/pthread_barrier_wait.c
new file mode 100644
index 0000000..8336f5e
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/pthread_barrier_wait.c
@@ -0,0 +1 @@
+#include <sysdeps/sparc/nptl/pthread_barrier_wait.c>
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/sem_post.c b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_post.c
new file mode 100644
index 0000000..3c4b940
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_post.c
@@ -0,0 +1 @@
+#include <sysdeps/sparc/nptl/sem_post.c>
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/sem_timedwait.c b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_timedwait.c
new file mode 100644
index 0000000..f19b2c5
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_timedwait.c
@@ -0,0 +1 @@
+#include <sysdeps/sparc/nptl/sem_timedwait.c>
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/sem_trywait.c b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_trywait.c
new file mode 100644
index 0000000..80157c5
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_trywait.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/sem_trywait.c>
diff --git a/sysdeps/sparc/sparc32/sparcv9/nptl/sem_wait.c b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_wait.c
new file mode 100644
index 0000000..b6d8287
--- /dev/null
+++ b/sysdeps/sparc/sparc32/sparcv9/nptl/sem_wait.c
@@ -0,0 +1 @@
+#include <sysdeps/sparc/nptl/sem_wait.c>
diff --git a/sysdeps/sparc/sparc64/nptl/cpu_relax.S b/sysdeps/sparc/sparc64/nptl/cpu_relax.S
new file mode 100644
index 0000000..9d45eb7
--- /dev/null
+++ b/sysdeps/sparc/sparc64/nptl/cpu_relax.S
@@ -0,0 +1,67 @@
+/* CPU strand yielding for busy loops.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Contributed by David S. Miller (davem@davemloft.net)
+ This file is part of the GNU C Library.
+
+ 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 <sysdep.h>
+
+ .text
+__cpu_relax_generic:
+ rd %ccr, %g0
+ rd %ccr, %g0
+ rd %ccr, %g0
+ retl
+ nop
+ .size __cpu_relax_generic,.-__cpu_relax_generic
+
+__cpu_relax_pause:
+ wr %g0, 128, %asr27
+ retl
+ nop
+ .size __cpu_relax_pause,.-__cpu_relax_pause
+
+ENTRY(__cpu_relax)
+ .type __cpu_relax, @gnu_indirect_function
+# ifdef SHARED
+ SETUP_PIC_REG_LEAF(o3, o5)
+# endif
+ set HWCAP_SPARC_PAUSE, %o1
+ andcc %o0, %o1, %g0
+ be 1f
+ nop
+# ifdef SHARED
+ sethi %gdop_hix22(__cpu_relax_pause), %o1
+ xor %o1, %gdop_lox10(__cpu_relax_pause), %o1
+# else
+ set __cpu_relax_pause, %o1
+# endif
+ ba 10f
+ nop
+1:
+# ifdef SHARED
+ sethi %gdop_hix22(__cpu_relax_generic), %o1
+ xor %o1, %gdop_lox10(__cpu_relax_generic), %o1
+# else
+ set __cpu_relax_generic, %o1
+# endif
+10:
+# ifdef SHARED
+ add %o3, %o1, %o1
+# endif
+ retl
+ mov %o1, %o0
+END(__cpu_relax)
diff --git a/sysdeps/unix/sysv/linux/sparc/Makefile b/sysdeps/unix/sysv/linux/sparc/Makefile
index 96b783e..e67aecf 100644
--- a/sysdeps/unix/sysv/linux/sparc/Makefile
+++ b/sysdeps/unix/sysv/linux/sparc/Makefile
@@ -11,3 +11,8 @@ endif
ifeq ($(subdir),sysvipc)
sysdep_routines += getshmlba
endif
+
+ifeq ($(subdir),nptl)
+# pull in __syscall_error routine
+libpthread-routines += sysdep
+endif
diff --git a/sysdeps/unix/sysv/linux/sparc/Versions b/sysdeps/unix/sysv/linux/sparc/Versions
index 5d31d1d..4dc1cd7 100644
--- a/sysdeps/unix/sysv/linux/sparc/Versions
+++ b/sysdeps/unix/sysv/linux/sparc/Versions
@@ -30,6 +30,14 @@ libc {
__getshmlba;
}
}
+
+libpthread {
+ GLIBC_2.3.3 {
+ # Changed PTHREAD_STACK_MIN.
+ pthread_attr_setstack; pthread_attr_setstacksize;
+ }
+}
+
librt {
GLIBC_2.3 {
# AIO functions.
diff --git a/sysdeps/unix/sysv/linux/sparc/aio_cancel.c b/sysdeps/unix/sysv/linux/sparc/aio_cancel.c
new file mode 100644
index 0000000..0d6da82
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/aio_cancel.c
@@ -0,0 +1,33 @@
+#include <shlib-compat.h>
+
+#define aio_cancel64 XXX
+#include <aio.h>
+#undef aio_cancel64
+#include <errno.h>
+
+extern __typeof (aio_cancel) __new_aio_cancel;
+extern __typeof (aio_cancel) __old_aio_cancel;
+
+#define aio_cancel __new_aio_cancel
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__new_aio_cancel, __new_aio_cancel64);
+versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3);
+versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3);
+
+#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3)
+
+#undef ECANCELED
+#define aio_cancel __old_aio_cancel
+#define ECANCELED 125
+
+#include <sysdeps/pthread/aio_cancel.c>
+
+#undef aio_cancel
+strong_alias (__old_aio_cancel, __old_aio_cancel64);
+compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1);
+compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1);
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
new file mode 100644
index 0000000..d4ed7a9
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/lowlevellock.h
@@ -0,0 +1,342 @@
+/* Copyright (C) 2003-2014 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _LOWLEVELLOCK_H
+#define _LOWLEVELLOCK_H 1
+
+#include <time.h>
+#include <sys/param.h>
+#include <bits/pthreadtypes.h>
+#include <atomic.h>
+#include <kernel-features.h>
+
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_REQUEUE 3
+#define FUTEX_CMP_REQUEUE 4
+#define FUTEX_WAKE_OP 5
+#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1)
+#define FUTEX_LOCK_PI 6
+#define FUTEX_UNLOCK_PI 7
+#define FUTEX_TRYLOCK_PI 8
+#define FUTEX_WAIT_BITSET 9
+#define FUTEX_WAKE_BITSET 10
+#define FUTEX_WAIT_REQUEUE_PI 11
+#define FUTEX_CMP_REQUEUE_PI 12
+#define FUTEX_PRIVATE_FLAG 128
+#define FUTEX_CLOCK_REALTIME 256
+
+#define FUTEX_BITSET_MATCH_ANY 0xffffffff
+
+
+/* Values for 'private' parameter of locking macros. Yes, the
+ definition seems to be backwards. But it is not. The bit will be
+ reversed before passing to the system call. */
+#define LLL_PRIVATE 0
+#define LLL_SHARED FUTEX_PRIVATE_FLAG
+
+#ifndef __sparc32_atomic_do_lock
+/* Delay in spinlock loop. */
+extern void __cpu_relax (void);
+#define BUSY_WAIT_NOP __cpu_relax ()
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_rtld
+/* In libc.so or ld.so all futexes are private. */
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ ((fl) | FUTEX_PRIVATE_FLAG)
+# else
+# define __lll_private_flag(fl, private) \
+ ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
+# endif
+#else
+# ifdef __ASSUME_PRIVATE_FUTEX
+# define __lll_private_flag(fl, private) \
+ (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
+# else
+# define __lll_private_flag(fl, private) \
+ (__builtin_constant_p (private) \
+ ? ((private) == 0 \
+ ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \
+ : (fl)) \
+ : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \
+ & THREAD_GETMEM (THREAD_SELF, header.private_futex))))
+# endif
+#endif
+
+
+#define lll_futex_wait(futexp, val, private) \
+ lll_futex_timed_wait (futexp, val, NULL, private)
+
+#define lll_futex_timed_wait(futexp, val, timespec, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAIT, private), \
+ (val), (timespec)); \
+ __ret; \
+ })
+
+#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ int __op = FUTEX_WAIT_BITSET | clockbit; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), NULL /* Unused. */, \
+ FUTEX_BITSET_MATCH_ANY); \
+ __ret; \
+ })
+
+#define lll_futex_wake(futexp, nr, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \
+ __lll_private_flag (FUTEX_WAKE, private), \
+ (nr), 0); \
+ __ret; \
+ })
+
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE, private),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+#define lll_robust_dead(futexv, private) \
+ do \
+ { \
+ int *__futexp = &(futexv); \
+ atomic_or (__futexp, FUTEX_OWNER_DIED); \
+ lll_futex_wake (__futexp, 1, private); \
+ } \
+ while (0)
+
+/* Returns non-zero if error happened, zero if success. */
+#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, private) 1
+#else
+# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_WAKE_OP, private), \
+ (nr_wake), (nr_wake2), (futexp2), \
+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+#endif
+
+/* Priority Inheritance support. */
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
+ mutex, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), mutex); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \
+ })
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+static inline int
+__attribute__ ((always_inline))
+__lll_trylock (int *futex)
+{
+ return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0;
+}
+#define lll_trylock(futex) __lll_trylock (&(futex))
+
+static inline int
+__attribute__ ((always_inline))
+__lll_cond_trylock (int *futex)
+{
+ return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0;
+}
+#define lll_cond_trylock(futex) __lll_cond_trylock (&(futex))
+
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_trylock (int *futex, int id)
+{
+ return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0;
+}
+#define lll_robust_trylock(futex, id) \
+ __lll_robust_trylock (&(futex), id)
+
+
+extern void __lll_lock_wait_private (int *futex) attribute_hidden;
+extern void __lll_lock_wait (int *futex, int private) attribute_hidden;
+extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden;
+
+static inline void
+__attribute__ ((always_inline))
+__lll_lock (int *futex, int private)
+{
+ int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
+
+ if (__glibc_unlikely (val != 0))
+ {
+ if (__builtin_constant_p (private) && private == LLL_PRIVATE)
+ __lll_lock_wait_private (futex);
+ else
+ __lll_lock_wait (futex, private);
+ }
+}
+#define lll_lock(futex, private) __lll_lock (&(futex), private)
+
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_lock (int *futex, int id, int private)
+{
+ int result = 0;
+ if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+ result = __lll_robust_lock_wait (futex, private);
+ return result;
+}
+#define lll_robust_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), id, private)
+
+static inline void
+__attribute__ ((always_inline))
+__lll_cond_lock (int *futex, int private)
+{
+ int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0);
+
+ if (__glibc_unlikely (val != 0))
+ __lll_lock_wait (futex, private);
+}
+#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private)
+
+#define lll_robust_cond_lock(futex, id, private) \
+ __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private)
+
+
+extern int __lll_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *,
+ int private) attribute_hidden;
+
+static inline int
+__attribute__ ((always_inline))
+__lll_timedlock (int *futex, const struct timespec *abstime, int private)
+{
+ int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
+ int result = 0;
+
+ if (__glibc_unlikely (val != 0))
+ result = __lll_timedlock_wait (futex, abstime, private);
+ return result;
+}
+#define lll_timedlock(futex, abstime, private) \
+ __lll_timedlock (&(futex), abstime, private)
+
+static inline int
+__attribute__ ((always_inline))
+__lll_robust_timedlock (int *futex, const struct timespec *abstime,
+ int id, int private)
+{
+ int result = 0;
+ if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0)
+ result = __lll_robust_timedlock_wait (futex, abstime, private);
+ return result;
+}
+#define lll_robust_timedlock(futex, abstime, id, private) \
+ __lll_robust_timedlock (&(futex), abstime, id, private)
+
+#define lll_unlock(lock, private) \
+ ((void) ({ \
+ int *__futex = &(lock); \
+ int __val = atomic_exchange_24_rel (__futex, 0); \
+ if (__glibc_unlikely (__val > 1)) \
+ lll_futex_wake (__futex, 1, private); \
+ }))
+
+#define lll_robust_unlock(lock, private) \
+ ((void) ({ \
+ int *__futex = &(lock); \
+ int __val = atomic_exchange_rel (__futex, 0); \
+ if (__glibc_unlikely (__val & FUTEX_WAITERS)) \
+ lll_futex_wake (__futex, 1, private); \
+ }))
+
+#define lll_islocked(futex) \
+ (futex != 0)
+
+/* Initializers for lock. */
+#define LLL_LOCK_INITIALIZER (0)
+#define LLL_LOCK_INITIALIZER_LOCKED (1)
+
+/* The kernel notifies a process which uses CLONE_CHILD_CLEARTID via futex
+ wakeup when the clone terminates. The memory location contains the
+ thread ID while the clone is running and is reset to zero
+ afterwards. */
+#define lll_wait_tid(tid) \
+ do \
+ { \
+ __typeof (tid) __tid; \
+ while ((__tid = (tid)) != 0) \
+ lll_futex_wait (&(tid), __tid, LLL_SHARED); \
+ } \
+ while (0)
+
+extern int __lll_timedwait_tid (int *, const struct timespec *)
+ attribute_hidden;
+
+#define lll_timedwait_tid(tid, abstime) \
+ ({ \
+ int __res = 0; \
+ if ((tid) != 0) \
+ __res = __lll_timedwait_tid (&(tid), (abstime)); \
+ __res; \
+ })
+
+#endif /* lowlevellock.h */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
new file mode 100644
index 0000000..fd9968f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <nptl/pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ .globl __syscall_error; \
+ENTRY(name) \
+ ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
+ cmp %g1, 0; \
+ bne 1f; \
+.type __##syscall_name##_nocancel,@function; \
+.globl __##syscall_name##_nocancel; \
+__##syscall_name##_nocancel: \
+ mov SYS_ify(syscall_name), %g1; \
+ ta 0x10; \
+ bcc 8f; \
+ mov %o7, %g1; \
+ call __syscall_error; \
+ mov %g1, %o7; \
+8: jmpl %o7 + 8, %g0; \
+ nop; \
+.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
+1: save %sp, -96, %sp; \
+ cfi_def_cfa_register(%fp); \
+ cfi_window_save; \
+ cfi_register(%o7, %i7); \
+ CENABLE; \
+ nop; \
+ mov %o0, %l0; \
+ COPY_ARGS_##args \
+ mov SYS_ify(syscall_name), %g1; \
+ ta 0x10; \
+ bcc 1f; \
+ mov %o0, %l1; \
+ CDISABLE; \
+ mov %l0, %o0; \
+ call __syscall_error; \
+ mov %l1, %o0; \
+ b 2f; \
+ mov -1, %l1; \
+1: CDISABLE; \
+ mov %l0, %o0; \
+2: jmpl %i7 + 8, %g0; \
+ restore %g0, %l1, %o0;
+
+
+# ifdef IS_IN_libpthread
+# define CENABLE call __pthread_enable_asynccancel
+# define CDISABLE call __pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+# define CENABLE call __libc_enable_asynccancel
+# define CDISABLE call __libc_disable_asynccancel
+# elif defined IS_IN_librt
+# define CENABLE call __librt_enable_asynccancel
+# define CDISABLE call __librt_disable_asynccancel
+# else
+# error Unsupported library
+# endif
+
+#define COPY_ARGS_0 /* Nothing */
+#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef __ASSEMBLER__
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+# else
+# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined __ASSEMBLER__
+
+# define SINGLE_THREAD_P (1)
+# define NO_CANCELLATION 1
+
+#endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+#endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile b/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
index 715af3d..7ea433f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/Makefile
@@ -7,3 +7,8 @@ LD += -melf64_sparc
ifeq ($(subdir),stdlib)
sysdep_routines += __start_context
endif
+
+ifeq ($(subdir),nptl)
+CFLAGS-pause.c += -fexceptions
+CFLAGS-sigsuspend.c += -fexceptions
+endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/Versions b/sysdeps/unix/sysv/linux/sparc/sparc64/Versions
index cfcc15b..fbea1bb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/Versions
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/Versions
@@ -9,3 +9,11 @@ libc {
wordexp;
}
}
+
+librt {
+ GLIBC_2.3.3 {
+ # Changed timer_t.
+ timer_create; timer_delete; timer_getoverrun; timer_gettime;
+ timer_settime;
+ }
+}
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
new file mode 100644
index 0000000..4dad994
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+#include <tls.h>
+#ifndef __ASSEMBLER__
+# include <nptl/pthreadP.h>
+#endif
+
+#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt
+
+# undef PSEUDO
+# define PSEUDO(name, syscall_name, args) \
+ .text; \
+ .globl __syscall_error; \
+ENTRY(name) \
+ ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\
+ brnz,pn %g1, 1f; \
+.type __##syscall_name##_nocancel,@function; \
+.globl __##syscall_name##_nocancel; \
+__##syscall_name##_nocancel: \
+ mov SYS_ify(syscall_name), %g1; \
+ ta 0x6d; \
+ bcc,pt %xcc, 8f; \
+ mov %o7, %g1; \
+ call __syscall_error; \
+ mov %g1, %o7; \
+8: jmpl %o7 + 8, %g0; \
+ nop; \
+.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\
+1: save %sp, -192, %sp; \
+ cfi_def_cfa_register(%fp); \
+ cfi_window_save; \
+ cfi_register(%o7, %i7); \
+ CENABLE; \
+ nop; \
+ mov %o0, %l0; \
+ COPY_ARGS_##args \
+ mov SYS_ify(syscall_name), %g1; \
+ ta 0x6d; \
+ bcc,pt %xcc, 1f; \
+ mov %o0, %l1; \
+ CDISABLE; \
+ mov %l0, %o0; \
+ call __syscall_error; \
+ mov %l1, %o0; \
+ ba,pt %xcc, 2f; \
+ mov -1, %l1; \
+1: CDISABLE; \
+ mov %l0, %o0; \
+2: jmpl %i7 + 8, %g0; \
+ restore %g0, %l1, %o0;
+
+# ifdef IS_IN_libpthread
+# define CENABLE call __pthread_enable_asynccancel
+# define CDISABLE call __pthread_disable_asynccancel
+# elif !defined NOT_IN_libc
+# define CENABLE call __libc_enable_asynccancel
+# define CDISABLE call __libc_disable_asynccancel
+# elif defined IS_IN_librt
+# define CENABLE call __librt_enable_asynccancel
+# define CDISABLE call __librt_disable_asynccancel
+# else
+# error Unsupported library
+# endif
+
+#define COPY_ARGS_0 /* Nothing */
+#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0;
+#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1;
+#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2;
+#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3;
+#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4;
+#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5;
+
+# ifndef __ASSEMBLER__
+# define SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+# else
+# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1
+# endif
+
+#elif !defined __ASSEMBLER__
+
+# define SINGLE_THREAD_P (1)
+# define NO_CANCELLATION 1
+
+#endif
+
+#ifndef __ASSEMBLER__
+# define RTLD_SINGLE_THREAD_P \
+ __builtin_expect (THREAD_GETMEM (THREAD_SELF, \
+ header.multiple_threads) == 0, 1)
+#endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c
new file mode 100644
index 0000000..d307135
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/x86_64/timer_create.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c
new file mode 100644
index 0000000..2dd94f5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/x86_64/timer_delete.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c
new file mode 100644
index 0000000..22eaff5
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c
new file mode 100644
index 0000000..cea524b
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/x86_64/timer_gettime.c>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c
new file mode 100644
index 0000000..fa23114
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c
@@ -0,0 +1 @@
+#include <sysdeps/unix/sysv/linux/x86_64/timer_settime.c>