* sysdeps/unix/sysv/linux/m68k/fchownat.c: Include string.h.

* sysdeps/sparc/sparc32/dl-machine.h (LD_SO_PRELOAD): Remove unused
	define.

	* sysdeps/sparc/sparc32/bits/atomic.h: Include stdint.h, add
	{,u}atomic*_t typedefs.
	(__sparc32_atomic_do_lock): Add __volatile and memory clobber.
	(__sparc32_atomic_do_unlock): Add memory barrier.
	(__sparc32_atomic_do_lock24, __sparc32_atomic_do_unlock24): Define.
	[!SHARED] (__v9_compare_and_exchange_val_32_acq): Define.
	(__v7_compare_and_exchange_val_acq, __v7_compare_and_exchange_bool_acq,
	__v7_exchange_acq, __v7_exchange_and_add, __v7_exchange_24_rel,
	__v7_compare_and_exchange_val_24_acq, __atomic_is_v9,
	atomic_exchange_acq, atomic_compare_and_exchange_val_24_acq,
	atomic_exchange_24_rel): Define.
	[SHARED] (atomic_exchange_and_add): Define.
	[!SHARED] (__ATOMIC_HWCAP_SPARC_V9): Define.
	[!SHARED] (_dl_hwcap): New weak decl.
	* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h (atomic_exchange_24_rel,
	atomic_compare_and_exchange_val_24_acq): Define.
	* sysdeps/sparc/sparc64/bits/atomic.h (atomic_exchange_24_rel,
	atomic_compare_and_exchange_val_24_acq): Define.
This commit is contained in:
Ulrich Drepper 2006-01-04 00:20:45 +00:00
parent 6d3aff23e2
commit b01fe5f792
23 changed files with 1006 additions and 31 deletions

View File

@ -1,3 +1,29 @@
2006-01-03 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/m68k/fchownat.c: Include string.h.
* sysdeps/sparc/sparc32/dl-machine.h (LD_SO_PRELOAD): Remove unused
define.
* sysdeps/sparc/sparc32/bits/atomic.h: Include stdint.h, add
{,u}atomic*_t typedefs.
(__sparc32_atomic_do_lock): Add __volatile and memory clobber.
(__sparc32_atomic_do_unlock): Add memory barrier.
(__sparc32_atomic_do_lock24, __sparc32_atomic_do_unlock24): Define.
[!SHARED] (__v9_compare_and_exchange_val_32_acq): Define.
(__v7_compare_and_exchange_val_acq, __v7_compare_and_exchange_bool_acq,
__v7_exchange_acq, __v7_exchange_and_add, __v7_exchange_24_rel,
__v7_compare_and_exchange_val_24_acq, __atomic_is_v9,
atomic_exchange_acq, atomic_compare_and_exchange_val_24_acq,
atomic_exchange_24_rel): Define.
[SHARED] (atomic_exchange_and_add): Define.
[!SHARED] (__ATOMIC_HWCAP_SPARC_V9): Define.
[!SHARED] (_dl_hwcap): New weak decl.
* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h (atomic_exchange_24_rel,
atomic_compare_and_exchange_val_24_acq): Define.
* sysdeps/sparc/sparc64/bits/atomic.h (atomic_exchange_24_rel,
atomic_compare_and_exchange_val_24_acq): Define.
2006-01-03 Ulrich Drepper <drepper@redhat.com>
lio_listio should emit an event for each individual request in

View File

