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/x86_64 | |
| 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/x86_64')
36 files changed, 4217 insertions, 0 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 000000000..b32ce29ef --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,4 @@ +ifeq ($(subdir),nptl) +CFLAGS-pt-initfini.s = -g0 -fPIC -fno-inline-functions \ +		       -fno-asynchronous-unwind-tables $(fno-unit-at-a-time) +endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions new file mode 100644 index 000000000..3b111ddb5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Versions @@ -0,0 +1,7 @@ +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/x86_64/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h new file mode 100644 index 000000000..51fdab0fb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -0,0 +1,209 @@ +/* Copyright (C) 2002, 2003, 2004 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.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# 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 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers.  The structure of the attribute type is not +   exposed on purpose.  */ +typedef unsigned long int pthread_t; + + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_ATTR_T]; +  long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ +  struct __pthread_internal_list *__prev; +  struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct +  { +    int __lock; +    unsigned int __count; +    int __owner; +#if __WORDSIZE == 64 +    unsigned int __nusers; +#endif +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +#if __WORDSIZE != 64 +    unsigned int __nusers; +#endif +    int __spins; +  } __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 not exposed on purpose.  */ +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 not exposed on purpose.  */ +typedef union +{ +# if __WORDSIZE == 64 +  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; +# else +  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; +    /* FLAGS must stay at this position in the structure to maintain +       binary compatibility.  */ +    unsigned int __flags; +    int __writer; +  } __data; +# endif +  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/x86_64/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h new file mode 100644 index 000000000..57edbbbfb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2002, 2004 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.  */ + +#ifndef _SEMAPHORE_H +# error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." +#endif + +#include <bits/wordsize.h> + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T	32 +#else +# define __SIZEOF_SEM_T	16 +#endif + + +/* 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/x86_64/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 000000000..dfa6adb3e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <sysdeps/unix/sysv/linux/x86_64/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h new file mode 100644 index 000000000..02485daa5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include <signal.h> +#include <time.h> +#include <sys/types.h> + +#define OLD_TIMER_MAX	256 + +extern timer_t __compat_timer_list[OLD_TIMER_MAX] attribute_hidden; + + +extern int __timer_create_new (clockid_t clock_id, struct sigevent *evp, +			       timer_t *timerid); +extern int __timer_delete_new (timer_t timerid); +extern int __timer_getoverrun_new (timer_t timerid); +extern int __timer_gettime_new (timer_t timerid, struct itimerspec *value); +extern int __timer_settime_new (timer_t timerid, int flags, +				const struct itimerspec *value, +				struct itimerspec *ovalue); + + +extern int __timer_create_old (clockid_t clock_id, struct sigevent *evp, +			       int *timerid); +extern int __timer_delete_old (int timerid); +extern int __timer_getoverrun_old (int timerid); +extern int __timer_gettime_old (int timerid, struct itimerspec *value); +extern int __timer_settime_old (int timerid, int flags, +				const struct itimerspec *value, +				struct itimerspec *ovalue); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c new file mode 100644 index 000000000..c828e158d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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 <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + + +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 4,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \ +		  NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S new file mode 100644 index 000000000..3621efa4f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -0,0 +1,30 @@ +/* Copyright (C) 2002, 2003 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.  */ + +/* In libc.so we do not unconditionally use the lock prefix.  Only if +   the application is using threads.  */ +#ifndef UP +# define LOCK \ +	cmpl	$0, __libc_multiple_threads(%rip); 			      \ +	je	0f;							      \ +	lock;								      \ +0: +#endif + +#include "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S new file mode 100644 index 000000000..3a49e25dd --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -0,0 +1,283 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <pthread-errnos.h> + +	.text + +#ifndef LOCK +# ifdef UP +#  define LOCK +# else +#  define LOCK lock +# endif +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.globl	__lll_mutex_lock_wait +	.type	__lll_mutex_lock_wait,@function +	.hidden	__lll_mutex_lock_wait +	.align	16 +__lll_mutex_lock_wait: +	pushq	%r10 +	pushq	%rdx + +	xorq	%r10, %r10	/* No timeout.  */ +	movl	$2, %edx +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif + +	cmpl	%edx, %eax	/* NB:	 %edx == 2 */ +	jne	2f + +1:	movl	$SYS_futex, %eax +	syscall + +2:	movl	%edx, %eax +	xchgl	%eax, (%rdi)	/* NB:	 lock is implied */ + +	testl	%eax, %eax +	jnz	1b + +	popq	%rdx +	popq	%r10 +	retq +	.size	__lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + +#ifdef NOT_IN_libc +	.globl	__lll_mutex_timedlock_wait +	.type	__lll_mutex_timedlock_wait,@function +	.hidden	__lll_mutex_timedlock_wait +	.align	16 +__lll_mutex_timedlock_wait: +	/* Check for a valid timeout value.  */ +	cmpq	$1000000000, 8(%rdx) +	jae	3f + +	pushq	%r8 +	pushq	%r9 +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 + +	/* Stack frame for the timespec and timeval structs.  */ +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rdx, %r13 + +1: +	/* Get current time.  */ +	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	/* This is a regular function call, all caller-save registers +	   might be clobbered.  */ +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	4f +	addq	$1000000000, %rsi +	decq	%rdi +4:	testq	%rdi, %rdi +	js	5f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movl	$1, %eax +	movl	$2, %edx +	LOCK +	cmpxchgl %edx, (%r12) + +	testl	%eax, %eax +	je	8f + +	movq	%rsp, %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rcx + +8:				/* NB: %edx == 2 */ +	xorl	%eax, %eax +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	7f + +6:	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	popq	%r9 +	popq	%r8 +	retq + +	/* Check whether the time expired.  */ +7:	cmpq	$-ETIMEDOUT, %rcx +	je	5f + +	/* Make sure the current holder knows we are going to sleep.  */ +	movl	%edx, %eax +	xchgl	%eax, (%rdi) +	testl	%eax, %eax +	jz	6b +	jmp	1b + +3:	movl	$EINVAL, %eax +	retq + +5:	movl	$ETIMEDOUT, %eax +	jmp	6b +	.size	__lll_mutex_timedlock_wait,.-__lll_mutex_timedlock_wait +#endif + + +#ifdef NOT_IN_libc +	.globl	lll_unlock_wake_cb +	.type	lll_unlock_wake_cb,@function +	.hidden	lll_unlock_wake_cb +	.align	16 +lll_unlock_wake_cb: +	pushq	%rsi +	pushq	%rdx + +	LOCK +	addl	$1, (%rdi) +	jng	1f + +	popq	%rdx +	popq	%rsi +	retq +	.size	lll_unlock_wake_cb,.-lll_unlock_wake_cb +#endif + + +	.globl	__lll_mutex_unlock_wake +	.type	__lll_mutex_unlock_wake,@function +	.hidden	__lll_mutex_unlock_wake +	.align	16 +__lll_mutex_unlock_wake: +	pushq	%rsi +	pushq	%rdx + +	movl	$0, (%rdi) +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx	/* Wake one thread.  */ +	movl	$SYS_futex, %eax +	syscall + +	popq	%rdx +	popq	%rsi +	retq +	.size	__lll_mutex_unlock_wake,.-__lll_mutex_unlock_wake + + +#ifdef NOT_IN_libc +	.globl	__lll_timedwait_tid +	.type	__lll_timedwait_tid,@function +	.hidden	__lll_timedwait_tid +	.align	16 +__lll_timedwait_tid: +	pushq	%r12 +	pushq	%r13 + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	subq	$16, %rsp + +	/* Get current time.  */ +2:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	5f +	addq	$1000000000, %rsi +	decq	%rdi +5:	testq	%rdi, %rdi +	js	6f		/* Time is already up.  */ + +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movl	(%r12), %edx +	testl	%edx, %edx +	jz	4f + +	movq	%rsp, %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdi +	movl	$SYS_futex, %eax +	syscall + +	cmpl	$0, (%rdi) +	jne	1f +4:	xorl	%eax, %eax + +8:	addq	$16, %rsp +	popq	%r13 +	popq	%r12 +	retq + +1:	cmpq	$-ETIMEDOUT, %rax +	jne	2b + +6:	movl	$ETIMEDOUT, %eax +	jmp	8b +	.size	__lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h new file mode 100644 index 000000000..40c2518af --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -0,0 +1,341 @@ +/* Copyright (C) 2002, 2003, 2004 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.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> + +#ifndef LOCK_INSTR +# ifdef UP +#  define LOCK_INSTR	/* nothing */ +# else +#  define LOCK_INSTR "lock;" +# endif +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +/* Initializer for compatibility lock.  */ +#define LLL_MUTEX_LOCK_INITIALIZER		(0) +#define LLL_MUTEX_LOCK_INITIALIZER_LOCKED	(1) +#define LLL_MUTEX_LOCK_INITIALIZER_WAITERS	(2) + +/* Delay in spinlock loop.  */ +#define BUSY_WAIT_NOP          asm ("rep; nop") + + +#define lll_futex_wait(futex, val) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (val) _val asm ("edx") = (val);			      \ +    __asm __volatile ("xorq %%r10, %%r10\n\t"				      \ +		      "syscall"						      \ +		      : "=a" (__ignore)					      \ +		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT),	      \ +			"d" (_val)					      \ +		      : "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + + +#define lll_futex_wake(futex, nr) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (nr) _nr asm ("edx") = (nr);			      \ +    __asm __volatile ("syscall"						      \ +		      : "=a" (__ignore)					      \ +		      : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE),	      \ +			"d" (_nr)					      \ +		      : "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + + +/* Does not preserve %eax and %ecx.  */ +extern int __lll_mutex_lock_wait (int *__futex, int __val) attribute_hidden; +/* Does not preserver %eax, %ecx, and %edx.  */ +extern int __lll_mutex_timedlock_wait (int *__futex, int __val, +				       const struct timespec *__abstime) +     attribute_hidden; +/* Preserves all registers but %eax.  */ +extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; + + +/* NB: in the lll_mutex_trylock macro we simply return the value in %eax +   after the cmpxchg instruction.  In case the operation succeded this +   value is zero.  In case the operation failed, the cmpxchg instruction +   has loaded the current value of the memory work which is guaranteed +   to be nonzero.  */ +#define lll_mutex_trylock(futex) \ +  ({ int ret;								      \ +     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_cond_trylock(futex) \ +  ({ int ret;								      \ +     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"			      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS),	      \ +			 "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER)	      \ +		       : "memory");					      \ +     ret; }) + + +#define lll_mutex_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (1), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_cond_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm __volatile (LOCK_INSTR "cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (2), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_timedlock(futex, timeout) \ +  ({ int result, ignore1, ignore2, ignore3;				      \ +     __asm __volatile (LOCK_INSTR "cmpxchgl %2, %4\n\t"			      \ +		       "jnz 1f\n\t"					      \ +		       ".subsection 1\n"				      \ +		       "1:\tleaq %4, %%rdi\n\t"				      \ +		       "movq %8, %%rdx\n\t"				      \ +		       "subq $128, %%rsp\n\t"				      \ +		       "callq __lll_mutex_timedlock_wait\n\t"		      \ +		       "addq $128, %%rsp\n\t"				      \ +		       "jmp 2f\n\t"					      \ +		       ".previous\n"					      \ +		       "2:"						      \ +		       : "=a" (result), "=&D" (ignore1), "=S" (ignore2),      \ +			 "=&d" (ignore3), "=m" (futex)			      \ +		       : "0" (0), "2" (1), "m" (futex), "m" (timeout)	      \ +		       : "memory", "cx", "cc", "r10", "r11");		      \ +     result; }) + + +#define lll_mutex_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm __volatile (LOCK_INSTR "decl %0\n\t"			      \ +			      "jne 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %0, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_unlock_wake\n\t"	      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=m" (futex), "=&D" (ignore)		      \ +			      : "m" (futex)				      \ +			      : "ax", "cx", "r11", "cc", "memory"); }) + + +#define lll_mutex_islocked(futex) \ +  (futex != LLL_MUTEX_LOCK_INITIALIZER) + + +/* We have a separate internal lock implementation which is not tied +   to binary compatibility.  */ + +/* 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 +    2  -  taken by more users */ + + +#if defined NOT_IN_libc || defined UP +# define lll_trylock(futex) lll_mutex_trylock (futex) +# define lll_lock(futex) lll_mutex_lock (futex) +# define lll_unlock(futex) lll_mutex_unlock (futex) +#else +/* Special versions of the macros for use in libc itself.  They avoid +   the lock prefix when the thread library is not used. + +   The code sequence to avoid unnecessary lock prefixes is what the AMD +   guys suggested.  If you do not like it, bring it up with AMD. + +   XXX In future we might even want to avoid it on UP machines.  */ + +# define lll_trylock(futex) \ +  ({ unsigned char ret;							      \ +     __asm __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"	      \ +		       "je 0f\n\t"					      \ +		       "lock; cmpxchgl %2, %1\n\t"			      \ +		       "jmp 1f\n"					      \ +		       "0:\tcmpxchgl %2, %1\n\t"			      \ +		       "1:setne %0"					      \ +		       : "=a" (ret), "=m" (futex)			      \ +		       : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ +			 "0" (LLL_MUTEX_LOCK_INITIALIZER)		      \ +		       : "memory");					      \ +     ret; }) + + +# define lll_lock(futex) \ +  (void) ({ int ignore1, ignore2, ignore3;				      \ +	    __asm __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"   \ +			      "je 0f\n\t"				      \ +			      "lock; cmpxchgl %0, %2\n\t"		      \ +			      "jnz 1f\n\t"				      \ +		  	      "jmp 2f\n"				      \ +			      "0:\tcmpxchgl %0, %2\n\t"			      \ +			      "jnz 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %2, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_lock_wait\n\t"		      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=S" (ignore1), "=&D" (ignore2), "=m" (futex),\ +				"=a" (ignore3)				      \ +			      : "0" (1), "m" (futex), "3" (0)		      \ +			      : "cx", "r11", "cc", "memory"); }) + + +# define lll_unlock(futex) \ +  (void) ({ int ignore;							      \ +            __asm __volatile ("cmpl $0, __libc_multiple_threads(%%rip)\n\t"   \ +			      "je 0f\n\t"				      \ +			      "lock; decl %0\n\t"			      \ +			      "jne 1f\n\t"				      \ +		  	      "jmp 2f\n"				      \ +			      "0:\tdecl %0\n\t"				      \ +			      "jne 1f\n\t"				      \ +			      ".subsection 1\n"				      \ +			      "1:\tleaq %0, %%rdi\n\t"			      \ +			      "subq $128, %%rsp\n\t"			      \ +			      "callq __lll_mutex_unlock_wake\n\t"	      \ +			      "addq $128, %%rsp\n\t"			      \ +			      "jmp 2f\n\t"				      \ +			      ".previous\n"				      \ +			      "2:"					      \ +			      : "=m" (futex), "=&D" (ignore)		      \ +			      : "m" (futex)				      \ +			      : "ax", "cx", "r11", "cc", "memory"); }) +#endif + + +#define lll_islocked(futex) \ +  (futex != LLL_MUTEX_LOCK_INITIALIZER) + + +/* The kernel notifies a process with 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. + +   The macro parameter must not have any side effect.  */ +#define lll_wait_tid(tid) \ +  do {									      \ +    int __ignore;							      \ +    register __typeof (tid) _tid asm ("edx") = (tid);			      \ +    if (_tid != 0)							      \ +      __asm __volatile ("xorq %%r10, %%r10\n\t"				      \ +			"1:\tmovq %2, %%rax\n\t"			      \ +			"syscall\n\t"					      \ +			"cmpl $0, (%%rdi)\n\t"				      \ +			"jne 1b"					      \ +			: "=&a" (__ignore)				      \ +			: "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid),      \ +			  "d" (_tid)					      \ +			: "memory", "cc", "r10", "r11", "cx");		      \ +  } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) +     attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ +  ({									      \ +    int __result = 0;							      \ +    if (tid != 0)							      \ +      {									      \ +	if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)	      \ +	  __result = EINVAL;						      \ +	else								      \ +	  __result = __lll_timedwait_tid (&tid, abstime);		      \ +      }									      \ +    __result; }) + + +/* 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/x86_64/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/not-cancel.h new file mode 100644 index 000000000..acf1a617e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/not-cancel.h @@ -0,0 +1 @@ +#include "../i386/not-cancel.h" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S new file mode 100644 index 000000000..653b6b12f --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S @@ -0,0 +1,33 @@ +/* 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 <tcb-offsets.h> + +#define SAVE_PID \ +	movl	%fs:PID, %esi;						      \ +	movl	%esi, %edx;						      \ +	negl	%edx;							      \ +	movl	%edx, %fs:PID + +#define RESTORE_PID \ +	testq	%rax, %rax;						      \ +	je	1f;							      \ +	movl	%esi, %fs:PID;						      \ +1: + +#include <../../../../../../sysdeps/unix/sysv/linux/x86_64/vfork.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S new file mode 100644 index 000000000..fa8125dd8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -0,0 +1,160 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelbarrier.h> + +#define SYS_futex	202 +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_barrier_wait +	.type	pthread_barrier_wait,@function +	.align	16 +pthread_barrier_wait: +	/* Get the mutex.  */ +	xorl	%eax, %eax +	movl	$1, %esi +	LOCK +	cmpxchgl %esi, MUTEX(%rdi) +	jnz	1f + +	/* One less waiter.  If this was the last one needed wake +	   everybody.  */ +2:	decl	LEFT(%rdi) +	je	3f + +	/* There are more threads to come.  */ +#if CURR_EVENT == 0 +	movl	(%rdi), %edx +#else +	movl	CURR_EVENT(%rdi), %edx +#endif + +	/* Release the mutex.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	6f + +	/* Wait for the remaining threads.  The call will return immediately +	   if the CURR_EVENT memory has meanwhile been changed.  */ +7: +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	xorq	%r10, %r10 +8:	movl	$SYS_futex, %eax +	syscall + +	/* Don't return on spurious wakeups.  The syscall does not change +	   any register except %eax so there is no need to reload any of +	   them.  */ +#if CURR_EVENT == 0 +	cmpl	%edx, (%rdi) +#else +	cmpl	%edx, CURR_EVENT(%rdi) +#endif +	je	8b + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%rdi), %eax +	LOCK +	xaddl	%edx, LEFT(%rdi) +	subl	$1, %eax +	cmpl	%eax, %edx +	jne,pt	10f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	9f + +10:	xorl	%eax, %eax		/* != PTHREAD_BARRIER_SERIAL_THREAD */ + +	retq + +	/* The necessary number of threads arrived.  */ +3: +#if CURR_EVENT == 0 +	incl	(%rdi) +#else +	incl	CURR_EVENT(%rdi) +#endif + +	/* Wake up all waiters.  The count is a signed number in the kernel +	   so 0x7fffffff is the highest value.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	movl	$1, %edx +	movl	INIT_COUNT(%rdi), %eax +	LOCK +	xaddl	%edx, LEFT(%rdi) +	subl	$1, %eax +	cmpl	%eax, %edx +	jne,pt	5f + +	/* Release the mutex.  We cannot release the lock before +	   waking the waiting threads since otherwise a new thread might +	   arrive and gets waken up, too.  */ +	LOCK +	decl	MUTEX(%rdi) +	jne	4f + +5:	orl	$-1, %eax		/* == PTHREAD_BARRIER_SERIAL_THREAD */ + +	retq + +1:	addq	$MUTEX, %rdi +	callq	__lll_mutex_lock_wait +	subq	$MUTEX, %rdi +	jmp	2b + +4:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	5b + +6:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	subq	$MUTEX, %rdi +	jmp	7b + +9:	addq	$MUTEX, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	10b +	.size	pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S new file mode 100644 index 000000000..8b3833392 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -0,0 +1,138 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 +#define FUTEX_CMP_REQUEUE	4 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_broadcast (pthread_cond_t *cond) */ +	.globl	__pthread_cond_broadcast +	.type	__pthread_cond_broadcast, @function +	.align	16 +__pthread_cond_broadcast: + +	/* Get internal lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +2:	addq	$cond_futex, %rdi +	movq	total_seq-cond_futex(%rdi), %r9 +	cmpq	wakeup_seq-cond_futex(%rdi), %r9 +	jna	4f + +	/* Cause all currently waiting threads to recognize they are +	   woken up.  */ +	movq	%r9, wakeup_seq-cond_futex(%rdi) +	movq	%r9, woken_seq-cond_futex(%rdi) +	addq	%r9, %r9 +	movl	%r9d, (%rdi) +	incl	broadcast_seq-cond_futex(%rdi) + +	/* Get the address of the mutex used.  */ +	movq	dep_mutex-cond_futex(%rdi), %r8 + +	/* Unlock.  */ +	LOCK +	decl	cond_lock-cond_futex(%rdi) +	jne	7f + +8:	cmpq	$-1, %r8 +	je	9f + +	/* Wake up all threads.  */ +	movl	$FUTEX_CMP_REQUEUE, %esi +	movl	$SYS_futex, %eax +	movl	$1, %edx +	movl	$0x7fffffff, %r10d +	syscall + +	/* For any kind of error, which mainly is EAGAIN, we try again +	   with WAKE.  The general test also covers running on old +	   kernels.  */ +	cmpq	$-4095, %rax +	jae	9f + +10:	xorl	%eax, %eax +	retq + +	.align	16 +	/* Unlock.  */ +4:	LOCK +	decl	cond_lock-cond_futex(%rdi) +	jne	5f + +6:	xorl	%eax, %eax +	retq + +	/* Initial locking failed.  */ +1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +5:	addq	$cond_lock-cond_futex, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	6b + +	/* Unlock in loop requires wakeup.  */ +7:	addq	$cond_lock-cond_futex, %rdi +	callq	__lll_mutex_unlock_wake +	subq	$cond_lock-cond_futex, %rdi +	jmp	8b + +9:	/* The futex requeue functionality is not available.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall +	jmp	10b +	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, +		  GLIBC_2_3_2) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S new file mode 100644 index 000000000..bc5843564 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S @@ -0,0 +1,104 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 +#define FUTEX_REQUEUE		3 + +#define EINVAL			22 + + +	.text + +	/* int pthread_cond_signal (pthread_cond_t *cond) */ +	.globl	__pthread_cond_signal +	.type	__pthread_cond_signal, @function +	.align	16 +__pthread_cond_signal: + +	/* Get internal lock.  */ +	movq	%rdi, %r8 +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +2:	addq	$cond_futex, %rdi +	movq	total_seq(%r8), %rcx +	cmpq	wakeup_seq(%r8), %rcx +	jbe	4f + +	/* Bump the wakeup number.  */ +	addq	$1, wakeup_seq(%r8) +	addl	$1, (%rdi) + +	/* Wake up one thread.  */ +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	movl	$1, %edx +	syscall + +	/* Unlock.  */ +4:	LOCK +#if cond_lock == 0 +	decl	(%r8) +#else +	decl	cond_lock(%r8) +#endif +	jne	5f + +6:	xorl	%eax, %eax +	retq + +	/* Initial locking failed.  */ +1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +5: +	movq	%r8, %rdi +	callq	__lll_mutex_unlock_wake +	jmp	6b +	.size	__pthread_cond_signal, .-__pthread_cond_signal +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, +		  GLIBC_2_3_2) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S new file mode 100644 index 000000000..ad3ae1e76 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -0,0 +1,470 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, +			       const struct timespec *abstime)  */ +	.globl	__pthread_cond_timedwait +	.type	__pthread_cond_timedwait, @function +	.align	16 +__pthread_cond_timedwait: +.LSTARTCODE: +	pushq	%r12 +.Lpush_r12: +	pushq	%r13 +.Lpush_r13: +	pushq	%r14 +.Lpush_r14: +#define FRAME_SIZE 80 +	subq	$FRAME_SIZE, %rsp +.Lsubq: + +	cmpq	$1000000000, 8(%rdx) +	movl	$EINVAL, %eax +	jae	18f + +	/* Stack frame: + +	   rsp + 80 +	            +--------------------------+ +	   rsp + 48 | cleanup buffer           | +	            +--------------------------+ +	   rsp + 40 | old wake_seq value       | +	            +--------------------------+ +	   rsp + 24 | timeout value            | +	            +--------------------------+ +	   rsp + 16 | mutex pointer            | +	            +--------------------------+ +	   rsp +  8 | condvar pointer          | +	            +--------------------------+ +	   rsp +  4 | old broadcast_seq value  | +	            +--------------------------+ +	   rsp +  0 | old cancellation mode    | +	            +--------------------------+ +	*/ + +	cmpq	$-1, dep_mutex(%rdi) + +	/* Prepare structure passed to cancellation handler.  */ +	movq	%rdi, 8(%rsp) +	movq	%rsi, 16(%rsp) +	movq	%rdx, %r13 + +	je	22f +	movq	%rsi, dep_mutex(%rdi) + +	/* Get internal lock.  */ +22:	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	1f + +	/* Unlock the mutex.  */ +2:	movq	16(%rsp), %rdi +	xorl	%esi, %esi +	callq	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	16f + +	movq	8(%rsp), %rdi +	incq	total_seq(%rdi) +	incl	cond_futex(%rdi) +	addl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Install cancellation handler.  */ +#ifdef PIC +	leaq	__condvar_cleanup(%rip), %rsi +#else +	leaq	__condvar_cleanup, %rsi +#endif +	leaq	48(%rsp), %rdi +	movq	%rsp, %rdx +	callq	__pthread_cleanup_push + +	/* Get and store current wakeup_seq value.  */ +	movq	8(%rsp), %rdi +	movq	wakeup_seq(%rdi), %r9 +	movl	broadcast_seq(%rdi), %edx +	movq	%r9, 40(%rsp) +	movl	%edx, 4(%rsp) + +	/* Get the current time.  */ +8: +#ifdef __NR_clock_gettime +	/* Get the clock number.  Note that the field in the condvar +	   structure stores the number minus 1.  */ +	movq	8(%rsp), %rdi +	movl	cond_nwaiters(%rdi), %edi +	andl	$((1 << clock_bits) - 1), %edi +	/* Only clocks 0 and 1 are allowed so far.  Both are handled in the +	   kernel.  */ +	leaq	24(%rsp), %rsi +	movl	$__NR_clock_gettime, %eax +	syscall +# ifndef __ASSUME_POSIX_TIMERS +	cmpq	$-ENOSYS, %rax +	je	19f +# endif + +	/* Compute relative timeout.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	32(%rsp), %rdx +#else +	leaq	24(%rsp), %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	32(%rsp), %rax +	movl	$1000, %edx +	mul	%rdx		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	%rax, %rdx +#endif +	jns	12f +	addq	$1000000000, %rdx +	decq	%rcx +12:	testq	%rcx, %rcx +	movq	8(%rsp), %rdi +	movq	$-ETIMEDOUT, %r14 +	js	6f + +	/* Store relative timeout.  */ +21:	movq	%rcx, 24(%rsp) +	movq	%rdx, 32(%rsp) + +	movl	cond_futex(%rdi), %r12d + +	/* Unlock.  */ +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	3f + +4:	callq	__pthread_enable_asynccancel +	movl	%eax, (%rsp) + +	leaq	24(%rsp), %r10 +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%r12, %rdx +	addq	$cond_futex, %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %r14 + +	movl	(%rsp), %edi +	callq	__pthread_disable_asynccancel + +	/* Lock.  */ +	movq	8(%rsp), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jne	5f + +6:	movl	broadcast_seq(%rdi), %edx + +	movq	woken_seq(%rdi), %rax + +	movq	wakeup_seq(%rdi), %r9 + +	cmpl	4(%rsp), %edx +	jne	23f + +	cmpq	40(%rsp), %r9 +	jbe	15f + +	cmpq	%rax, %r9 +	ja	9f + +15:	cmpq	$-ETIMEDOUT, %r14 +	jne	8b + +13:	incq	wakeup_seq(%rdi) +	incl	cond_futex(%rdi) +	movl	$ETIMEDOUT, %r14d +	jmp	14f + +23:	xorq	%r14, %r14 +	jmp	24f + +9:	xorq	%r14, %r14 +14:	incq	woken_seq(%rdi) + +24:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	25f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	25f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi + +25:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	10f + +	/* Remove cancellation handler.  */ +11:	movq	48+CLEANUP_PREV(%rsp), %rdx +	movq	%rdx, %fs:CLEANUP + +	movq	16(%rsp), %rdi +	callq	__pthread_mutex_cond_lock + +	testq	%rax, %rax +	cmoveq	%r14, %rax + +18:	addq	$FRAME_SIZE, %rsp +.Laddq: +	popq	%r14 +.Lpop_r14: +	popq	%r13 +.Lpop_r13: +	popq	%r12 +.Lpop_r12: + +	retq + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +3: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +16:	movq	8(%rsp), %rdi +	movq	%rax, (%rsp) +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	17f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +17:	movq	(%rsp), %rax +	jmp	18b + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS +	/* clock_gettime not available.  */ +19:	leaq	24(%rsp), %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	32(%rsp), %rax +	movl	$1000, %edx +	mul	%rdx		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdx +	subq	24(%rsp), %rcx +	subq	%rax, %rdx +	jns	20f +	addq	$1000000000, %rdx +	decq	%rcx +20:	testq	%rcx, %rcx +	movq	8(%rsp), %rdi +	movq	$-ETIMEDOUT, %r14 +	js	6b +	jmp	21b +#endif +.LENDCODE: +	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, +		  GLIBC_2_3_2) + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	L(ENDCIE)-L(STARTCIE)		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zR"				# NUL-terminated augmentation +						# string. +#else +	.ascii	"\0"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 1				# Augmentation value length. +	.byte	0x1b				# Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code +#else +	.long	.LSTARTCODE			# Start address of the code. +#endif +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +#ifdef SHARED +	.uleb128 0				# No augmentation data. +#endif +	.byte	0x40+.Lpush_r12-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x40+.Lpush_r13-.Lpush_r12	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	0x8d				# DW_CFA_offset %r13 +	.uleb128 3 +	.byte	0x40+.Lpush_r14-.Lpush_r13	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32 +	.byte	0x84				# DW_CFA_offset %r14 +	.uleb128 4 +	.byte	0x40+.Lsubq-.Lpush_r14		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32+FRAME_SIZE +	.byte	3				# DW_CFA_advance_loc2 +	.2byte	.Laddq-.Lsubq +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32 +	.byte	0x40+.Lpop_r14-.Laddq		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	0xce				# DW_CFA_restore %r14 +	.byte	0x40+.Lpop_r13-.Lpop_r14	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0xcd				# DW_CFA_restore %r13 +	.byte	0x40+.Lpop_r12-.Lpop_r13	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xcc				# DW_CFA_restore %r12 +	.byte	0x40+.LSbl1-.Lpop_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 32+FRAME_SIZE +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x8d				# DW_CFA_offset %r13 +	.uleb128 3 +	.byte	0x84				# DW_CFA_offset %r14 +	.uleb128 4 +	.align	8 +.LENDFDE: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S new file mode 100644 index 000000000..b837d466b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -0,0 +1,423 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <lowlevelcond.h> +#include <tcb-offsets.h> + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.align	16 +	.type	__condvar_cleanup, @function +	.globl	__condvar_cleanup +	.hidden	__condvar_cleanup +__condvar_cleanup: +	pushq	%r12 + +	/* Get internal lock.  */ +	movq	%rdi, %r8 +	movq	8(%rdi), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jz	1f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif + +1:	movl	broadcast_seq(%rdi), %edx +	cmpl	4(%r8), %edx +	jne	3f + +	incq	wakeup_seq(%rdi) +	incq	woken_seq(%rdi) +	incl	cond_futex(%rdi) + +3:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	xorq	%r12, %r12 +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	4f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	4f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi +	movl	$1, %r12d + +4:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	je	2f +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +	/* Wake up all waiters to make sure no signal gets lost.  */ +2:	testq	%r12, %r12 +	jnz	5f +	addq	$cond_futex, %rdi +	movl	$FUTEX_WAKE, %esi +	movl	$0x7fffffff, %edx +	movl	$SYS_futex, %eax +	syscall + +5:	movq	16(%r8), %rdi +	callq	__pthread_mutex_cond_lock + +	popq	%r12 + +	retq +	.size	__condvar_cleanup, .-__condvar_cleanup + + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */ +	.globl	__pthread_cond_wait +	.type	__pthread_cond_wait, @function +	.align	16 +__pthread_cond_wait: +.LSTARTCODE: +	pushq	%r12 +.Lpush_r12: +#define FRAME_SIZE 64 +	subq	$FRAME_SIZE, %rsp +.Lsubq: +	/* Stack frame: + +	   rsp + 64 +	            +--------------------------+ +	   rsp + 32 | cleanup buffer           | +		    +--------------------------+ +	   rsp + 24 | old wake_seq value       | +	            +--------------------------+ +	   rsp + 16 | mutex pointer            | +	            +--------------------------+ +	   rsp +  8 | condvar pointer          | +	            +--------------------------+ +	   rsp +  4 | old broadcast_seq value  | +	            +--------------------------+ +	   rsp +  0 | old cancellation mode    | +	            +--------------------------+ +	*/ + +	cmpq	$-1, dep_mutex(%rdi) + +		/* Prepare structure passed to cancellation handler.  */ +	movq	%rdi, 8(%rsp) +	movq	%rsi, 16(%rsp) + +	je	15f +	movq	%rsi, dep_mutex(%rdi) + +	/* Get internal lock.  */ +15:	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jne	1f + +	/* Unlock the mutex.  */ +2:	movq	16(%rsp), %rdi +	xorl	%esi, %esi +	callq	__pthread_mutex_unlock_usercnt + +	testl	%eax, %eax +	jne	12f + +	movq	8(%rsp), %rdi +	incq	total_seq(%rdi) +	incl	cond_futex(%rdi) +	addl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Install cancellation handler.  */ +#ifdef PIC +	leaq	__condvar_cleanup(%rip), %rsi +#else +	leaq	__condvar_cleanup, %rsi +#endif +	leaq	32(%rsp), %rdi +	movq	%rsp, %rdx +	callq	__pthread_cleanup_push + +	/* Get and store current wakeup_seq value.  */ +	movq	8(%rsp), %rdi +	movq	wakeup_seq(%rdi), %r9 +	movl	broadcast_seq(%rdi), %edx +	movq	%r9, 24(%rsp) +	movl	%edx, 4(%rsp) + +	/* Unlock.  */ +8:	movl	cond_futex(%rdi), %r12d +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	3f + +4:	callq	__pthread_enable_asynccancel +	movl	%eax, (%rsp) + +	movq	8(%rsp), %rdi +	xorq	%r10, %r10 +	movq	%r12, %rdx +	addq	$cond_futex-cond_lock, %rdi +	movl	$SYS_futex, %eax +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	syscall + +	movl	(%rsp), %edi +	callq	__pthread_disable_asynccancel + +	/* Lock.  */ +	movq	8(%rsp), %rdi +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if cond_lock == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, cond_lock(%rdi) +#endif +	jnz	5f + +6:	movl	broadcast_seq(%rdi), %edx + +	movq	woken_seq(%rdi), %rax + +	movq	wakeup_seq(%rdi), %r9 + +	cmpl	4(%rsp), %edx +	jne	16f + +	cmpq	24(%rsp), %r9 +	jbe	8b + +	cmpq	%rax, %r9 +	jna	8b + +	incq	woken_seq(%rdi) + +	/* Unlock */ +16:	subl	$(1 << clock_bits), cond_nwaiters(%rdi) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	cmpq	$0xffffffffffffffff, total_seq(%rdi) +	jne	17f +	movl	cond_nwaiters(%rdi), %eax +	andl	$~((1 << clock_bits) - 1), %eax +	jne	17f + +	addq	$cond_nwaiters, %rdi +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	movl	$1, %edx +	syscall +	subq	$cond_nwaiters, %rdi + +17:	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	10f + +	/* Remove cancellation handler.  */ +11:	movq	32+CLEANUP_PREV(%rsp), %rdx +	movq	%rdx, %fs:CLEANUP + +	movq	16(%rsp), %rdi +	callq	__pthread_mutex_cond_lock +14:	addq	$FRAME_SIZE, %rsp +.Laddq: + +	popq	%r12 +.Lpop_r12: + +	/* We return the result of the mutex_lock operation.  */ +	retq + +	/* Initial locking failed.  */ +1: +.LSbl1: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +	/* Unlock in loop requires wakeup.  */ +3: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +	/* Locking in loop failed.  */ +5: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if cond_lock != 0 +	subq	$cond_lock, %rdi +#endif +	jmp	6b + +	/* Unlock after loop requires wakeup.  */ +10: +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +	/* The initial unlocking of the mutex failed.  */ +12:	movq	%rax, %r10 +	movq	8(%rsp), %rdi +	LOCK +#if cond_lock == 0 +	decl	(%rdi) +#else +	decl	cond_lock(%rdi) +#endif +	jne	13f + +#if cond_lock != 0 +	addq	$cond_lock, %rdi +#endif +	callq	__lll_mutex_unlock_wake + +13:	movq	%r10, %rax +	jmp	14b +.LENDCODE: +	.size	__pthread_cond_wait, .-__pthread_cond_wait +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, +		  GLIBC_2_3_2) + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	L(ENDCIE)-L(STARTCIE)		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zR"				# NUL-terminated augmentation +						# string. +#else +	.ascii	"\0"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 1				# Augmentation value length. +	.byte	0x1b				# Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x8 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code +#else +	.long	.LSTARTCODE			# Start address of the code. +#endif +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +#ifdef SHARED +	.uleb128 0				# No augmentation data. +#endif +	.byte	0x40+.Lpush_r12-.LSTARTCODE	# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.byte	0x40+.Lsubq-.Lpush_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16+FRAME_SIZE +	.byte	3				# DW_CFA_advance_loc2 +	.2byte	.Laddq-.Lsubq +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	0x40+.Lpop_r12-.Laddq		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	0xcc				# DW_CFA_restore %r12 +	.byte	0x40+.LSbl1-.Lpop_r12		# DW_CFA_advance_loc+N +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 80 +	.byte	0x8c				# DW_CFA_offset %r12 +	.uleb128 2 +	.align	8 +.LENDFDE: diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S new file mode 100644 index 000000000..6bf8d095b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -0,0 +1,257 @@ +/* Copyright (C) 2002, 2003, 2005 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.  */ + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + +#define SYS_futex	202 +#define FUTEX_WAKE	1 + +	.comm	__fork_generation, 4, 4 + +	.text + + +	.globl	__pthread_once +	.type	__pthread_once,@function +	.align	16 +__pthread_once: +.LSTARTCODE: +	testl	$2, (%rdi) +	jz	1f +	xorl	%eax, %eax +	retq + +	/* Preserve the function pointer.  */ +1:	pushq	%rsi +.Lpush_rsi: +	xorq	%r10, %r10 + +	/* Not yet initialized or initialization in progress. +	   Get the fork generation counter now.  */ +6:	movl	(%rdi), %eax + +5:	movl	%eax, %edx + +	testl	$2, %eax +	jnz	4f + +	andl	$3, %edx +	orl	__fork_generation(%rip), %edx +	orl	$1, %edx + +	LOCK +	cmpxchgl %edx, (%rdi) +	jnz	5b + +	/* Check whether another thread already runs the initializer.  */ +	testl	$1, %eax +	jz	3f	/* No -> do it.  */ + +	/* Check whether the initializer execution was interrupted +	   by a fork.  */ +	xorl	%edx, %eax +	testl	$0xfffffffc, %eax +	jnz	3f	/* Different for generation -> run initializer.  */ + +	/* Somebody else got here first.  Wait.  */ +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall +	jmp	6b + +	/* Preserve the pointer to the control variable.  */ +3:	pushq	%rdi +.Lpush_rdi: + +.LcleanupSTART: +	callq	*8(%rsp) +.LcleanupEND: + +	/* Get the control variable address back.  */ +	popq	%rdi +.Lpop_rdi: + +	/* Sucessful run of the initializer.  Signal that we are done.  */ +	LOCK +	incl	(%rdi) + +	/* Wake up all other threads.  */ +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +4:	addq	$8, %rsp +.Ladd: +	xorl	%eax, %eax +	retq + +	.size	__pthread_once,.-__pthread_once + + +	.globl	__pthread_once_internal +__pthread_once_internal = __pthread_once + +	.globl	pthread_once +pthread_once = __pthread_once + + +	.type	clear_once_control,@function +	.align	16 +clear_once_control: +	movq	(%rsp), %rdi +	movq	%rax, %r8 +	movl	$0, (%rdi) + +	movl	$0x7fffffff, %edx +	movl	$FUTEX_WAKE, %esi +	movl	$SYS_futex, %eax +	syscall + +	movq	%r8, %rdi +.LcallUR: +	call	_Unwind_Resume@PLT +	hlt +.LENDCODE: +	.size	clear_once_control,.-clear_once_control + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				# @LPStart format (omit) +	.byte	0xff				# @TType format (omit) +	.byte	0x01				# call-site format +						# DW_EH_PE_uleb128 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.uleb128 .LcleanupSTART-.LSTARTCODE +	.uleb128 .LcleanupEND-.LcleanupSTART +	.uleb128 clear_once_control-.LSTARTCODE +	.uleb128  0 +	.uleb128 .LcallUR-.LSTARTCODE +	.uleb128 .LENDCODE-.LcallUR +	.uleb128 0 +	.uleb128  0 +.Lcstend: + + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.long	.LENDCIE-.LSTARTCIE		# Length of the CIE. +.LSTARTCIE: +	.long	0				# CIE ID. +	.byte	1				# Version number. +#ifdef SHARED +	.string	"zPLR"				# NUL-terminated augmentation +						# string. +#else +	.string	"zPL"				# NUL-terminated augmentation +						# string. +#endif +	.uleb128 1				# Code alignment factor. +	.sleb128 -8				# Data alignment factor. +	.byte	16				# Return address register +						# column. +#ifdef SHARED +	.uleb128 7				# Augmentation value length. +	.byte	0x9b				# Personality: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4 +						# + DW_EH_PE_indirect +	.long	DW.ref.__gcc_personality_v0-. +	.byte	0x1b				# LSDA Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +	.byte	0x1b				# FDE Encoding: DW_EH_PE_pcrel +						# + DW_EH_PE_sdata4. +#else +	.uleb128 10				# Augmentation value length. +	.byte	0x0				# Personality: absolute +	.quad	__gcc_personality_v0 +	.byte	0x0				# LSDA Encoding: absolute +#endif +	.byte 0x0c				# DW_CFA_def_cfa +	.uleb128 7 +	.uleb128 8 +	.byte	0x90				# DW_CFA_offset, column 0x10 +	.uleb128 1 +	.align 8 +.LENDCIE: + +	.long	.LENDFDE-.LSTARTFDE		# Length of the FDE. +.LSTARTFDE: +	.long	.LSTARTFDE-.LSTARTFRAME		# CIE pointer. +#ifdef SHARED +	.long	.LSTARTCODE-.			# PC-relative start address +						# of the code. +	.long	.LENDCODE-.LSTARTCODE		# Length of the code. +	.uleb128 4				# Augmentation size +	.long	.LexceptSTART-. +#else +	.quad	.LSTARTCODE			# Start address of the code. +	.quad	.LENDCODE-.LSTARTCODE		# Length of the code. +	.uleb128 8				# Augmentation size +	.quad	.LexceptSTART +#endif +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpush_rsi-.LSTARTCODE +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpush_rdi-.Lpush_rsi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpop_rdi-.Lpush_rdi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Ladd-.Lpop_rdi +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 8 +	.byte	4				# DW_CFA_advance_loc4 +	.long	clear_once_control-.Ladd +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 24 +#if 0 +	.byte	4				# DW_CFA_advance_loc4 +	.long	.Lpop_rdi2-clear_once_control +	.byte	14				# DW_CFA_def_cfa_offset +	.uleb128 16 +#endif +	.align	8 +.LENDFDE: + + +#ifdef SHARED +	.hidden	DW.ref.__gcc_personality_v0 +	.weak	DW.ref.__gcc_personality_v0 +	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits +	.align	8 +	.type	DW.ref.__gcc_personality_v0, @object +	.size	DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: +	.quad	__gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..5e9d8fb1d --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -0,0 +1,177 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_rdlock +	.type	__pthread_rwlock_rdlock,@function +	.align	16 +__pthread_rwlock_rdlock: +	xorq	%r10, %r10 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%rdi), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%rdi) +	je	5f +	cmpl	$0, FLAGS(%rdi) +	je	5f + +3:	incl	READERS_QUEUED(%rdi) +	je	4f + +	movl	READERS_WAKEUP(%rdi), %edx + +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	10f + +11:	addq	$READERS_WAKEUP, %rdi +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall + +	subq	$READERS_WAKEUP, %rdi + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	12f + +13:	decl	READERS_QUEUED(%rdi) +	jmp	2b + +5:	xorl	%edx, %edx +	incl	NR_READERS(%rdi) +	je	8f +9:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	6f +7: + +	movq	%rdx, %rax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	/* Deadlock detected.  */ +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	7b + +	/* Overflow.  */ +8:	decl	NR_READERS(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +	/* Overflow.  */ +4:	decl	READERS_QUEUED(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	11b + +12: +#if MUTEX == 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	13b +	.size	__pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + +	.globl	pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + +	.globl	__pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..b44660418 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -0,0 +1,220 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedrdlock +	.type	pthread_rwlock_timedrdlock,@function +	.align	16 +pthread_rwlock_timedrdlock: +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%r12), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, WRITERS_QUEUED(%r12) +	je	5f +	cmpl	$0, FLAGS(%r12) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpq	$1000000000, 8(%r13) +	jae	19f + +	incl	READERS_QUEUED(%r12) +	je	4f + +	movl	READERS_WAKEUP(%r12), %r14d + +	/* Unlock.  */ +	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdi +	subq	(%rsp), %rcx +	subq	%rax, %rdi +	jns	15f +	addq	$1000000000, %rdi +	decq	%rcx +15:	testq	%rcx, %rcx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rcx, (%rsp)	/* Store relative timeout.  */ +	movq	%rdi, 8(%rsp) + +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%rsp, %r10 +	movl	%r14d, %edx +	leaq	READERS_WAKEUP(%r12), %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rdx +17: + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%r12) +#else +	cmpxchgl %esi, MUTEX(%r12) +#endif +	jnz	12f + +13:	decl	READERS_QUEUED(%r12) +	cmpq	$-ETIMEDOUT, %rdx +	jne	2b + +18:	movl	$ETIMEDOUT, %edx +	jmp	9f + + +5:	xorl	%edx, %edx +	incl	NR_READERS(%r12) +	je	8f +9:	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	6f + +7:	movq	%rdx, %rax + +	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leal	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +8:	decl	NR_READERS(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +	/* Overflow.  */ +4:	decl	READERS_QUEUED(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	13b + +16:	movq	$-ETIMEDOUT, %rdx +	jmp	17b + +19:	movl	$EINVAL, %edx +	jmp	9b +	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..525e5b6b9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -0,0 +1,211 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	pthread_rwlock_timedwrlock +	.type	pthread_rwlock_timedwrlock,@function +	.align	16 +pthread_rwlock_timedwrlock: +	pushq	%r12 +	pushq	%r13 +	pushq	%r14 +	subq	$16, %rsp + +	movq	%rdi, %r12 +	movq	%rsi, %r13 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%r12), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%r12) +	je	5f + +	/* Check the value of the timeout parameter.  */ +3:	cmpq	$1000000000, 8(%r13) +	jae	19f + +	incl	WRITERS_QUEUED(%r12) +	je	4f + +	movl	WRITERS_WAKEUP(%r12), %r14d + +	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	10f + +	/* Get current time.  */ +11:	movq	%rsp, %rdi +	xorl	%esi, %esi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rcx +	movq	8(%r13), %rdi +	subq	(%rsp), %rcx +	subq	%rax, %rdi +	jns	15f +	addq	$1000000000, %rdi +	decq	%rcx +15:	testq	%rcx, %rcx +	js	16f		/* Time is already up.  */ + +	/* Futex call.  */ +	movq	%rcx, (%rsp)	/* Store relative timeout.  */ +	movq	%rdi, 8(%rsp) + +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movq	%rsp, %r10 +	movl	%r14d, %edx +	leaq	WRITERS_WAKEUP(%r12), %rdi +	movl	$SYS_futex, %eax +	syscall +	movq	%rax, %rdx +17: + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%r12) +#else +	cmpxchgl %esi, MUTEX(%r12) +#endif +	jnz	12f + +13:	decl	WRITERS_QUEUED(%r12) +	cmpq	$-ETIMEDOUT, %rdx +	jne	2b + +18:	movl	$ETIMEDOUT, %edx +	jmp	9f + + +5:	xorl	%edx, %edx +	movl	%fs:TID, %eax +	movl	%eax, WRITER(%r12) +9:	LOCK +#if MUTEX == 0 +	decl	(%r12) +#else +	decl	MUTEX(%r12) +#endif +	jne	6f + +7:	movq	%rdx, %rax + +	addq	$16, %rsp +	popq	%r14 +	popq	%r13 +	popq	%r12 +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +20:	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leal	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +	/* Overflow.  */ +4:	decl	WRITERS_QUEUED(%r12) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	11b + +12: +#if MUTEX == 0 +	movq	%r12, %rdi +#else +	leaq	MUTEX(%r12), %rdi +#endif +	callq	__lll_mutex_lock_wait +	jmp	13b + +16:	movq	$-ETIMEDOUT, %rdx +	jmp	17b + +19:	movl	$EINVAL, %edx +	jmp	9b +	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S new file mode 100644 index 000000000..3a6b9f0ba --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -0,0 +1,130 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> + + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_unlock +	.type	__pthread_rwlock_unlock,@function +	.align	16 +__pthread_rwlock_unlock: +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	cmpl	$0, WRITER(%rdi) +	jne	5f +	decl	NR_READERS(%rdi) +	jnz	6f + +5:	movl	$0, WRITER(%rdi) + +	movl	$1, %esi +	leaq	WRITERS_WAKEUP(%rdi), %r10 +	movq	%rsi, %rdx +	cmpl	$0, WRITERS_QUEUED(%rdi) +	jne	0f + +	/* If also no readers waiting nothing to do.  */ +	cmpl	$0, READERS_QUEUED(%rdi) +	je	6f + +	movl	$0x7fffffff, %edx +	leaq	READERS_WAKEUP(%rdi), %r10 + +0:	incl	(%r10) +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	7f + +8:	movl	$SYS_futex, %eax +	movq	%r10, %rdi +	syscall + +	xorl	%eax, %eax +	retq + +	.align	16 +6:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	3f + +4:	xorl	%eax, %eax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +3: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	4b + +7: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	8b + +	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock + +	.globl	pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + +	.globl	__pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..0e82f890a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -0,0 +1,165 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> + + +#define SYS_futex		202 +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +#ifndef UP +# define LOCK lock +#else +# define LOCK +#endif + + +	.text + +	.globl	__pthread_rwlock_wrlock +	.type	__pthread_rwlock_wrlock,@function +	.align	16 +__pthread_rwlock_wrlock: +	xorq	%r10, %r10 + +	/* Get the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	1f + +2:	movl	WRITER(%rdi), %eax +	testl	%eax, %eax +	jne	14f +	cmpl	$0, NR_READERS(%rdi) +	je	5f + +3:	incl	WRITERS_QUEUED(%rdi) +	je	4f + +	movl	WRITERS_WAKEUP(%rdi), %edx + +	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	10f + +11:	addq	$WRITERS_WAKEUP, %rdi +#if FUTEX_WAIT == 0 +	xorl	%esi, %esi +#else +	movl	$FUTEX_WAIT, %esi +#endif +	movl	$SYS_futex, %eax +	syscall + +	subq	$WRITERS_WAKEUP, %rdi + +	/* Reget the lock.  */ +	movl	$1, %esi +	xorl	%eax, %eax +	LOCK +#if MUTEX == 0 +	cmpxchgl %esi, (%rdi) +#else +	cmpxchgl %esi, MUTEX(%rdi) +#endif +	jnz	12f + +13:	decl	WRITERS_QUEUED(%rdi) +	jmp	2b + +5:	xorl	%edx, %edx +	movl	%fs:TID, %eax +	movl	%eax, WRITER(%rdi) +9:	LOCK +#if MUTEX == 0 +	decl	(%rdi) +#else +	decl	MUTEX(%rdi) +#endif +	jne	6f +7: + +	movq	%rdx, %rax +	retq + +1: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	2b + +14:	cmpl	%fs:TID, %eax +	jne	3b +	movl	$EDEADLK, %edx +	jmp	9b + +6: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +	jmp	7b + +4:	decl	WRITERS_QUEUED(%rdi) +	movl	$EAGAIN, %edx +	jmp	9b + +10: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_unlock_wake +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	11b + +12: +#if MUTEX != 0 +	addq	$MUTEX, %rdi +#endif +	callq	__lll_mutex_lock_wait +#if MUTEX != 0 +	subq	$MUTEX, %rdi +#endif +	jmp	13b +	.size	__pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + +	.globl	pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + +	.globl	__pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c new file mode 100644 index 000000000..dc811787e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include <nptl/sysdeps/x86_64/pthread_spin_init.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S new file mode 100644 index 000000000..7da1c75dc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include <nptl/sysdeps/x86_64/pthread_spin_unlock.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S new file mode 100644 index 000000000..7f608a597 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -0,0 +1,66 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	sem_post +	.type	sem_post,@function +	.align	16 +sem_post: +	movl	$1, %edx +	LOCK +	xaddl	%edx, (%rdi) + +	movl	$SYS_futex, %eax +	movl	$FUTEX_WAKE, %esi +	incl	%edx +	syscall + +	testq	%rax, %rax +	js	1f + +	xorl	%eax, %eax +	retq + +1: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	$EINVAL, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	$EINVAL, (%rax) +#endif + +	orl	$-1, %eax +	retq +	.size	sem_post,.-sem_post diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S new file mode 100644 index 000000000..c44d3f5e7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -0,0 +1,175 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 + +/* For the calculation see asm/vsyscall.h.  */ +#define VSYSCALL_ADDR_vgettimeofday	0xffffffffff600000 + + +	.text + +	.globl	sem_timedwait +	.type	sem_timedwait,@function +	.align	16 +	cfi_startproc +sem_timedwait: +	/* First check for cancellation.  */ +	movl	%fs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	11f + +	movl	(%rdi), %eax +2:	testl	%eax, %eax +	je	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%rdi) +	jne	2b + +	xorl	%eax, %eax +	retq + +	/* Check whether the timeout value is valid.  */ +1:	pushq	%r12 +	cfi_adjust_cfa_offset(8) +	pushq	%r13 +	cfi_adjust_cfa_offset(8) +	pushq	%r14 +	cfi_adjust_cfa_offset(8) +	subq	$24, %rsp +	cfi_adjust_cfa_offset(24) + +	movq	%rdi, %r12 +	cfi_offset(12, -16)		/* %r12 */ +	movq	%rsi, %r13 +	cfi_offset(13, -24)		/* %r13 */ + +	/* Check for invalid nanosecond field.  */ +	cmpq	$1000000000, 8(%r13) +	movl	$EINVAL, %r14d +	cfi_offset(14, -24)		/* %r14 */ +	jae	6f + +7:	call	__pthread_enable_asynccancel +	movl	%eax, 16(%rsp) + +	xorl	%esi, %esi +	movq	%rsp, %rdi +	movq	$VSYSCALL_ADDR_vgettimeofday, %rax +	callq	*%rax + +	/* Compute relative timeout.  */ +	movq	8(%rsp), %rax +	movl	$1000, %edi +	mul	%rdi		/* Milli seconds to nano seconds.  */ +	movq	(%r13), %rdi +	movq	8(%r13), %rsi +	subq	(%rsp), %rdi +	subq	%rax, %rsi +	jns	5f +	addq	$1000000000, %rsi +	decq	%rdi +5:	testq	%rdi, %rdi +	movl	$ETIMEDOUT, %r14d +	js	6f		/* Time is already up.  */ + +	movq	%rdi, (%rsp)	/* Store relative timeout.  */ +	movq	%rsi, 8(%rsp) + +	movq	%rsp, %r10 +	movq	%r12, %rdi +	xorl	%esi, %esi +	movl	$SYS_futex, %eax +	xorl	%edx, %edx +	syscall +	movq	%rax, %r14 + +	movl	16(%rsp), %edi +	call	__pthread_disable_asynccancel + +	testq	%r14, %r14 +	je	9f +	cmpq	$-EWOULDBLOCK, %r14 +	jne	3f + +9:	movl	(%r12), %eax +8:	testl	%eax, %eax +	je	7b + +	leaq	-1(%rax), %rcx +	LOCK +	cmpxchgl %ecx, (%r12) +	jne	8b + +	xorl	%eax, %eax +10:	addq	$24, %rsp +	cfi_adjust_cfa_offset(-24) +	popq	%r14 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(14) +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) +	retq + +	cfi_adjust_cfa_offset(48) +	cfi_offset(12, -16)		/* %r12 */ +	cfi_offset(13, -24)		/* %r13 */ +	cfi_offset(14, -32)		/* %r14 */ +3:	negq	%r14 +6: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	%r14d, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	%r14d, (%rax) +#endif + +	orl	$-1, %eax +	jmp	10b +	cfi_adjust_cfa_offset(-48) +	cfi_restore(14) +	cfi_restore(13) +	cfi_restore(12) + +11:	/* Canceled.  */ +	movq	$0xffffffffffffffff, %fs:RESULT +	LOCK +	orl	$0x10, %fs:CANCELHANDLING +	movq	%fs:CLEANUP_JMP_BUF, %rdi +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	sem_timedwait,.-sem_timedwait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S new file mode 100644 index 000000000..31271bb94 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -0,0 +1,59 @@ +/* Copyright (C) 2002, 2003 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 <sysdep.h> +#include <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +	.text + +	.globl	sem_trywait +	.type	sem_trywait,@function +	.align	16 +sem_trywait: +	movl	(%rdi), %eax +2:	testl	%eax, %eax +	jz	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%rdi) +	jne	2b + +	xorl	%eax, %eax +	retq + +1: +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	$EAGAIN, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	$EAGAIN, (%rax) +#endif +	orl	$-1, %eax +	retq +	.size	sem_trywait,.-sem_trywait +	versioned_symbol(libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S new file mode 100644 index 000000000..63ecd063a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -0,0 +1,120 @@ +/* Copyright (C) 2002, 2003, 2005 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 <sysdep.h> +#include <shlib-compat.h> +#include <pthread-errnos.h> + +#ifndef UP +# define LOCK lock +#else +# define +#endif + +#define SYS_futex		202 + + +	.text + +	.globl	sem_wait +	.type	sem_wait,@function +	.align	16 +	cfi_startproc +sem_wait: +	/* First check for cancellation.  */ +	movl	%fs:CANCELHANDLING, %eax +	andl	$0xfffffff9, %eax +	cmpl	$8, %eax +	je	4f + +	pushq	%r12 +	cfi_adjust_cfa_offset(8) +	cfi_offset(12, -16) +	pushq	%r13 +	cfi_adjust_cfa_offset(8) +	movq	%rdi, %r13 +	cfi_offset(13, -24) + +3:	movl	(%r13), %eax +2:	testl	%eax, %eax +	je	1f + +	leaq	-1(%rax), %rdx +	LOCK +	cmpxchgl %edx, (%r13) +	jne	2b +	xorl	%eax, %eax + +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) + +	retq + +	cfi_adjust_cfa_offset(16) +	cfi_offset(12, -16) +	cfi_offset(13, -24) +1:	call	__pthread_enable_asynccancel +	movl	%eax, %r8d + +	xorq	%r10, %r10 +	movl	$SYS_futex, %eax +	movq	%r13, %rdi +	movq	%r10, %rsi +	movq	%r10, %rdx +	syscall +	movq	%rax, %r12 + +	movl	%r8d, %edi +	call	__pthread_disable_asynccancel + +	testq	%r12, %r12 +	je	3b +	cmpq	$-EWOULDBLOCK, %r12 +	je	3b +	negq	%r12 +#if USE___THREAD +	movq	errno@gottpoff(%rip), %rdx +	movl	%r12d, %fs:(%rdx) +#else +	callq	__errno_location@plt +	movl	%r12d, (%rax) +#endif +	orl	$-1, %eax + +	popq	%r13 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(13) +	popq	%r12 +	cfi_adjust_cfa_offset(-8) +	cfi_restore(12) + +	retq + +4:	/* Canceled.  */ +	movq	$0xffffffffffffffff, %fs:RESULT +	LOCK +	orl	$0x10, %fs:CANCELHANDLING +	movq	%fs:CLEANUP_JMP_BUF, %rdi +	jmp	HIDDEN_JUMPTARGET (__pthread_unwind) +	cfi_endproc +	.size	sem_wait,.-sem_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 000000000..97debaba9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,138 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, 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 + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args)				      \ +  .text;								      \ +  ENTRY (name)								      \ +    SINGLE_THREAD_P;							      \ +    jne L(pseudo_cancel);						      \ +  .type __##syscall_name##_nocancel,@function;				      \ +  .globl __##syscall_name##_nocancel;					      \ +  __##syscall_name##_nocancel:						      \ +    DO_CALL (syscall_name, args);					      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +    ret;								      \ +  .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;	      \ +  L(pseudo_cancel):							      \ +    /* Save registers that might get destroyed.  */			      \ +    SAVESTK_##args							      \ +    PUSHARGS_##args							      \ +    CENABLE								      \ +    /* Restore registers.  */						      \ +    POPARGS_##args							      \ +    /* The return value from CENABLE is argument for CDISABLE.  */	      \ +    movq %rax, (%rsp);							      \ +    movl $SYS_ify (syscall_name), %eax;					      \ +    syscall;								      \ +    movq (%rsp), %rdi;							      \ +    /* Save %rax since it's the error code from the syscall.  */	      \ +    movq %rax, 8(%rsp);							      \ +    CDISABLE								      \ +    movq 8(%rsp), %rax;							      \ +    RESTSTK_##args							      \ +    cmpq $-4095, %rax;							      \ +    jae SYSCALL_ERROR_LABEL;						      \ +  L(pseudo_end): + + +# define PUSHARGS_0	/* Nothing.  */ +# define PUSHARGS_1	PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2	PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3	PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4	PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5	PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6	PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0	/* Nothing.  */ +# define POPARGS_1	POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2	POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3	POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4	POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5	POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6	POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function.  */ +# define SAVESTK_0	subq $24, %rsp; cfi_adjust_cfa_offset (24); +# define SAVESTK_1	SAVESTK_0 +# define SAVESTK_2	SAVESTK_1 +# define SAVESTK_3	subq $40, %rsp; cfi_adjust_cfa_offset (40); +# define SAVESTK_4	SAVESTK_3 +# define SAVESTK_5	subq $56, %rsp; cfi_adjust_cfa_offset (56); +# define SAVESTK_6	SAVESTK_5 + +# define RESTSTK_0	addq $24,%rsp; cfi_adjust_cfa_offset (-24); +# define RESTSTK_1	RESTSTK_0 +# define RESTSTK_2	RESTSTK_1 +# define RESTSTK_3	addq $40, %rsp; cfi_adjust_cfa_offset (-40); +# define RESTSTK_4	RESTSTK_3 +# define RESTSTK_5	addq $56, %rsp; cfi_adjust_cfa_offset (-56); +# define RESTSTK_6	RESTSTK_5 + +# ifdef IS_IN_libpthread +#  define CENABLE	call __pthread_enable_asynccancel; +#  define CDISABLE	call __pthread_disable_asynccancel; +#  define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +#  define CENABLE	call __libc_enable_asynccancel; +#  define CDISABLE	call __libc_disable_asynccancel; +#  define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +#  define CENABLE	call __librt_enable_asynccancel; +#  define CDISABLE	call __librt_disable_asynccancel; +# else +#  error Unsupported library +# 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) +#  else +#   define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +#  endif + +# else + +#  ifndef __ASSEMBLER__ +#   define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +#  else +#   define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +#  endif + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c new file mode 100644 index 000000000..a07b1afe5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_create.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "compat-timer.h" +#include <atomic.h> + + +#define timer_create_alias __timer_create_new +#include "../timer_create.c" + +#undef timer_create +weak_alias(__timer_create_new, timer_create) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c new file mode 100644 index 000000000..8456dc31a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_delete.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "compat-timer.h" + + +#define timer_delete_alias __timer_delete_new +#include "../timer_delete.c" + +#undef timer_delete +weak_alias(__timer_delete_new, timer_delete) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c new file mode 100644 index 000000000..86a2df696 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "compat-timer.h" + + +#define timer_getoverrun_alias __timer_getoverrun_new +#include "../timer_getoverr.c" + +#undef timer_getoverrun +weak_alias(__timer_getoverrun_new, timer_getoverrun) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c new file mode 100644 index 000000000..6b260e453 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_gettime.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "compat-timer.h" + + +#define timer_gettime_alias __timer_gettime_new +#include "../timer_gettime.c" + +#undef timer_gettime +weak_alias(__timer_gettime_new, timer_gettime) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c new file mode 100644 index 000000000..0ec178246 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/timer_settime.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@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; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +#include "compat-timer.h" + + +#define timer_settime_alias __timer_settime_new +#include "../timer_settime.c" + +#undef timer_settime +weak_alias(__timer_settime_new, timer_settime) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 000000000..f68d40439 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,35 @@ +/* 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 <tcb-offsets.h> + +#define SAVE_PID \ +	movl	%fs:PID, %esi;						      \ +	movl	$0x80000000, %ecx;					      \ +	movl	%esi, %edx;						      \ +	negl	%edx;							      \ +	cmove	%ecx, %edx;						      \ +	movl	%edx, %fs:PID + +#define RESTORE_PID \ +	testq	%rax, %rax;						      \ +	je	1f;							      \ +	movl	%esi, %fs:PID;						      \ +1: + +#include <sysdeps/unix/sysv/linux/x86_64/vfork.S>  | 
