* 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> 2006-01-03 Ulrich Drepper <drepper@redhat.com>
lio_listio should emit an event for each individual request in 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> 2006-01-03 Ulrich Drepper <drepper@redhat.com>
* sysdeps/pthread/pthread.h [__WORDSIZE==64]: Don't use cast in * 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. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -79,7 +79,11 @@
}) })
/* Returns non-zero if error happened, zero if success. */ /* 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); \ INTERNAL_SYSCALL_DECL (__err); \
long int __ret; \ long int __ret; \
@ -90,16 +94,13 @@
FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ 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 #endif
static inline int static inline int
__attribute__ ((always_inline)) __attribute__ ((always_inline))
__lll_mutex_trylock (int *futex) __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)) #define lll_mutex_trylock(futex) __lll_mutex_trylock (&(futex))
@ -107,7 +108,7 @@ static inline int
__attribute__ ((always_inline)) __attribute__ ((always_inline))
__lll_mutex_cond_trylock (int *futex) __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)) #define lll_mutex_cond_trylock(futex) __lll_mutex_cond_trylock (&(futex))
@ -119,7 +120,7 @@ static inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
__lll_mutex_lock (int *futex) __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)) if (__builtin_expect (val != 0, 0))
__lll_lock_wait (futex); __lll_lock_wait (futex);
@ -131,7 +132,7 @@ static inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
__lll_mutex_cond_lock (int *futex) __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)) if (__builtin_expect (val != 0, 0))
__lll_lock_wait (futex); __lll_lock_wait (futex);
@ -147,7 +148,7 @@ static inline int
__attribute__ ((always_inline)) __attribute__ ((always_inline))
__lll_mutex_timedlock (int *futex, const struct timespec *abstime) __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; int result = 0;
if (__builtin_expect (val != 0, 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) \ #define lll_mutex_unlock(lock) \
((void) ({ \ ((void) ({ \
int *__futex = &(lock); \ int *__futex = &(lock); \
int __val = atomic_exchange_rel (__futex, 0); \ int __val = atomic_exchange_24_rel (__futex, 0); \
if (__builtin_expect (__val > 1, 0)) \ if (__builtin_expect (__val > 1, 0)) \
lll_futex_wake (__futex, 1); \ lll_futex_wake (__futex, 1); \
})) }))
@ -168,7 +169,7 @@ __lll_mutex_timedlock (int *futex, const struct timespec *abstime)
#define lll_mutex_unlock_force(lock) \ #define lll_mutex_unlock_force(lock) \
((void) ({ \ ((void) ({ \
int *__futex = &(lock); \ int *__futex = &(lock); \
(void) atomic_exchange_rel (__futex, 0); \ (void) atomic_exchange_24_rel (__futex, 0); \
lll_futex_wake (__futex, 1); \ 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. /* 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. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -21,6 +21,34 @@
#ifndef _BITS_ATOMIC_H #ifndef _BITS_ATOMIC_H
#define _BITS_ATOMIC_H 1 #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. /* We have no compare and swap, just test and set.
The following implementation contends on 64 global locks The following implementation contends on 64 global locks
per library and assumes no variable will be accessed using atomic.h 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)) \ unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \
& 63; \ & 63; \
do \ do \
__asm ("ldstub %1, %0" \ __asm __volatile ("ldstub %1, %0" \
: "=r" (__old_lock), \ : "=r" (__old_lock), \
"=m" (__sparc32_atomic_locks[__idx]) \ "=m" (__sparc32_atomic_locks[__idx]) \
: "m" (__sparc32_atomic_locks[__idx])); \ : "m" (__sparc32_atomic_locks[__idx]) \
: "memory"); \
while (__old_lock); \ while (__old_lock); \
} \ } \
while (0) while (0)
#define __sparc32_atomic_do_unlock(addr) \ #define __sparc32_atomic_do_unlock(addr) \
do \ 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) 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. */ /* 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_memp = (mem); \
__typeof (*mem) __acev_ret; \ __typeof (*mem) __acev_ret; \
__typeof (*mem) __acev_newval = (newval); \ __typeof (*mem) __acev_newval = (newval); \
@ -68,7 +139,7 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__acev_memp); \ __sparc32_atomic_do_unlock (__acev_memp); \
__acev_ret; }) __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); \ ({ __typeof (mem) __aceb_memp = (mem); \
int __aceb_ret; \ int __aceb_ret; \
__typeof (*mem) __aceb_newval = (newval); \ __typeof (*mem) __aceb_newval = (newval); \
@ -82,4 +153,175 @@ volatile unsigned char __sparc32_atomic_locks[64]
__sparc32_atomic_do_unlock (__aceb_memp); \ __sparc32_atomic_do_unlock (__aceb_memp); \
__aceb_ret; }) __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 */ #endif /* bits/atomic.h */

View File

@ -1,5 +1,5 @@
/* Machine-dependent ELF dynamic relocation inline functions. SPARC version. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or 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_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */
#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ #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. */ /* Return nonzero iff ELF header is compatible with the running host. */
static inline int static inline int
elf_machine_matches_host (const Elf32_Ehdr *ehdr) elf_machine_matches_host (const Elf32_Ehdr *ehdr)

View File

@ -1,5 +1,5 @@
/* Atomic operations. sparcv9 version. /* 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. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -79,6 +79,12 @@ typedef uintmax_t uatomic_max_t;
abort (); \ abort (); \
__oldval; }) __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() \ #define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \ __asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory") " | #StoreLoad | #StoreStore" : : : "memory")

View File

@ -1,5 +1,5 @@
/* Atomic operations. sparc64 version. /* 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. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003. Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
@ -94,6 +94,12 @@ typedef uintmax_t uatomic_max_t;
} \ } \
__oldval; }) __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() \ #define atomic_full_barrier() \
__asm __volatile ("membar #LoadLoad | #LoadStore" \ __asm __volatile ("membar #LoadLoad | #LoadStore" \
" | #StoreLoad | #StoreStore" : : : "memory") " | #StoreLoad | #StoreStore" : : : "memory")

View File

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