@ -1,3 +1,36 @@
2006-01-03 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Remove #error for
sparc-linux configured glibc.
(lll_futex_wake_unlock): Define to 1 for sparc-linux configured glibc.
(__lll_mutex_trylock, __lll_mutex_cond_trylock, __lll_mutex_lock,
__lll_mutex_cond_lock, __lll_mutex_timedlock): Use
atomic_compare_and_exchange_val_24_acq instead of
atomic_compare_and_exchange_val_acq.
(lll_mutex_unlock, lll_mutex_unlock_force): Use atomic_exchange_24_rel
instead of atomic_exchange_rel.
* sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: New
file.
* sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: New
file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c:
New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c:
New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: New file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: New
file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c: New
file.
* sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: New file.
2006-01-03 Ulrich Drepper <drepper@redhat.com>
* sysdeps/pthread/pthread.h [__WORDSIZE==64]: Don't use cast in

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -79,7 +79,11 @@
})
/* Returns non-zero if error happened, zero if success. */
#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
#ifdef __sparc32_atomic_do_lock
/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */
# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) 1
#else
# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2) \
({ \
INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \
@ -90,16 +94,13 @@
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
})
#ifdef __sparc32_atomic_do_lock
#error SPARC < v9 does not support compare and swap which is essential for futex based locking
#endif
static inline int
__attribute__ ((always_inline))
__lll_mutex_trylock (int *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0;
return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0;
}
#define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
@ -107,7 +108,7 @@ static inline int
__attribute__ ((always_inline))
__lll_mutex_cond_trylock (int *futex)
{
return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0;
return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0;
}
#define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
@ -119,7 +120,7 @@ static inline void
__attribute__ ((always_inline))
__lll_mutex_lock (int *futex)
{
int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
if (__builtin_expect (val != 0, 0))
__lll_lock_wait (futex);
@ -131,7 +132,7 @@ static inline void
__attribute__ ((always_inline))
__lll_mutex_cond_lock (int *futex)
{
int val = atomic_compare_and_exchange_val_acq (futex, 2, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0);
if (__builtin_expect (val != 0, 0))
__lll_lock_wait (futex);
@ -147,7 +148,7 @@ static inline int
__attribute__ ((always_inline))
__lll_mutex_timedlock (int *futex, const struct timespec *abstime)
{
int val = atomic_compare_and_exchange_val_acq (futex, 1, 0);
int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0);
int result = 0;
if (__builtin_expect (val != 0, 0))
@ -160,7 +161,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
#define lll_mutex_unlock(lock) \
((void) ({ \
int *__futex = &(lock); \
int __val = atomic_exchange_rel (__futex, 0); \
int __val = atomic_exchange_24_rel (__futex, 0); \
if (__builtin_expect (__val > 1, 0)) \
lll_futex_wake (__futex, 1); \
}))
@ -168,7 +169,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
#define lll_mutex_unlock_force(lock) \
((void) ({ \
int *__futex = &(lock); \
(void) atomic_exchange_rel (__futex, 0); \
(void) atomic_exchange_24_rel (__futex, 0); \
lll_futex_wake (__futex, 1); \
}))

View File

@ -0,0 +1,131 @@
/* low level locking for pthread library. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <sys/time.h>
void
__lll_lock_wait (int *futex)
{
do
{
int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_wait (futex, 2);
}
while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
}
int
__lll_timedlock_wait (int *futex, const struct timespec *abstime)
{
/* Reject invalid timeouts. */
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
do
{
struct timeval tv;
struct timespec rt;
/* Get the current time. */
(void) __gettimeofday (&tv, NULL);
/* Compute relative timeout. */
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (rt.tv_nsec < 0)
{
rt.tv_nsec += 1000000000;
--rt.tv_sec;
}
/* Already timed out? */
if (rt.tv_sec < 0)
return ETIMEDOUT;
/* Wait. */
int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1);
if (oldval != 0)
lll_futex_timed_wait (futex, 2, &rt);
}
while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0);
return 0;
}
/* These don't get included in libc.so */
#ifdef IS_IN_libpthread
int
lll_unlock_wake_cb (int *futex)
{
int val = atomic_exchange_24_rel (futex, 0);
if (__builtin_expect (val > 1, 0))
lll_futex_wake (futex, 1);
return 0;
}
int
__lll_timedwait_tid (int *tidp, const struct timespec *abstime)
{
int tid;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
return EINVAL;
/* Repeat until thread terminated. */
while ((tid = *tidp) != 0)
{
struct timeval tv;
struct timespec rt;
/* Get the current time. */
(void) __gettimeofday (&tv, NULL);
/* Compute relative timeout. */
rt.tv_sec = abstime->tv_sec - tv.tv_sec;
rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (rt.tv_nsec < 0)
{
rt.tv_nsec += 1000000000;
--rt.tv_sec;
}
/* Already timed out? */
if (rt.tv_sec < 0)
return ETIMEDOUT;
/* Wait until thread terminates. */
if (lll_futex_timed_wait (tidp, tid, &rt) == -ETIMEDOUT)
return ETIMEDOUT;
}
return 0;
}
#endif

View File

