diff options
| author | Austin Foxley <austinf@cetoncorp.com> | 2009-10-17 12:26:24 -0700 | 
|---|---|---|
| committer | Austin Foxley <austinf@cetoncorp.com> | 2009-10-17 12:26:24 -0700 | 
| commit | c68d0fa2d88fc2134a38d99e7e944828384a7671 (patch) | |
| tree | 6596943bd1c77f18d6e49d4153ddd3f3d67b49f5 /libpthread/nptl/sysdeps/unix/sysv/linux/alpha | |
| parent | 9a03e98a3b418f33c347a6023e9320f3a42cb9e4 (diff) | |
| download | uClibc-alpine-c68d0fa2d88fc2134a38d99e7e944828384a7671.tar.bz2 uClibc-alpine-c68d0fa2d88fc2134a38d99e7e944828384a7671.tar.xz | |
libpthread/nptl: core of the "Native Posix Threading Library" for uClibc
targetting arm,sh,i386,mips,sparc for now
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/alpha')
19 files changed, 945 insertions, 0 deletions
| diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 000000000..8c8084079 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction +libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions new file mode 100644 index 000000000..437c4da28 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Versions @@ -0,0 +1,13 @@ +libpthread { +  GLIBC_2.3.3 { +    # Changed PTHREAD_STACK_MIN. +    pthread_attr_setstack; pthread_attr_setstacksize; +  } +} +librt { +  GLIBC_2.3.3 { +    # Changed timer_t. +    timer_create; timer_delete; timer_getoverrun; timer_gettime; +    timer_settime; +  } +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 000000000..e0718780c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,89 @@ +/* Minimum guaranteed maximum values for system limits.  Linux/Alpha version. +   Copyright (C) 1993-1998,2000,2002,2003,2004 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 +   modify it under the terms of the GNU Library General Public License as +   published by the Free Software Foundation; either version 2 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 +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol +   and defines LINK_MAX although filesystems have different maxima.  A +   similar thing is true for OPEN_MAX: the limit can be changed at +   runtime and therefore the macro must not be defined.  Remove this +   after including the header if necessary.  */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information.  */ +#include <linux/limits.h> + +/* Have to remove NR_OPEN?  */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX?  */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX?  */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process.  */ +#define _POSIX_THREAD_KEYS_MAX	128 +/* This is the value this implementation supports.  */ +#define PTHREAD_KEYS_MAX	1024 + +/* Controlling the iterations of destructors for thread-specific data.  */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS	4 +/* Number of iterations this implementation does.  */ +#define PTHREAD_DESTRUCTOR_ITERATIONS	_POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process.  */ +#define _POSIX_THREAD_THREADS_MAX	64 +/* We have no predefined limit on the number of threads.  */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O +   priority level.  */ +#define AIO_PRIO_DELTA_MAX	20 + +/* Minimum size for a thread.  We are free to choose a reasonable value.  */ +#define PTHREAD_STACK_MIN	24576 + +/* Maximum number of timer expiration overruns.  */ +#define DELAYTIMER_MAX	2147483647 + +/* Maximum tty name length.  */ +#define TTY_NAME_MAX		32 + +/* Maximum login name length.  This is arbitrary.  */ +#define LOGIN_NAME_MAX		256 + +/* Maximum host name length.  */ +#define HOST_NAME_MAX		64 + +/* Maximum message queue priority level.  */ +#define MQ_PRIO_MAX		32768 diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h new file mode 100644 index 000000000..0f3bf838e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Machine-specific pthread type layouts.  Alpha version. +   Copyright (C) 2003, 2004, 2005 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 +   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.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#define __SIZEOF_PTHREAD_ATTR_T		56 +#define __SIZEOF_PTHREAD_MUTEX_T	40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T	4 +#define __SIZEOF_PTHREAD_COND_T		48 +#define __SIZEOF_PTHREAD_CONDATTR_T	4 +#define __SIZEOF_PTHREAD_RWLOCK_T	56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T	8 +#define __SIZEOF_PTHREAD_BARRIER_T	32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T	4 + + +/* Thread identifiers.  The structure of the attribute type is +   deliberately not exposed.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is deliberately not exposed.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    unsigned int __nusers; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    int __spins; +    __pthread_list_t __list; +#define __PTHREAD_MUTEX_HAVE_PREV       1 +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling.  The structure of +   the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __futex; +    __extension__ unsigned long long int __total_seq; +    __extension__ unsigned long long int __wakeup_seq; +    __extension__ unsigned long long int __woken_seq; +    void *__mutex; +    unsigned int __nwaiters; +    unsigned int __broadcast_seq; +  } __data; +  char __size[__SIZEOF_PTHREAD_COND_T]; +  __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_CONDATTR_T]; +  int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling.  The +   structure of the attribute type is deliberately not exposed.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __nr_readers; +    unsigned int __readers_wakeup; +    unsigned int __writer_wakeup; +    unsigned int __nr_readers_queued; +    unsigned int __nr_writers_queued; +    int __writer; +    int __pad1; +    unsigned long int __pad2; +    unsigned long int __pad3; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h new file mode 100644 index 000000000..6dadfda20 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h @@ -0,0 +1,37 @@ +/* Machine-specific POSIX semaphore type layouts.  Alpha version. +   Copyright (C) 2003 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 +   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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +# define __SIZEOF_SEM_T	32 + +/* Value returned if `sem_open' failed.  */ +#define SEM_FAILED      ((sem_t *) 0) + +/* Maximum value the semaphore can have.  */ +#define SEM_VALUE_MAX   (2147483647) + + +typedef union +{ +  char __size[__SIZEOF_SEM_T]; +  long int __align; +} sem_t; diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S new file mode 100644 index 000000000..eea1cbeed --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/alpha/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c new file mode 100644 index 000000000..6a51e73da --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2003 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 +   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.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation.	 */ +#include <nptl/sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c new file mode 100644 index 000000000..ca85fc008 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 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 +   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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK()							\ +  INLINE_SYSCALL (clone, 5,						\ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,	\ +		  NULL, NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h new file mode 100644 index 000000000..fd4a7ca4b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -0,0 +1,217 @@ +/* Copyright (C) 2003, 2004 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 +   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 Libr	\ary; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> +#include <atomic.h> +#include <sysdep.h> + + +#define __NR_futex		394 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +/* Initializer for compatibility lock.	*/ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +#define lll_futex_wait(futexp, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +#define lll_futex_timed_wait(futexp, val, timespec) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAIT, (val), (timespec));	      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +#define lll_futex_wake(futexp, nr) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 4,				      \ +			      (futexp), FUTEX_WAKE, (nr), 0);		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret;		      \ +  }) + +/* Returns non-zero if error happened, zero if success.  */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val) \ +  ({									      \ +    INTERNAL_SYSCALL_DECL (__err);					      \ +    long int __ret;							      \ +    __ret = INTERNAL_SYSCALL (futex, __err, 6,				      \ +			      (futexp), FUTEX_CMP_REQUEUE, (nr_wake),	      \ +			      (nr_move), (mutex), (val));		      \ +    INTERNAL_SYSCALL_ERROR_P (__ret, __err);				      \ +  }) + + +static inline int __attribute__((always_inline)) +__lll_mutex_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_mutex_trylock(lock)	__lll_mutex_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_mutex_cond_trylock(int *futex) +{ +  return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_mutex_cond_trylock(lock)	__lll_mutex_cond_trylock (&(lock)) + + +extern void __lll_lock_wait (int *futex) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_mutex_lock(int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_lock(futex) __lll_mutex_lock (&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_cond_lock (int *futex) +{ +  if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) +    __lll_lock_wait (futex); +} +#define lll_mutex_cond_lock(futex) __lll_mutex_cond_lock (&(futex)) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *) +	attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_mutex_timedlock (int *futex, const struct timespec *abstime) +{ +  int result = 0; +  if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) +    result = __lll_timedlock_wait (futex, abstime); +  return result; +} +#define lll_mutex_timedlock(futex, abstime) \ +  __lll_mutex_timedlock (&(futex), abstime) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock (int *futex) +{ +  int val = atomic_exchange_rel (futex, 0); +  if (__builtin_expect (val > 1, 0)) +    lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock(futex) __lll_mutex_unlock(&(futex)) + + +static inline void __attribute__ ((always_inline)) +__lll_mutex_unlock_force (int *futex) +{ +  (void) atomic_exchange_rel (futex, 0); +  lll_futex_wake (futex, 1); +} +#define lll_mutex_unlock_force(futex) __lll_mutex_unlock_force(&(futex)) + + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible +   mutex implementation. */ + +/* Type for lock object.  */ +typedef int lll_lock_t; + +/* Initializers for lock.  */ +#define LLL_LOCK_INITIALIZER		(0) +#define LLL_LOCK_INITIALIZER_LOCKED	(1) + +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + +/* The states of a lock are: +    0  -  untaken +    1  -  taken by one user +   >1  -  taken by more users */ + +#define lll_trylock(lock)	lll_mutex_trylock (lock) +#define lll_lock(lock)		lll_mutex_lock (lock) +#define lll_unlock(lock)	lll_mutex_unlock (lock) +#define lll_islocked(lock)	lll_mutex_islocked (lock) + +/* The kernel notifies a process which uses CLONE_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);	\ +  } 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;						\ +  }) + + +/* Conditional variable handling.  */ + +extern void __lll_cond_wait (pthread_cond_t *cond) +     attribute_hidden; +extern int __lll_cond_timedwait (pthread_cond_t *cond, +				 const struct timespec *abstime) +     attribute_hidden; +extern void __lll_cond_wake (pthread_cond_t *cond) +     attribute_hidden; +extern void __lll_cond_broadcast (pthread_cond_t *cond) +     attribute_hidden; + +#define lll_cond_wait(cond) \ +  __lll_cond_wait (cond) +#define lll_cond_timedwait(cond, abstime) \ +  __lll_cond_timedwait (cond, abstime) +#define lll_cond_wake(cond) \ +  __lll_cond_wake (cond) +#define lll_cond_broadcast(cond) \ +  __lll_cond_broadcast (cond) + +#endif	/* lowlevellock.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S new file mode 100644 index 000000000..ec5d175be --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2003, 2004 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 +   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 <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS						\ +	/* Load the current cached pid value across the vfork.  */	\ +	rduniq;								\ +	ldl	a2, PID_OFFSET(v0);					\ +	mov	v0, a1;							\ +	/* Write back its negation, to indicate that the pid value is	\ +	   uninitialized in the the child, and in the window between	\ +	   here and the point at which we restore the value.  */	\ +	negl	a2, t0;							\ +	stl	t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + +	/* If we're back in the parent, restore the saved pid.  */ +	beq	v0, 1f +	stl	a2, PID_OFFSET(a1) +1:	ret + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c new file mode 100644 index 000000000..79a3c47ae --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2003, 2004 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 +   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 "pthreadP.h" +#include <lowlevellock.h> + + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ +  pthread_once_t *once_control = (pthread_once_t *) arg; + +  *once_control = 0; +  lll_futex_wake (once_control, INT_MAX); +} + +int +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ +  for (;;) +    { +      int oldval; +      int newval; +      int tmp; + +      /* Pseudo code: +	 newval = __fork_generation | 1; +	 oldval = *once_control; +	 if ((oldval & 2) == 0) +	   *once_control = newval; +	 Do this atomically. +      */ +      newval = __fork_generation | 1; +      __asm __volatile ( +		"1:	ldl_l	%0, %2\n" +		"	and	%0, 2, %1\n" +		"	bne	%1, 2f\n" +		"	mov	%3, %1\n" +		"	stl_c	%1, %2\n" +		"	beq	%1, 1b\n" +		"2:	mb" +		: "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) +		: "r" (newval), "m" (*once_control)); + +      /* Check if the initializer has already been done.  */ +      if ((oldval & 2) != 0) +	return 0; + +      /* Check if another thread already runs the initializer.	*/ +      if ((oldval & 1) == 0) +	break; + +      /* Check whether the initializer execution was interrupted by a fork.  */ +      if (oldval != newval) +	break; + +      /* Same generation, some other thread was faster. Wait.  */ +      lll_futex_wait (once_control, oldval); +    } + +  /* This thread is the first here.  Do the initialization. +     Register a cleanup handler so that in case the thread gets +     interrupted the initialization can be restarted.  */ +  pthread_cleanup_push (clear_once_control, once_control); + +  init_routine (); + +  pthread_cleanup_pop (0); + +  /* Add one to *once_control to take the bottom 2 bits from 01 to 10.  */ +  atomic_increment (once_control); + +  /* Wake up all other threads.  */ +  lll_futex_wake (once_control, INT_MAX); + +  return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c new file mode 100644 index 000000000..27fd817e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c @@ -0,0 +1,5 @@ +/* ??? This is an ass-backwards way to do this.  We should simply define +   the acquire/release semantics of atomic_exchange_and_add.  And even if +   we don't do this, we should be using atomic_full_barrier or otherwise.  */ +#define __lll_rel_instr  "mb" +#include "../sem_post.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 000000000..f3f7718e3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2003 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 +   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 <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 + +# ifdef PROF +#  define PSEUDO_PROF				\ +	.set noat;				\ +	lda	AT, _mcount;			\ +	jsr	AT, (AT), _mcount;		\ +	.set at +# else +#  define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END +   besides "ret".  */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)			\ +	.globl name;						\ +	.align 4;						\ +	.type name, @function;					\ +	.usepv name, std;					\ +	cfi_startproc;						\ +__LABEL(name)							\ +	ldgp	gp, 0(pv);					\ +	PSEUDO_PROF;						\ +	PSEUDO_PREPARE_ARGS					\ +	SINGLE_THREAD_P(t0);					\ +	bne	t0, $pseudo_cancel;				\ +	lda	v0, SYS_ify(syscall_name);			\ +	call_pal PAL_callsys;					\ +	bne	a3, SYSCALL_ERROR_LABEL;			\ +__LABEL($pseudo_ret)						\ +	.subsection 2;						\ +__LABEL($pseudo_cancel)						\ +	subq	sp, 64, sp;					\ +	cfi_def_cfa_offset(64);					\ +	stq	ra, 0(sp);					\ +	cfi_offset(ra, -64);					\ +	SAVE_ARGS_##args;					\ +	CENABLE;						\ +	LOAD_ARGS_##args;					\ +	/* Save the CENABLE return value in RA.  That register	\ +	   is preserved across syscall and the real return 	\ +	   address is saved on the stack.  */			\ +	mov	v0, ra;						\ +	lda	v0, SYS_ify(syscall_name);			\ +	call_pal PAL_callsys;					\ +	stq	v0, 8(sp);					\ +	mov	ra, a0;						\ +	bne	a3, $multi_error;				\ +	CDISABLE;						\ +	ldq	ra, 0(sp);					\ +	ldq	v0, 8(sp);					\ +	addq	sp, 64, sp;					\ +	cfi_remember_state;					\ +	cfi_restore(ra);					\ +	cfi_def_cfa_offset(0);					\ +	ret;							\ +	cfi_restore_state;					\ +__LABEL($multi_error)						\ +	CDISABLE;						\ +	ldq	ra, 0(sp);					\ +	ldq	v0, 8(sp);					\ +	addq	sp, 64, sp;					\ +	cfi_restore(ra);					\ +	cfi_def_cfa_offset(0);					\ +__LABEL($syscall_error)						\ +	SYSCALL_ERROR_HANDLER;					\ +	.previous + +# undef PSEUDO_END +# define PSEUDO_END(sym)					\ +	.subsection 2;						\ +	cfi_endproc;						\ +	.size sym, .-sym + +# define SAVE_ARGS_0	/* Nothing.  */ +# define SAVE_ARGS_1	SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2	SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3	SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4	SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5	SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6	SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0	/* Nothing.  */ +# define LOAD_ARGS_1	LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2	LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3	LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4	LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5	LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6	LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +#  define __local_enable_asynccancel	__pthread_enable_asynccancel +#  define __local_disable_asynccancel	__pthread_disable_asynccancel +#  define __local_multiple_threads	__pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define __local_enable_asynccancel	__libc_enable_asynccancel +#  define __local_disable_asynccancel	__libc_disable_asynccancel +#  define __local_multiple_threads	__libc_multiple_threads +# elif defined IS_IN_librt +#  define __local_enable_asynccancel	__librt_enable_asynccancel +#  define __local_disable_asynccancel	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +# ifdef PIC +#  define CENABLE	bsr ra, __local_enable_asynccancel !samegp +#  define CDISABLE	bsr ra, __local_disable_asynccancel !samegp +# else +#  define CENABLE	jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +#  define CDISABLE	jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +#  ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +#   define SINGLE_THREAD_P \ +	__builtin_expect (__local_multiple_threads == 0, 1) +#  elif defined(PIC) +#   define SINGLE_THREAD_P(reg)  ldl reg, __local_multiple_threads(gp) !gprel +#  else +#   define SINGLE_THREAD_P(reg)					\ +	ldah	reg, __local_multiple_threads(gp) !gprelhigh;	\ +	ldl	reg, __local_multiple_threads(reg) !gprellow +#  endif +# else +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P \ +	__builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#  else +#   define SINGLE_THREAD_P(reg)					\ +	call_pal PAL_rduniq;					\ +	ldl reg, MULTIPLE_THREADS_OFFSET($0) +#  endif +# endif + +#else + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c new file mode 100644 index 000000000..172223af3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c new file mode 100644 index 000000000..537516e0a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c new file mode 100644 index 000000000..3f21a73c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c new file mode 100644 index 000000000..a50143adc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c new file mode 100644 index 000000000..37baeffac --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 000000000..f0c39982c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2004 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 +   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 <sysdep.h> +#include <tcb-offsets.h> + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS						\ +	/* Load the current cached pid value across the vfork.  */	\ +	rduniq;								\ +	ldl	a2, PID_OFFSET(v0);					\ +	mov	v0, a1;							\ +	/* If the cached value is initialized (nonzero), then write	\ +	   back its negation, or INT_MIN, to indicate that the pid	\ +	   value is uninitialized in the the child, and in the window	\ +	   between here and the point at which we restore the value.  */ \ +	ldah	t0, -0x8000;						\ +	negl	a2, t1;							\ +	cmovne	a2, t1, t0;						\ +	stl	t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + +	/* If we're back in the parent, restore the saved pid.  */ +	beq	v0, 1f +	stl	a2, PID_OFFSET(a1) +1:	ret + +PSEUDO_END (__vfork) +hidden_def (__vfork) +weak_alias (__vfork, vfork) | 