@ -0,0 +1,62 @@
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include "pthreadP.h"
#include <lowlevellock.h>
struct sparc_pthread_barrier
{
struct pthread_barrier b;
unsigned char left_lock;
unsigned char pshared;
};
int
pthread_barrier_init (barrier, attr, count)
pthread_barrier_t *barrier;
const pthread_barrierattr_t *attr;
unsigned int count;
{
struct sparc_pthread_barrier *ibarrier;
if (__builtin_expect (count == 0, 0))
return EINVAL;
struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr;
if (iattr != NULL)
{
if (iattr->pshared != PTHREAD_PROCESS_PRIVATE
&& __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0))
/* Invalid attribute. */
return EINVAL;
}
ibarrier = (struct sparc_pthread_barrier *) barrier;
/* Initialize the individual fields. */
ibarrier->b.lock = LLL_LOCK_INITIALIZER;
ibarrier->b.left = count;
ibarrier->b.init_count = count;
ibarrier->b.curr_event = 0;
ibarrier->left_lock = 0;
ibarrier->pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED);
return 0;
}

View File

@ -0,0 +1,100 @@
/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <pthreadP.h>
struct sparc_pthread_barrier
{
struct pthread_barrier b;
unsigned char left_lock;
unsigned char pshared;
};
/* Wait on barrier. */
int
pthread_barrier_wait (barrier)
pthread_barrier_t *barrier;
{
struct sparc_pthread_barrier *ibarrier
= (struct sparc_pthread_barrier *) barrier;
int result = 0;
/* Make sure we are alone. */
lll_lock (ibarrier->b.lock);
/* One more arrival. */
--ibarrier->b.left;
/* Are these all? */
if (ibarrier->b.left == 0)
{
/* Yes. Increment the event counter to avoid invalid wake-ups and
tell the current waiters that it is their turn. */
++ibarrier->b.curr_event;
/* Wake up everybody. */
lll_futex_wake (&ibarrier->b.curr_event, INT_MAX);
/* This is the thread which finished the serialization. */
result = PTHREAD_BARRIER_SERIAL_THREAD;
}
else
{
/* The number of the event we are waiting for. The barrier's event
number must be bumped before we continue. */
unsigned int event = ibarrier->b.curr_event;
/* Before suspending, make the barrier available to others. */
lll_unlock (ibarrier->b.lock);
/* Wait for the event counter of the barrier to change. */
do
lll_futex_wait (&ibarrier->b.curr_event, event);
while (event == ibarrier->b.curr_event);
}
/* Make sure the init_count is stored locally or in a register. */
unsigned int init_count = ibarrier->b.init_count;
/* If this was the last woken thread, unlock. */
if (__atomic_is_v9 || ibarrier->pshared == 0)
{
if (atomic_increment_val (&ibarrier->b.left) == init_count)
/* We are done. */
lll_unlock (ibarrier->b.lock);
}
else
{
unsigned int left;
/* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val
is only atomic for threads within the same process, not for
multiple processes. */
__sparc32_atomic_do_lock24 (&ibarrier->left_lock);
left = ++ibarrier->b.left;
__sparc32_atomic_do_unlock24 (&ibarrier->left_lock);
if (left == init_count)
/* We are done. */
lll_unlock (ibarrier->b.lock);
}
return result;
}

View File

@ -0,0 +1,63 @@
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <semaphore.h>
#include <lowlevellock.h>
#include <shlib-compat.h>
#include "semaphoreP.h"
struct sparc_sem
{
struct sem s;
unsigned char lock;
};
int
__new_sem_init (sem, pshared, value)
sem_t *sem;
int pshared;
unsigned int value;
{
/* Parameter sanity check. */
if (__builtin_expect (value > SEM_VALUE_MAX, 0))
{
__set_errno (EINVAL);
return -1;
}
/* Map to the internal type. */
struct sparc_sem *isem = (struct sparc_sem *) sem;
/* Use the value the user provided. */
isem->s.count = value;
isem->lock = 0;
/* We can completely ignore the PSHARED parameter since inter-process
use needs no special preparation. */
return 0;
}
versioned_symbol (libpthread, __new_sem_init, sem_init, GLIBC_2_1);
#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_init, __old_sem_init)
compat_symbol (libpthread, __old_sem_init, sem_init, GLIBC_2_0);
#endif

View File

@ -0,0 +1,54 @@
/* sem_post -- post to a POSIX semaphore. SPARC version.
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <shlib-compat.h>
int
__new_sem_post (sem_t *sem)
{
int *futex = (int *) sem, nr;
if (__atomic_is_v9)
nr = atomic_increment_val (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
nr = ++*futex;
__sparc32_atomic_do_unlock24 (futex + 1);
}
int err = lll_futex_wake (futex, nr);
if (__builtin_expect (err, 0) < 0)
{
__set_errno (-err);
return -1;
}
return 0;
}
versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_post, __old_sem_post)
compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0);
#endif

View File

@ -0,0 +1,117 @@
/* sem_timedwait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
sem_timedwait (sem_t *sem, const struct timespec *abstime)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int val;
int err;
if (*futex > 0)
{
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
}
err = -EINVAL;
if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
goto error_return;
do
{
struct timeval tv;
struct timespec rt;
int sec, nsec;
/* Get the current time. */
__gettimeofday (&tv, NULL);
/* Compute relative timeout. */
sec = abstime->tv_sec - tv.tv_sec;
nsec = abstime->tv_nsec - tv.tv_usec * 1000;
if (nsec < 0)
{
nsec += 1000000000;
--sec;
}
/* Already timed out? */
err = -ETIMEDOUT;
if (sec < 0)
goto error_return;
/* Do wait. */
rt.tv_sec = sec;
rt.tv_nsec = nsec;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_timed_wait (futex, 0, &rt);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
if (err != 0 && err != -EWOULDBLOCK)
goto error_return;
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
}
while (val <= 0);
return 0;
error_return:
__set_errno (-err);
return -1;
}

View File

@ -0,0 +1,59 @@
/* sem_trywait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <shlib-compat.h>
int
__new_sem_trywait (sem_t *sem)
{
int *futex = (int *) sem;
int val;
if (*futex > 0)
{
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
}
__set_errno (EAGAIN);
return -1;
}
versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_trywait, __old_sem_trywait)
compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0);
#endif

View File

@ -0,0 +1,74 @@
/* sem_wait -- wait on a semaphore. SPARC version.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <sysdep.h>
#include <lowlevellock.h>
#include <internaltypes.h>
#include <semaphore.h>
#include <pthreadP.h>
#include <shlib-compat.h>
int
__new_sem_wait (sem_t *sem)
{
/* First check for cancellation. */
CANCELLATION_P (THREAD_SELF);
int *futex = (int *) sem;
int err;
do
{
int val;
if (__atomic_is_v9)
val = atomic_decrement_if_positive (futex);
else
{
__sparc32_atomic_do_lock24 (futex + 1);
val = *futex;
if (val > 0)
*futex = val - 1;
__sparc32_atomic_do_unlock24 (futex + 1);
}
if (val > 0)
return 0;
/* Enable asynchronous cancellation. Required by the standard. */
int oldtype = __pthread_enable_asynccancel ();
err = lll_futex_wait (futex, 0);
/* Disable asynchronous cancellation. */
__pthread_disable_asynccancel (oldtype);
}
while (err == 0 || err == -EWOULDBLOCK);
__set_errno (-err);
return -1;
}
versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1);
#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1)
strong_alias (__new_sem_wait, __old_sem_wait)
compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0);
#endif

View File

@ -0,0 +1 @@
#include "../../../../../../../pthread_barrier_init.c"

View File

@ -0,0 +1 @@
#include "../../../../../../pthread/pthread_barrier_wait.c"

View File

@ -0,0 +1 @@
#include "../../../../../../../sem_init.c"

View File

@ -0,0 +1 @@
#include "../../../sem_post.c"

View File

@ -0,0 +1 @@
#include "../../../sem_timedwait.c"

View File

@ -0,0 +1 @@
#include "../../../sem_trywait.c"

View File

@ -0,0 +1 @@
#include "../../../sem_wait.c"

View File

@ -1,5 +1,5 @@
/* Atomic operations. sparc32 version.
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -21,6 +21,34 @@
#ifndef _BITS_ATOMIC_H
#define _BITS_ATOMIC_H 1
#include <stdint.h>
typedef int8_t atomic8_t;
typedef uint8_t uatomic8_t;
typedef int_fast8_t atomic_fast8_t;
typedef uint_fast8_t uatomic_fast8_t;
typedef int16_t atomic16_t;
typedef uint16_t uatomic16_t;
typedef int_fast16_t atomic_fast16_t;
typedef uint_fast16_t uatomic_fast16_t;
typedef int32_t atomic32_t;
typedef uint32_t uatomic32_t;
typedef int_fast32_t atomic_fast32_t;
typedef uint_fast32_t uatomic_fast32_t;
typedef int64_t atomic64_t;
typedef uint64_t uatomic64_t;
typedef int_fast64_t atomic_fast64_t;
typedef uint_fast64_t uatomic_fast64_t;
typedef intptr_t atomicptr_t;
typedef uintptr_t uatomicptr_t;
typedef intmax_t atomic_max_t;
typedef uintmax_t uatomic_max_t;
/* We have no compare and swap, just test and set.
The following implementation contends on 64 global locks
per library and assumes no variable will be accessed using atomic.h
@ -41,22 +69,65 @@ volatile unsigned char __sparc32_atomic_locks[64]
unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
& 63; \
do \
__asm ("ldstub %1, %0" \
: "=r" (__old_lock), \
"=m" (__sparc32_atomic_locks[__idx]) \
: "m" (__sparc32_atomic_locks[__idx])); \
__asm __volatile ("ldstub %1, %0" \
: "=r" (__old_lock), \
"=m" (__sparc32_atomic_locks[__idx]) \
: "m" (__sparc32_atomic_locks[__idx]) \
: "memory"); \
while (__old_lock); \
} \
while (0)
#define __sparc32_atomic_do_unlock(addr) \
do \
__sparc32_atomic_locks[(((long) addr >> 2) \
^ ((long) addr >> 12)) & 63] = 0; \
{ \
__sparc32_atomic_locks[(((long) addr >> 2) \
^ ((long) addr >> 12)) & 63] = 0; \
__asm __volatile ("" ::: "memory"); \
} \
while (0)
#define __sparc32_atomic_do_lock24(addr) \
do \
{ \
unsigned int __old_lock; \
do \
__asm __volatile ("ldstub %1, %0" \
: "=r" (__old_lock), "=m" (*(addr)) \
: "m" (*(addr)) \
: "memory"); \
while (__old_lock); \
} \
while (0)
#define __sparc32_atomic_do_unlock24(addr) \
do \
{ \
*(char *) (addr) = 0; \
__asm __volatile ("" ::: "memory"); \
} \
while (0)
#ifndef SHARED
# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ \
register __typeof (*(mem)) __acev_tmp __asm ("%g6"); \
register __typeof (mem) __acev_mem __asm ("%g1") = (mem); \
register __typeof (*(mem)) __acev_oldval __asm ("%g5"); \
__acev_tmp = (newval); \
__acev_oldval = (oldval); \
/* .word 0xcde05005 is cas [%g1], %g5, %g6. Can't use cas here though, \
because as will then mark the object file as V8+ arch. */ \
__asm __volatile (".word 0xcde05005" \
: "+r" (__acev_tmp), "=m" (*__acev_mem) \
: "r" (__acev_oldval), "m" (*__acev_mem), \
"r" (__acev_mem)); \
__acev_tmp; })
#endif
/* The only basic operation needed is compare and exchange. */
#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
@ -68,7 +139,7 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ __typeof (mem) __aceb_memp = (mem); \
int __aceb_ret; \
__typeof (*mem) __aceb_newval = (newval); \
@ -82,4 +153,175 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__aceb_memp); \
__aceb_ret; })
#define __v7_exchange_acq(mem, newval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock (__acev_memp); \
__acev_ret = *__acev_memp; \
*__acev_memp = __acev_newval; \
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
#define __v7_exchange_and_add(mem, value) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
\
__sparc32_atomic_do_lock (__acev_memp); \
__acev_ret = *__acev_memp; \
*__acev_memp = __acev_ret + (value); \
__sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; })
/* Special versions, which guarantee that top 8 bits of all values
are cleared and use those bits as the ldstub lock. */
#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock24 (__acev_memp); \
__acev_ret = *__acev_memp & 0xffffff; \
if (__acev_ret == (oldval)) \
*__acev_memp = __acev_newval; \
else \
__sparc32_atomic_do_unlock24 (__acev_memp); \
__asm __volatile ("" ::: "memory"); \
__acev_ret; })
#define __v7_exchange_24_rel(mem, newval) \
({ __typeof (mem) __acev_memp = (mem); \
__typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \
\
__sparc32_atomic_do_lock24 (__acev_memp); \
__acev_ret = *__acev_memp & 0xffffff; \
*__acev_memp = __acev_newval; \
__asm __volatile ("" ::: "memory"); \
__acev_ret; })
#ifdef SHARED
/* When dynamically linked, we assume pre-v9 libraries are only ever
used on pre-v9 CPU. */
# define __atomic_is_v9 0
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
__v7_compare_and_exchange_val_acq (mem, newval, oldval)
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
__v7_compare_and_exchange_bool_acq (mem, newval, oldval)
# define atomic_exchange_acq(mem, newval) \
__v7_exchange_acq (mem, newval)
# define atomic_exchange_and_add(mem, value) \
__v7_exchange_and_add (mem, value)
# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ \
if (sizeof (*mem) != 4) \
abort (); \
__v7_compare_and_exchange_val_24_acq (mem, newval, oldval); })
# define atomic_exchange_24_rel(mem, newval) \
({ \
if (sizeof (*mem) != 4) \
abort (); \
__v7_exchange_24_rel (mem, newval); })
#else
/* In libc.a/libpthread.a etc. we don't know if we'll be run on
pre-v9 or v9 CPU. To be interoperable with dynamically linked
apps on v9 CPUs e.g. with process shared primitives, use cas insn
on v9 CPUs and ldstub on pre-v9. */
/* Avoid <ldsodefs.h> include here. */
extern uint64_t _dl_hwcap __attribute__((weak));
# define __ATOMIC_HWCAP_SPARC_V9 16
# define __atomic_is_v9 \
(__builtin_expect (&_dl_hwcap != 0, 1) \
&& __builtin_expect (_dl_hwcap & __ATOMIC_HWCAP_SPARC_V9, \
__ATOMIC_HWCAP_SPARC_V9))
# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
else \
__acev_wret \
= __v7_compare_and_exchange_val_acq (mem, newval, oldval); \
__acev_wret; })
# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \
({ \
int __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
{ \
__typeof (oldval) __acev_woldval = (oldval); \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, \
__acev_woldval) \
!= __acev_woldval; \
} \
else \
__acev_wret \
= __v7_compare_and_exchange_bool_acq (mem, newval, oldval); \
__acev_wret; })
# define atomic_exchange_rel(mem, newval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
{ \
__typeof (mem) __acev_wmemp = (mem); \
__typeof (*(mem)) __acev_wval = (newval); \
do \
__acev_wret = *__acev_wmemp; \
while (__builtin_expect \
(__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\
__acev_wval, \
__acev_wret) \
!= __acev_wret, 0)); \
} \
else \
__acev_wret = __v7_exchange_acq (mem, newval); \
__acev_wret; })
# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
({ \
__typeof (*mem) __acev_wret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_wret \
= __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\
else \
__acev_wret \
= __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\
__acev_wret; })
# define atomic_exchange_24_rel(mem, newval) \
({ \
__typeof (*mem) __acev_w24ret; \
if (sizeof (*mem) != 4) \
abort (); \
if (__atomic_is_v9) \
__acev_w24ret = atomic_exchange_rel (mem, newval); \
else \
__acev_w24ret = __v7_exchange_24_rel (mem, newval); \
__acev_w24ret; })
#endif
#endif /* bits/atomic.h */

View File

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. SPARC version.
Copyright (C) 1996-2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1996-2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -40,13 +40,6 @@
#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */
/* Use a different preload file when running in 32-bit emulation mode
on a 64-bit host. */
#define LD_SO_PRELOAD ((GLRO(dl_hwcap) & HWCAP_SPARC_V9) \
? "/etc/ld.so.preload32" \
: "/etc/ld.so.preload")
/* Return nonzero iff ELF header is compatible with the running host. */
static inline int
elf_machine_matches_host (const Elf32_Ehdr *ehdr)

View File

@ -1,5 +1,5 @@
/* Atomic operations. sparcv9 version.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -79,6 +79,12 @@ typedef uintmax_t uatomic_max_t;
abort (); \
__oldval; })
#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
#define atomic_exchange_24_rel(mem, newval) \
atomic_exchange_rel (mem, newval)
#define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory")

View File

@ -1,5 +1,5 @@
/* Atomic operations. sparc64 version.
Copyright (C) 2003 Free Software Foundation, Inc.
Copyright (C) 2003, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -94,6 +94,12 @@ typedef uintmax_t uatomic_max_t;
} \
__oldval; })
#define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \
atomic_compare_and_exchange_val_acq (mem, newval, oldval)
#define atomic_exchange_24_rel(mem, newval) \
atomic_exchange_rel (mem, newval)
#define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory")

View File

@ -20,6 +20,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sysdep.h>
#include <sys/syscall.h>