diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/sh')
35 files changed, 5804 insertions, 0 deletions
| diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile new file mode 100644 index 000000000..43a6fad84 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch new file mode 100644 index 000000000..9bd7569c9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch @@ -0,0 +1,84 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill <sjhill@uclibc.org> +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_SSRC = pt-vfork.S pthread_once.S pthread_rwlock_wrlock.S \ +			pthread_rwlock_rdlock.S pthread_rwlock_unlock.S \ +			lowlevellock.S pthread_barrier_wait.S pthread_cond_broadcast.S \ +			pthread_cond_signal.S \ +			pthread_rwlock_timedwrlock.S pthread_rwlock_timedrdlock.S \ +			sem_post.S sem_timedwait.S sem_trywait.S sem_wait.S + +libc_a_CSRC = fork.c +libc_a_SSRC = libc-lowlevellock.S clone.S vfork.S + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_once.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_wrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_rdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_barrier_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_broadcast.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_signal.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_cond_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-pthread_rwlock_timedwrlock.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-pthread_rwlock_timedrdlock.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-sem_post.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_timedwait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_trywait.S = -D_LIBC_REENTRANT -DUSE___THREAD +ASFLAGS-sem_wait.S = -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT  -DUSE___THREAD + +ASFLAGS-lowlevellock.S = -DNOT_IN_libc=1 -DIS_IN_libpthread=1 -D_LIBC_REENTRANT -DUSE___THREAD + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +#Needed to use the correct SYSCALL_ERROR_HANDLER +ASFLAGS-clone.S += -DUSE___THREAD +ASFLAGS-vfork.S += -DUSE___THREAD +endif + +CFLAGS += $(SSP_ALL_CFLAGS) +#CFLAGS:=$(CFLAGS:-O1=-O2) + +LINUX_ARCH_DIR:=$(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux/sh +LINUX_ARCH_OUT:=$(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux/sh + +LINUX_ARCH_OBJ:=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libpthread_SSRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(LINUX_ARCH_OBJ:.o=.os) +else +libpthread-a-y += $(LINUX_ARCH_OBJ) +endif +libpthread-so-y += $(LINUX_ARCH_OBJ:.o=.oS) + +libpthread-nomulti-y+=$(LINUX_ARCH_OBJS) + +LIBC_LINUX_ARCH_OBJ:=$(patsubst %.c,$(LINUX_ARCH_OUT)/%.o,$(libc_a_CSRC)) +LIBC_LINUX_ARCH_OBJ+=$(patsubst %.S,$(LINUX_ARCH_OUT)/%.o,$(libc_a_SSRC)) + +libc-static-y+=$(LIBC_LINUX_ARCH_OBJ) +libc-shared-y+=$(LIBC_LINUX_ARCH_OBJ:.o=.oS) + +libc-nomulti-y+=$(LIBC_LINUX_ARCH_OBJ) + +objclean-y+=nptl_linux_arch_clean + +nptl_linux_arch_clean: +	$(do_rm) $(addprefix $(LINUX_ARCH_OUT)/*., o os oS) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h new file mode 100644 index 000000000..969686dd5 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H	1 + +#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_COND_COMPAT_T 12 +#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 + + +/* 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; + + +typedef struct __pthread_internal_slist +{ +  struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling.  The structure of the attribute +   type is not exposed on purpose.  */ +typedef union +{ +  struct __pthread_mutex_s +  { +    int __lock; +    unsigned int __count; +    int __owner; +    /* KIND must stay at this position in the structure to maintain +       binary compatibility.  */ +    int __kind; +    unsigned int __nusers; +    __extension__ union +    { +      int __spins; +      __pthread_slist_t __list; +    }; +  } __data; +  char __size[__SIZEOF_PTHREAD_MUTEX_T]; +  long int __align; +} pthread_mutex_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; +  long 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]; +  long 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 +{ +  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; +    pthread_t __writer; +  } __data; +  char __size[__SIZEOF_PTHREAD_RWLOCK_T]; +  long int __align; +} pthread_rwlock_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; +  long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type.  */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type.  The structure of the type is +   deliberately not exposed.  */ +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIER_T]; +  long int __align; +} pthread_barrier_t; + +typedef union +{ +  char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; +  int __align; +} pthread_barrierattr_t; +#endif + + +#endif	/* bits/pthreadtypes.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h new file mode 100644 index 000000000..e6c5d845c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002 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 + + +#define __SIZEOF_SEM_T	16 + + +/* 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/sh/clone.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S new file mode 100644 index 000000000..918d57926 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <libc/sysdeps/linux/sh/clone.S> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c new file mode 100644 index 000000000..e17c0174b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +/* Value passed to 'clone' for initialization of the thread register.  */ +#define TLS_VALUE (pd + 1) + + +/* Get the real implementation.  */ +#include <sysdeps/pthread/createthread.c> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c new file mode 100644 index 000000000..dcedd2625 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sched.h> +#include <signal.h> +#include <stdio.h> +#include <sysdep.h> +#include <tls.h> + +/* TLS pointer argument is passed as the 5-th argument.  */ +#define ARCH_FORK() \ +  INLINE_SYSCALL (clone, 5,						      \ +		  CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0,     \ +		  NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S new file mode 100644 index 000000000..94a24b46e --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -0,0 +1,19 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include "lowlevellock.S" diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h new file mode 100644 index 000000000..062ce2871 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifdef __ASSEMBLER__ + +#define _IMP1 #1 +#define _IMM1 #-1 +#define _IMM4 #-4 +#define _IMM6 #-6 +#define _IMM8 #-8 + +#define	INC(mem, reg) \ +	.align	2; \ +	mova	99f, r0; \ +	mov	r15, r1; \ +	mov	_IMM6, r15; \ +98:	mov.l	mem, reg; \ +	add	_IMP1, reg; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	DEC(mem, reg) \ +	.align	2; \ +	mova	99f, r0; \ +	mov	r15, r1; \ +	mov	_IMM6, r15; \ +98:	mov.l	mem, reg; \ +	add	_IMM1, reg; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	XADD(reg, mem, new, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM4, r15; \ +98:	mov.l	mem, old; \ +	mov	old, new; \ +	add	reg, new; \ +	mov.l	new, mem; \ +99:	mov	r1, r15 + +#define	XCHG(reg, mem, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM4, r15; \ +98:	mov.l	mem, old; \ +	mov.l	reg, mem; \ +99:	mov	r1, r15 + +#define	CMPXCHG(reg, mem, new, old) \ +	.align	2; \ +	mova	99f, r0; \ +	nop; \ +	mov	r15, r1; \ +	mov	_IMM8, r15; \ +98:	mov.l	mem, old; \ +	cmp/eq	old, reg; \ +	bf	99f; \ +	mov.l	new, mem; \ +99:	mov	r1, r15 + +#endif  /* __ASSEMBLER__ */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S new file mode 100644 index 000000000..a5c916bb7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,296 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + +	.text + +#define SYS_gettimeofday	__NR_gettimeofday + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.globl	__lll_mutex_lock_wait +	.type	__lll_mutex_lock_wait,@function +	.hidden	__lll_mutex_lock_wait +	.align	5 +	/* void __lll_mutex_lock_wait (int val, int *__futex) */ +__lll_mutex_lock_wait: +	mov	#2, r6 +	cmp/eq	r4, r6 +	mov	r5, r4 +	mov	#0, r7		/* No timeout.  */ +	mov	#FUTEX_WAIT, r5 + +	bf	2f + +1: +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +2: +	XCHG (r6, @r4, r2) +	tst	r2, r2 +	bf	1b + +	rts +	 nop +	.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	5 +	/* int __lll_mutex_timedlock_wait (int val, int *__futex, +				       const struct timespec *abstime) */ +__lll_mutex_timedlock_wait: +	/* Check for a valid timeout value.  */ +	mov.l	@(4,r6), r1 +	mov.l	.L1g, r0 +	cmp/hs	r0, r1 +	bt	3f + +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	mov	r6, r9 +	mov	r5, r8 + +	/* Stack frame for the timespec and timeval structs.  */ +	add	#-8, r15 + +1: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(4,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	4f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +4: +	cmp/pz	r2 +	bf	5f		/* Time is already up.  */ + +	mov.l	r2, @r15	/* Store relative timeout.  */ +	mov.l	r3, @(4,r15) + +	mov	#1, r3 +	mov	#2, r6 +	CMPXCHG (r3, @r8, r6, r2) +	tst	r2, r2 +	bt	8f + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r4 + +8: +	mov	#0, r3 +	CMPXCHG (r3, @r8, r6, r2) +	bf/s	7f +	mov	#0, r0 + +6: +	add	#8, r15 +	mov.l	@r15+, r8 +	rts +	mov.l	@r15+, r9 +7: +	/* Check whether the time expired.  */ +	mov	#-ETIMEDOUT, r1 +	cmp/eq	r5, r1 +	bt	5f + +	/* Make sure the current holder knows we are going to sleep.  */ +	XCHG (r2, @r8, r3) +	tst	r3, r3 +	bt/s	6b +	mov	#0, r0 +	bra	1b +	nop +3: +	rts +	mov	#EINVAL, r0 +5: +	bra	6b +	mov	#ETIMEDOUT, r0 + +.L1k: +	.word	1000 +	.align	2 +.L1g: +	.long	1000000000 + +	.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	5 +lll_unlock_wake_cb: +	DEC	(@r4, r2) +	tst	r2, r2 +	bt	1f + +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6		/* Wake one thread.  */ +	mov	#0, r7 +	mov.l	r7, @r4		/* Stores 0.  */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +1: +	rts +	nop +	.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	5 +	/* void __lll_mutex_unlock_wake(int *__futex) */ +__lll_mutex_unlock_wake: +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6		/* Wake one thread.  */ +	mov	#0, r7 +	mov.l	r7, @r4		/* Stores 0.  */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	rts +	nop +	.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	5 +__lll_timedwait_tid: +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Stack frame for the timespec and timeval structs.  */ +	add	#-8, r15 + +2: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(4,r15), r0 +	mov.w	.L1k2, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	5f +	mov.l	.L1g2, r1 +	add	r1, r3 +	add	#-1, r2 +5: +	cmp/pz	r2 +	bf	6f		/* Time is already up.  */ + +	mov.l	r2, @r15	/* Store relative timeout.  */ +	mov.l	r3, @(4,r15) + +	mov.l	@r8, r2 +	tst	r2, r2 +	bt	4f + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r2, r6 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	@r8, r2 +	tst	r2, r2 +	bf	1f +4: +	mov	#0, r0 +3: +	add	#8, r15 +	mov.l	@r15+, r8 +	rts +	mov.l	@r15+, r9 +1: +	/* Check whether the time expired.  */ +	mov	#-ETIMEDOUT, r1 +	cmp/eq	r0, r1 +	bf	2b +6: +	bra	3b +	mov	#ETIMEDOUT, r0 + +.L1k2: +	.word	1000 +	.align	2 +.L1g2: +	.long	1000000000 +	.size	__lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h new file mode 100644 index 000000000..45339f5e0 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,294 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H	1 + +#include <syscall.h> +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> + +#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) + +extern int __lll_mutex_lock_wait (int val, int *__futex) attribute_hidden; +extern int __lll_mutex_timedlock_wait (int val, int *__futex, +				       const struct timespec *abstime) +     attribute_hidden; +extern int __lll_mutex_unlock_wake (int *__futex) attribute_hidden; + + +#define lll_mutex_trylock(futex) \ +  ({ unsigned char __result; \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%1,r2\n\ +	cmp/eq r2,%3\n\ +	bf 1f\n\ +	mov.l %2,@%1\n\ +     1: mov r1,r15\n\ +	mov #-1,%0\n\ +	negc %0,%0"\ +	: "=r" (__result) \ +	: "r" (&(futex)), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \ +	: "r0", "r1", "r2", "t", "memory"); \ +     __result; }) + +#define lll_mutex_cond_trylock(futex) \ +  ({ unsigned char __result; \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%1,r2\n\ +	cmp/eq r2,%3\n\ +	bf 1f\n\ +	mov.l %2,@%1\n\ +     1: mov r1,r15\n\ +	mov #-1,%0\n\ +	negc %0,%0"\ +	: "=r" (__result) \ +	: "r" (&(futex)), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ +	  "r" (LLL_MUTEX_LOCK_INITIALIZER) \ +	: "r0", "r1", "r2", "t", "memory"); \ +     __result; }) + +#define lll_mutex_lock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		nop\n\ +		mov r15,r1\n\ +		mov #-8,r15\n\ +	     0: mov.l @%2,%0\n\ +		tst %0,%0\n\ +		bf 1f\n\ +		mov.l %1,@%2\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (1), "r" (__futex) \ +		: "r0", "r1", "t", "memory"); \ +	    if (__result) \ +	      __lll_mutex_lock_wait (__result, __futex); }) + +/* Special version of lll_mutex_lock which causes the unlock function to +   always wakeup waiters.  */ +#define lll_mutex_cond_lock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		nop\n\ +		mov r15,r1\n\ +		mov #-8,r15\n\ +	     0: mov.l @%2,%0\n\ +		tst %0,%0\n\ +		bf 1f\n\ +		mov.l %1,@%2\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (2), "r" (__futex) \ +		: "r0", "r1", "t", "memory"); \ +	    if (__result) \ +	      __lll_mutex_lock_wait (__result, __futex); }) + +#define lll_mutex_timedlock(futex, timeout) \ +  ({ int __result, *__futex = &(futex); \ +     __asm __volatile ("\ +	.align 2\n\ +	mova 1f,r0\n\ +	nop\n\ +	mov r15,r1\n\ +	mov #-8,r15\n\ +     0: mov.l @%2,%0\n\ +	tst %0,%0\n\ +	bf 1f\n\ +	mov.l %1,@%2\n\ +     1: mov r1,r15"\ +	: "=&r" (__result) : "r" (1), "r" (__futex) \ +	: "r0", "r1", "t", "memory"); \ +    if (__result) \ +      __result = __lll_mutex_timedlock_wait (__result, __futex, timeout); \ +    __result; }) + +#define lll_mutex_unlock(futex) \ +  (void) ({ int __result, *__futex = &(futex); \ +	    __asm __volatile ("\ +		.align 2\n\ +		mova 1f,r0\n\ +		mov r15,r1\n\ +		mov #-6,r15\n\ +	     0: mov.l @%1,%0\n\ +		add #-1,%0\n\ +		mov.l %0,@%1\n\ +	     1: mov r1,r15"\ +		: "=&r" (__result) : "r" (__futex) \ +		: "r0", "r1", "memory"); \ +	    if (__result) \ +	      __lll_mutex_unlock_wake (__futex); }) + +#define lll_mutex_islocked(futex) \ +  (futex != 0) + + +/* 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) + + +# ifdef NEED_SYSCALL_INST_PAD +#  define SYSCALL_WITH_INST_PAD "\ +	trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +#  define SYSCALL_WITH_INST_PAD "\ +	trapa #0x14" +# endif + +#define lll_futex_wait(futex, val) \ +  do {									      \ +    int __ignore;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAIT;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (val);	      \ +    register unsigned long __r7 __asm ("r7") = 0;				      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__ignore)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +  } while (0) + +#define lll_futex_timed_wait(futex, val, timeout) \ +  ({									      \ +    int __status;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAIT;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (val);	      \ +    register unsigned long __r7 __asm ("r7") = (timeout);			      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__status)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +    __status;								      \ +  }) + + +#define lll_futex_wake(futex, nr) \ +  do {									      \ +    int __ignore;							      \ +    register unsigned long __r3 __asm ("r3") = SYS_futex;			      \ +    register unsigned long __r4 __asm ("r4") = (unsigned long) (futex);	      \ +    register unsigned long __r5 __asm ("r5") = FUTEX_WAKE;		      \ +    register unsigned long __r6 __asm ("r6") = (unsigned long) (nr);	      \ +    register unsigned long __r7 __asm ("r7") = 0;				      \ +    __asm __volatile (SYSCALL_WITH_INST_PAD				      \ +		      : "=z" (__ignore)					      \ +		      : "r" (__r3), "r" (__r4), "r" (__r5),		      \ +			"r" (__r6), "r" (__r7)				      \ +		      : "memory", "t");					      \ +  } while (0) + + +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 */ + +#define lll_trylock(futex) lll_mutex_trylock (futex) +#define lll_lock(futex) lll_mutex_lock (futex) +#define lll_unlock(futex) lll_mutex_unlock (futex) + +#define lll_islocked(futex) \ +  (futex != LLL_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.  */ + +extern int __lll_wait_tid (int *tid) attribute_hidden; +#define lll_wait_tid(tid) \ +  do {									      \ +    __typeof (tid) *__tid = &(tid);					      \ +    while (*__tid != 0)							      \ +      lll_futex_wait (__tid, *__tid);					      \ +  } 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/sh/not-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h new file mode 100644 index 000000000..eb83653d3 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/not-cancel.h @@ -0,0 +1,82 @@ +/* Uncancelable versions of cancelable interfaces.  Linux/NPTL version. +   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 <sysdep.h> + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +extern int __close_nocancel (int) attribute_hidden; +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; + +libc_hidden_proto(__open_nocancel) +libc_hidden_proto(__close_nocancel) +libc_hidden_proto(__read_nocancel) +libc_hidden_proto(__write_nocancel) +libc_hidden_proto(__waitpid_nocancel) + +#else +#define __open_nocancel(name, ...) __open (name, __VA_ARGS__) +#define __close_nocancel(fd) __close (fd) +#define __read_nocancel(fd, buf, len) __read (fd, buf, len) +#define __write_nocancel(fd, buf, len) __write (fd, buf, len) +#define __waitpid_nocancel(pid, stat_loc, options) \ +  __waitpid (pid, stat_loc, options) +#endif + +/* Uncancelable open.  */ +#define open_not_cancel(name, flags, mode) \ +   __open_nocancel (name, flags, mode) +#define open_not_cancel_2(name, flags) \ +   __open_nocancel (name, flags) + +/* Uncancelable close.  */ +#define close_not_cancel(fd) \ +  __close_nocancel (fd) +#define close_not_cancel_no_status(fd) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read.  */ +#define read_not_cancel(fd, buf, n) \ +  __read_nocancel (fd, buf, n) + +/* Uncancelable write.  */ +#define write_not_cancel(fd, buf, n) \ +  __write_nocancel (fd, buf, n) + +/* Uncancelable writev.  */ +#define writev_not_cancel_no_status(fd, iov, n) \ +  (void) ({ INTERNAL_SYSCALL_DECL (err);				      \ +	    INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl.  */ +#define fcntl_not_cancel(fd, cmd, val) \ +  __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid.  */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ +  __waitpid_nocancel (pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ +  INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 000000000..5391d5cc8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for SH. NPTL version. +   Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it +   and/or modify it under the terms of the GNU Library General Public +   License as published by the Free Software Foundation; either +   version 2 of the License, or (at your option) any later version. + +   In addition to the permissions in the GNU Library General Public +   License, the Free Software Foundation gives you unlimited +   permission to link the compiled version of this file with other +   programs, and to distribute those programs without any restriction +   coming from the use of this file.  (The Library General Public +   License restrictions do apply in other respects; for example, they +   cover modification of the file, and distribution when not linked +   into another program.) + +   The GNU C Library is distributed in the hope that it will be +   useful, but WITHOUT ANY WARRANTY; without even the implied warranty +   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +/* This file is compiled into assembly code which is then munged by a sed +   script into two files: crti.s and crtn.s. + +   * crti.s puts a function prologue at the beginning of the +   .init and .fini sections and defines global symbols for +   those addresses, so they can be called as functions. + +   * crtn.s puts the corresponding function epilogues +   in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +	.section .init\n\ +	.align 5\n\ +	.global	_init\n\ +	.type	_init,@function\n\ +_init:\n\ +	mov.l	r12,@-r15\n\ +	mov.l	r14,@-r15\n\ +	sts.l	pr,@-r15\n\ +	mova	.L22,r0\n\ +	mov.l	.L22,r12\n\ +	add	r0,r12\n\ +	mova	.L24,r0\n\ +	mov.l	.L24,r1\n\ +	add	r0,r1\n\ +	jsr	@r1\n\ +	 nop\n\ +	mova	.L23,r0\n\ +	mov.l	.L23,r1\n\ +	add	r0,r1\n\ +	jsr	@r1\n\ +	 mov	r15,r14\n\ +	bra	1f\n\ +	 nop\n\ +	.align 2\n\ +.L22:\n\ +	.long	_GLOBAL_OFFSET_TABLE_\n\ +.L23:\n\ +	.long	__gmon_start__@PLT\n\ +.L24:\n\ +	.long	__pthread_initialize_minimal_internal@PLT\n\ +1:\n\ +	ALIGN\n\ +	END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ +	.section .init\n\ +	mov	r14,r15\n\ +	lds.l	@r15+,pr\n\ +	mov.l	@r15+,r14\n\ +	rts	\n\ +	mov.l	@r15+,r12\n\ +	END_INIT\n\ +	.section .text\n\ +	.align 5\n\ +	.weak	__gmon_start__\n\ +	.type	__gmon_start__,@function\n\ +__gmon_start__:\n\ +	mov.l	r14,@-r15\n\ +	mov	r15,r14\n\ +	mov	r14,r15\n\ +	rts	\n\ +	mov.l	@r15+,r14\n\ +	\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ +	.section .fini\n\ +	.align 5\n\ +	.global	_fini\n\ +	.type	_fini,@function\n\ +_fini:\n\ +	mov.l	r12,@-r15\n\ +	mov.l	r14,@-r15\n\ +	sts.l	pr,@-r15\n\ +	mova	.L27,r0\n\ +	mov.l	.L27,r12\n\ +	add	r0,r12\n\ +	mov	r15,r14\n\ +	ALIGN\n\ +	END_FINI\n\ +	bra	1f\n\ +	 nop\n\ +	.align	2\n\ +.L27:\n\ +	.long	_GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ +	.section .fini\n\ +	mov	r14,r15\n\ +	lds.l	@r15+,pr\n\ +	mov.l	@r15+,r14\n\ +	rts	\n\ +	mov.l	@r15+,r12\n\ +\n\ +	END_FINI\n\ +	\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S new file mode 100644 index 000000000..54f2281d7 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. +   The calling process is suspended until the new process exits or is +   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	/* Save the PID value.  */ +	stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	@(r0,r2), r4 +	neg	r4, r1 +	mov.l	r1, @(r0,r2) + +	mov.w	.L1, r3 +	trapa	#0x10 +	mov     r0, r1 + +	/* Restore the old PID value in the parent.  */ +	tst	r0, r0 +	bt/s	2f +	 stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	r4, @(r0,r2) +	mov	r1, r0 +2: +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1			// r1=0 means r0 = -1 to -4095 +	tst	r1, r1			// i.e. error in linux +	bf	.Lpseudo_end +	SYSCALL_ERROR_HANDLER +.Lpseudo_end: +	rts +	 nop +.L1: +	.word	__NR_vfork +.L2: +	.word	PID - TLS_PRE_TCB_SIZE + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S new file mode 100644 index 000000000..608c7364c --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,191 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelbarrier.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + + +	.text + +	.globl	pthread_barrier_wait +	.type	pthread_barrier_wait,@function +	.align	5 +pthread_barrier_wait: +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the mutex.  */ +	mov	#0, r3 +	mov	#1, r4 +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +	bf	1f + +	/* One less waiter.  If this was the last one needed wake +	   everybody.  */ +2: +	mov.l	@(LEFT,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(LEFT,r8) +	tst	r0, r0 +	bt	3f + +	/* There are more threads to come.  */ +	mov.l	@(CURR_EVENT,r8), r6 + +	/* Release the mutex.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	6f +7: +	/* Wait for the remaining threads.  The call will return immediately +	   if the CURR_EVENT memory has meanwhile been changed.  */ +	mov	r8, r4 +#if CURR_EVENT != 0 +	add	#CURR_EVENT, r4 +#endif +	mov	#FUTEX_WAIT, r5 +	mov	#0, r7 +8: +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Don't return on spurious wakeups.  The syscall does not change +	   any register except r0 so there is no need to reload any of +	   them.  */ +	mov.l	@(CURR_EVENT,r8), r0 +	cmp/eq	r0, r6 +	bt	8b + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	INC	(@(LEFT,r8), r2) +	mov.l	@(INIT_COUNT,r8), r4 +	cmp/eq	r2, r4 +	bf	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.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	9f + +10: +	mov	#0, r0		/* != PTHREAD_BARRIER_SERIAL_THREAD */ +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	rts +	 mov.l	@r15+, r9 + +3: +	/* The necessary number of threads arrived.  */ +	mov.l	@(CURR_EVENT,r8), r1 +	add	#1, r1 +	mov.l	r1, @(CURR_EVENT,r8) + +	/* Wake up all waiters.  The count is a signed number in the kernel +	   so 0x7fffffff is the highest value.  */ +	mov.l	.Lall, r6 +	mov	r8, r4 +#if CURR_EVENT != 0 +	add	#CURR_EVENT, r4 +#endif +	mov	#0, r7 +	mov	#FUTEX_WAKE, r5 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Increment LEFT.  If this brings the count back to the +	   initial count unlock the object.  */ +	INC	(@(LEFT,r8), r2) +	mov.l	@(INIT_COUNT,r8), r4 +	cmp/eq	r2, r4 +	bf	5f + +	/* Release the mutex.  */ +	DEC (@(MUTEX,r8), r2) +	tst	r2, r2 +	bf	4f +5: +	mov	#-1, r0		/* == PTHREAD_BARRIER_SERIAL_THREAD */ +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	rts +	 mov.l	@r15+, r9 + +1: +	mov	r2, r4 +	mov	r8, r5 +	mov.l	.Lwait0, r1 +	bsrf	r1 +	 add	#MUTEX, r5 +.Lwait0b: +	bra	2b +	 nop + +4: +	mov	r8, r4 +	mov.l	.Lwake0, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake0b: +	bra	5b +	 nop + +6: +	mov	r6, r9 +	mov	r8, r4 +	mov.l	.Lwake1, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake1b: +	bra	7b +	 mov	r9, r6 + +9: +	mov	r6, r9 +	mov	r8, r4 +	mov.l	.Lwake2, r1 +	bsrf	r1 +	 add	#MUTEX, r4 +.Lwake2b: +	bra	10b +	 mov	r9, r6 + +	.align	2 +.Lall: +	.long	0x7fffffff +.Lwait0: +	.long	__lll_mutex_lock_wait-.Lwait0b +.Lwake0: +	.long	__lll_mutex_unlock_wake-.Lwake0b +.Lwake1: +	.long	__lll_mutex_unlock_wake-.Lwake1b +.Lwake2: +	.long	__lll_mutex_unlock_wake-.Lwake2b +	.size	pthread_barrier_wait,.-pthread_barrier_wait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S new file mode 100644 index 000000000..36eccf1e6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,210 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + +#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	5 +__pthread_cond_broadcast: +	mov.l   r10, @-r15 +	mov.l   r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	1f +2: +	mov.l	@(total_seq+4,r8),r0 +	mov.l	@(total_seq,r8),r1 +	mov.l	@(wakeup_seq+4,r8), r2 +	cmp/hi	r2, r0 +	bt	3f +	cmp/hi	r0, r2 +	bt	4f +	mov.l	@(wakeup_seq,r8), r2 +	cmp/hi	r2, r1 +	bf	4f + +3: +	/* Cause all currently waiting threads to recognize they are +	   woken up.  */ +	mov.l	r1, @(wakeup_seq,r8) +	mov.l	r0, @(wakeup_seq+4,r8) +	mov.l	r1, @(woken_seq,r8) +	mov.l	r0, @(woken_seq+4,r8) +	mov.l	@(broadcast_seq,r8), r2 +	add	#1, r2 +	mov.l	r2, @(broadcast_seq,r8) +	add	r1, r1 +	mov	r1, r10 +	mov.l	r10, @(cond_futex,r8) + +	/* Get the address of the mutex used.  */ +	mov.l	@(dep_mutex,r8), r9 + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	7f + +8: +	/* Don't use requeue for pshared condvars.  */ +	mov	#-1, r0 +	cmp/eq	r0, r9 +	mov	r8, r4 +	bt/s	9f +	 add	#cond_futex, r4 + +	/* Wake up all threads.  */ +	mov	#FUTEX_CMP_REQUEUE, r5 +	mov	#1, r6 +	mov	#-1, r7 +	shlr	r7		/* r7 = 0x7fffffff */ +	mov	r9, r0 +# if MUTEX_FUTEX != 0 +	add	#MUTEX_FUTEX, r0 +# endif +	mov	r10, r1 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x16 +	SYSCALL_INST_PAD + +	/* For any kind of error, which mainly is EAGAIN, we try again +	   with WAKE.  The general test also covers running on old +	   kernels.  */ +	mov	r0, r1 +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1 +	tst	r1, r1 +	mov	r8, r4 +	bt/s	9f +	 add	#cond_futex, r4 + +10: +	mov	#0, r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r10 + +4: +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	5f +6: +	mov	#0, r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r10 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait5, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait5b: +	bra	2b +	 nop + +5: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake5, r1 +	bsrf	r1 +	 nop +.Lmwake5b: +	bra	6b +	 nop + +7: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake6, r1 +	bsrf	r1 +	 nop +.Lmwake6b: +	bra	8b +	 nop + +9: +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	bra	10b +	 nop + +	.align	2 +.Lmwait5: +	.long	__lll_mutex_lock_wait-.Lmwait5b +.Lmwake5: +	.long	__lll_mutex_unlock_wake-.Lmwake5b +.Lmwake6: +	.long	__lll_mutex_unlock_wake-.Lmwake6b +	.size	__pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias (__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S new file mode 100644 index 000000000..d92f11cbb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,135 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <bits/kernel-features.h> +#include "lowlevel-atomic.h" + +#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	5 +__pthread_cond_signal: +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	1f +2: +	mov.l	@(total_seq+4,r8),r0 +	mov.l	@(total_seq,r8),r1 +	mov.l	@(wakeup_seq+4,r8), r2 +	cmp/hi	r2, r0 +	bt	3f +	cmp/hi	r0, r2 +	bt	4f +	mov.l	@(wakeup_seq,r8), r2 +	cmp/hi	r2, r1 +	bf	4f + +3: +	/* Bump the wakeup number.  */ +	mov	#1, r2 +	mov	#0, r3 +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	/* Wake up one thread.  */ +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +4: +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	5f +6: +	mov	#0, r0 +	lds.l	@r15+, pr +	rts +	 mov.l	@r15+, r8 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait4, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait4b: +	bra	2b +	 nop + +5: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake4, r1 +	bsrf	r1 +	 nop +.Lmwake4b: +	bra	6b +	 nop + +	.align	2 +.Lmwait4: +	.long	__lll_mutex_lock_wait-.Lmwait4b +.Lmwake4: +	.long	__lll_mutex_unlock_wake-.Lmwake4b +	.size	__pthread_cond_signal, .-__pthread_cond_signal +weak_alias (__pthread_cond_signal, pthread_cond_signal) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S new file mode 100644 index 000000000..5812488b2 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,768 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.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	5 +__pthread_cond_timedwait: +.LSTARTCODE: +	mov.l	r8, @-r15 +.Lpush_r8: +	mov.l	r9, @-r15 +.Lpush_r9: +	mov.l	r10, @-r15 +.Lpush_r10: +	mov.l	r11, @-r15 +.Lpush_r11: +	mov.l	r12, @-r15 +.Lpush_r12: +	mov.l	r13, @-r15 +.Lpush_r13: +	sts.l	pr, @-r15 +.Lpush_pr: +	add	#-64, r15 +.Lalloc: +	mov	r4, r8 +	mov	r5, r9 +	mov	r6, r13 +#ifdef __PIC__ +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 +#endif + +	mov.l	@(4,r13), r0 +	mov.l	.L1g, r1 +	cmp/hs	r1, r0 +	bf	0f +	bra	18f +	 mov	#EINVAL, r0 +0: +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	2f +	bra	1f +	 nop +#ifdef __PIC__ +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#endif + +2: +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +	mov.l	@(dep_mutex,r8),r0 +	cmp/eq	#-1, r0 +	bt	17f +	mov.l	r9, @(dep_mutex,r8) + +17: +	/* Unlock the mutex.  */ +	mov.l	.Lmunlock1, r1 +	mov	#0, r5 +	bsrf	r1 +	 mov	r9, r4 +.Lmunlock1b: + +	tst	r0, r0 +	bt	0f +	bra	16f +	 nop +0: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(total_seq,r8) +	mov.l	r1,@(total_seq+4,r8) +	mov.l	@(cond_futex,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_futex,r8) +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_nwaiters,r8) + +	/* Get and store current wakeup_seq value.  */ +	mov.l	@(wakeup_seq,r8), r10 +	mov.l	@(wakeup_seq+4,r8), r11 +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	r0, @(4,r15) + +8: +	/* Get current time.  */ +#ifdef __NR_clock_gettime +	/* Get the clock number.	 */ +	mov.l	@(cond_nwaiters,r8), r4 +	mov	#((1 << clock_bits) - 1), r0 +	and	r0, r4 +	/* Only clocks 0 and 1 are allowed.  Both are handled in the +	   kernel.  */ +	mov	r15, r5 +	add	#16, r5 +	mov.w	.L__NR_clock_gettime, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD +# ifndef __ASSUME_POSIX_TIMERS +	cmp/eq	#-ENOSYS, r0 +	bt	19f +# endif + +	/* Compute relative timeout.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	bra	0f +	 mov.l	@(20,r15), r1 +.L__NR_clock_gettime: +	.word	__NR_clock_gettime + +# ifndef __ASSUME_POSIX_TIMERS +19: +	mov	r15, r4 +	add	#16, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(20,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	sts	macl, r1 +#endif +0: +#else +	mov	r15, r4 +	add	#16, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	/* Compute relative timeout.  */ +	mov.l	@(20,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Micro seconds to nano seconds.  */ +	mov.l	@r13, r2 +	mov.l	@(4,r13), r3 +	mov.l	@(16,r15), r0 +	sts	macl, r1 +#endif +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	12f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +12: +	mov	#-ETIMEDOUT, r1 +	mov.l	r1, @(12,r15) +	cmp/pz	r2 +	bf	6f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @(16,r15) +	mov.l	r3, @(20,r15) +	mov.l	@(cond_futex,r8), r1 +	mov.l	r1, @(8,r15) + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	4f +	bra	3f +	 nop +4: +.LcleanupSTART: +	mov.l	.Lenable1, r1 +	bsrf	r1 +	 nop +.Lenable1b: +	mov.l	r0, @r15 + +	mov	r15, r7 +	add	#16, r7 +	mov	#FUTEX_WAIT, r5 +	mov.l	@(8,r15), r6 +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov.l	r0, @(12,r15) + +	mov.l	.Ldisable1, r1 +	bsrf	r1 +	 mov.l	@r15, r4 +.Ldisable1b: +.LcleanupEND: + +	/* Lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	5f +6: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	23f + +	mov.l	@(woken_seq,r8), r0 +	mov.l	@(woken_seq+4,r8), r1 + +	mov.l	@(wakeup_seq,r8), r2 +	mov.l	@(wakeup_seq+4,r8), r3 + +	cmp/eq	r3, r11 +	bf	7f +	cmp/eq	r2, r10 +	bt	15f +7: +	cmp/eq	r1, r3 +	bf	9f +	cmp/eq	r0, r2 +	bf	9f +15: +	mov.l	@(12,r15),r0 +	cmp/eq	#-ETIMEDOUT, r0 +	bf	8b + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) +	mov	#ETIMEDOUT, r0 +	bra	14f +	 mov.l	r0, @(24,r15) + +23: +	mov	#0, r0 +	bra	24f +	 mov.l	r0, @(24,r15) + +9: +	mov	#0, r0 +	mov.l	r0, @(24,r15) +14: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +24: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	25f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	25f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +25: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	mov	r9, r4 +	mov.l	.Lmlocki1, r1 +	bsrf	r1 +	 nop +.Lmlocki1b: + +	/* We return the result of the mutex_lock operation if it failed.  */ +	tst	r0, r0 +	bf	18f +	mov.l	@(24,r15), r0 + +18: +	add	#64, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r13 +	mov.l	@r15+, r12 +	mov.l	@r15+, r11 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r8 + +.L1k: +	.word	1000 +	.align	2 +.Lmunlock1: +	.long	__pthread_mutex_unlock_usercnt-.Lmunlock1b +.Lenable1: +	.long	__pthread_enable_asynccancel-.Lenable1b +.Ldisable1: +	.long	__pthread_disable_asynccancel-.Ldisable1b +.Lmlocki1: +	.long	__pthread_mutex_cond_lock-.Lmlocki1b +.L1g: +	.long	1000000000 + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait2, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait2b: +	bra	2b +	 nop + +3: +	/* Unlock in loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake2, r1 +	bsrf	r1 +	 nop +.Lmwake2b: +	bra	4b +	 nop + +5: +	/* Locking in loop failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait3, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait3b: +	bra	6b +	 nop + +10: +	/* Unlock after loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake3, r1 +	bsrf	r1 +	 nop +.Lmwake3b: +	bra	11b +	 nop + +16: +	/* The initial unlocking of the mutex failed.  */ +	mov.l	r0, @(24,r15) +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	17f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake4, r1 +	bsrf	r1 +	 nop +.Lmwake4b: +17: +	bra	18b +	 mov.l	@(24,r15), r0 + +	.align	2 +.Lmwait2: +	.long	__lll_mutex_lock_wait-.Lmwait2b +.Lmwake2: +	.long	__lll_mutex_unlock_wake-.Lmwake2b +.Lmwait3: +	.long	__lll_mutex_lock_wait-.Lmwait3b +.Lmwake3: +	.long	__lll_mutex_unlock_wake-.Lmwake3b +.Lmwake4: +	.long	__lll_mutex_unlock_wake-.Lmwake4b +	.size	__pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + + +	.type	__condvar_tw_cleanup, @function +__condvar_tw_cleanup: +	mov	r4, r11 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	1f +	 nop + +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait5, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait5b: + +1: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	3f + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +3: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov	#0, r10 +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	4f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	4f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	#1, r10 + +4: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	2f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake5, r1 +	bsrf	r1 +	 nop +.Lmwake5b: + +2: +	/* Wake up all waiters to make sure no signal gets lost.  */ +	tst	r10, r10 +	bf/s	5f +	 mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +5: +        mov.l   .Lmlocki5, r1 +        bsrf    r1 +         mov     r9, r4 +.Lmlocki5b: + +.LcallUR: +	mov.l	.Lresume, r1 +#ifdef __PIC__ +	add	r12, r1 +#endif +	jsr	@r1 +	 mov	r11, r4 +	sleep + +	.align	2 +.Lmwait5: +	.long   __lll_mutex_lock_wait-.Lmwait5b +.Lmwake5: +        .long   __lll_mutex_unlock_wake-.Lmwake5b +.Lmlocki5: +	.long   __pthread_mutex_cond_lock-.Lmlocki5b +.Lresume: +#ifdef __PIC__ +	.long	_Unwind_Resume@GOTOFF +#else +	.long	_Unwind_Resume +#endif +.LENDCODE: +	.size	__condvar_tw_cleanup, .-__condvar_tw_cleanup + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				! @LPStart format (omit) +	.byte	0xff				! @TType format (omit) +	.byte	0x0b				! call-site format +						! DW_EH_PE_sdata4 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.ualong	.LcleanupSTART-.LSTARTCODE +	.ualong	.LcleanupEND-.LcleanupSTART +	.ualong	__condvar_tw_cleanup-.LSTARTCODE +	.uleb128  0 +	.ualong	.LcallUR-.LSTARTCODE +	.ualong	.LENDCODE-.LcallUR +	.ualong	0 +	.uleb128  0 +.Lcstend: + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE. +.LSTARTCIE: +	.ualong	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 -4				! Data alignment factor. +	.byte	0x11				! 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 +	.ualong	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 6				! Augmentation value length. +	.byte	0x0				! Personality: absolute +	.ualong	__gcc_personality_v0 +	.byte	0x0				! LSDA Encoding: absolute +#endif +	.byte 0x0c				! DW_CFA_def_cfa +	.uleb128 0xf +	.uleb128 0 +	.align 2 +.LENDCIE: + +	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE. +.LSTARTFDE: +	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer. +#ifdef SHARED +	.ualong	.LSTARTCODE-.			! PC-relative start address +						! of the code. +#else +	.ualong	.LSTARTCODE			! Start address of the code. +#endif +	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code. +	.uleb128 4				! Augmentation size +#ifdef SHARED +	.ualong	.LexceptSTART-. +#else +	.ualong	.LexceptSTART +#endif +	.byte	0x4 +	.ualong	.Lpush_r8-.LSTARTCODE +	.byte	0xe +	.uleb128 4 +	.byte	0x88 +	.uleb128 1 +	.byte	0x4 +	.ualong	.Lpush_r9-.Lpush_r8 +	.byte	0xe +	.uleb128 8 +	.byte	0x89 +	.uleb128 2 +	.byte	0x4 +	.ualong	.Lpush_r10-.Lpush_r9 +	.byte	0xe +	.uleb128 12 +	.byte	0x8a +	.uleb128 3 +	.byte	0x4 +	.ualong	.Lpush_r11-.Lpush_r10 +	.byte	0xe +	.uleb128 16 +	.byte	0x8b +	.uleb128 4 +	.byte	0x4 +	.ualong	.Lpush_r12-.Lpush_r11 +	.byte	0xe +	.uleb128 20 +	.byte	0x8c +	.uleb128 5 +	.byte	0x4 +	.ualong	.Lpush_r13-.Lpush_r12 +	.byte	0xe +	.uleb128 24 +	.byte	0x8d +	.uleb128 6 +	.byte	0x4 +	.ualong	.Lpush_pr-.Lpush_r13 +	.byte	0xe +	.uleb128 28 +	.byte	0x91 +	.uleb128 7 +	.byte	0x4 +	.ualong	.Lalloc-.Lpush_pr +	.byte	0xe +	.uleb128 92 +	.align	2 +.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 4 +	.type   DW.ref.__gcc_personality_v0, @object +	.size   DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: +	.long   __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S new file mode 100644 index 000000000..c7df9bf86 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,625 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)  */ +	.globl	__pthread_cond_wait +	.type	__pthread_cond_wait, @function +	.align	5 +__pthread_cond_wait: +.LSTARTCODE: +	mov.l	r8, @-r15 +.Lpush_r8: +	mov.l	r9, @-r15 +.Lpush_r9: +	mov.l	r10, @-r15 +.Lpush_r10: +	mov.l	r11, @-r15 +.Lpush_r11: +	mov.l	r12, @-r15 +.Lpush_r12: +	sts.l	pr, @-r15 +.Lpush_pr: +	add	#-48, r15 +.Lalloc: +	mov	r4, r8 +	mov	r5, r9 +#ifdef __PIC__ +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 +#endif + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	2f +	bra	1f +	 nop +#ifdef __PIC__ +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#endif + +2: +	/* Store the reference to the mutex.  If there is already a +	   different value in there this is a bad user bug.  */ +	mov.l	@(dep_mutex,r8),r0 +	cmp/eq	#-1, r0 +	bt	15f +	mov.l	r9, @(dep_mutex,r8) + +15: +	/* Unlock the mutex.  */ +	mov.l	.Lmunlock0, r1 +	mov	#0, r5 +	bsrf	r1 +	 mov	r9, r4 +.Lmunlock0b: + +	tst	r0, r0 +	bt	0f +	bra	12f +	 nop +0: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(total_seq,r8) +	mov.l	r1,@(total_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8), r0 +	add	r2, r0 +	mov.l	r0, @(cond_nwaiters,r8) + +	/* Get and store current wakeup_seq value.  */ +	mov.l	@(wakeup_seq,r8), r10 +	mov.l	@(wakeup_seq+4,r8), r11 +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	r0, @(4,r15) + +8: +	mov.l	@(cond_futex,r8),r0 +	mov.l	r0, @(8,r15) + +	/* Unlock.  */ +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	3f +4: +.LcleanupSTART: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov.l	r0, @r15 + +	mov	#0, r7 +	mov	#FUTEX_WAIT, r5 +	mov.l	@(8,r15), r6 +	mov	r8, r4 +	add	#cond_futex, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	bsrf	r1 +	 mov.l	@r15, r4 +.Ldisable0b: +.LcleanupEND: + +	/* Lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bf	5f +6: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	16f + +	mov.l	@(woken_seq,r8), r0 +	mov.l	@(woken_seq+4,r8), r1 + +	mov.l	@(wakeup_seq,r8), r2 +	mov.l	@(wakeup_seq+4,r8), r3 + +	cmp/eq	r3, r11 +	bf	7f +	cmp/eq	r2, r10 +	bt	8b +7: +	cmp/eq	r1, r3 +	bf	9f +	cmp/eq	r0, r2 +	bt	8b +9: +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +16: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	17f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	17f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +17: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	mov.l	.Lmlocki0, r1 +	bsrf	r1 +	 mov	r9, r4 +.Lmlocki0b: +	/* We return the result of the mutex_lock operation.  */ + +14: +	add	#48, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r11 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	rts +	 mov.l	@r15+, r8 + +	.align	2 +.Lmunlock0: +	.long	__pthread_mutex_unlock_usercnt-.Lmunlock0b +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lmlocki0: +	.long	__pthread_mutex_cond_lock-.Lmlocki0b + +1: +	/* Initial locking failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait0, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait0b: +	bra	2b +	 nop +3: +	/* Unlock in loop requires waekup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake0, r1 +	bsrf	r1 +	 nop +.Lmwake0b: +	bra	4b +	 nop + +5: +	/* Locking in loop failed.  */ +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait1, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait1b: +	bra	6b +	 nop + +10: +	/* Unlock after loop requires wakeup.  */ +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake1, r1 +	bsrf	r1 +	 nop +.Lmwake1b: +	bra	11b +	 nop + +12: +	/* The initial unlocking of the mutex failed.  */ +	mov.l	r0, @(12,r15) +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bf	13f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake2, r1 +	bsrf	r1 +	 nop +.Lmwake2b: + +13: +	bra	14b +	 mov.l	@(12,r15), r0 + +	.align	2 +.Lmwait0: +	.long	__lll_mutex_lock_wait-.Lmwait0b +.Lmwake0: +	.long	__lll_mutex_unlock_wake-.Lmwake0b +.Lmwait1: +	.long	__lll_mutex_lock_wait-.Lmwait1b +.Lmwake1: +	.long	__lll_mutex_unlock_wake-.Lmwake1b +.Lmwake2: +	.long	__lll_mutex_unlock_wake-.Lmwake2b +	.size	__pthread_cond_wait, .-__pthread_cond_wait +weak_alias (__pthread_cond_wait, pthread_cond_wait) + + +	.type	__condvar_w_cleanup, @function +__condvar_w_cleanup: +	mov	r4, r11 + +	/* Get internal lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if cond_lock != 0 +	CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else +	CMPXCHG (r3, @r8, r4, r2) +#endif +	bt	1f +	 nop + +	mov	r8, r5 +#if cond_lock != 0 +	add	#cond_lock, r5 +#endif +	mov.l	.Lmwait3, r1 +	bsrf	r1 +	 mov	r2, r4 +.Lmwait3b: + +1: +	mov.l	@(broadcast_seq,r8), r0 +	mov.l	@(4,r15), r1 +	cmp/eq	r0, r1 +	bf	3f + +	mov	#1, r2 +	mov	#0, r3 + +	clrt +	mov.l	@(wakeup_seq,r8),r0 +	mov.l	@(wakeup_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(wakeup_seq,r8) +	mov.l	r1,@(wakeup_seq+4,r8) +	mov.l	@(cond_futex,r8),r0 +	add	r2, r0 +	mov.l	r0,@(cond_futex,r8) + +	clrt +	mov.l	@(woken_seq,r8),r0 +	mov.l	@(woken_seq+4,r8),r1 +	addc	r2, r0 +	addc	r3, r1 +	mov.l	r0,@(woken_seq,r8) +	mov.l	r1,@(woken_seq+4,r8) + +3: +	mov	#(1 << clock_bits), r2 +	mov.l	@(cond_nwaiters,r8),r0 +	sub	r2, r0 +	mov.l	r0,@(cond_nwaiters,r8) + +	/* Wake up a thread which wants to destroy the condvar object.  */ +	mov	#0, r10 +	mov.l	@(total_seq,r8),r0 +	mov.l	@(total_seq+4,r8),r1 +	and	r1, r0 +	not	r0, r0 +	cmp/eq	#0, r0 +	bf/s	4f +	 mov	#((1 << clock_bits) - 1), r1 +	not	r1, r1 +	mov.l	@(cond_nwaiters,r8),r0 +	tst	r1, r0 +	bf	4f + +	mov	r8, r4 +	add	#cond_nwaiters, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#1, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	#1, r10 + +4: +#if cond_lock != 0 +	DEC (@(cond_lock,r8), r2) +#else +	DEC (@r8, r2) +#endif +	tst	r2, r2 +	bt	2f + +	mov	r8, r4 +#if cond_lock != 0 +	add	#cond_lock, r4 +#endif +	mov.l	.Lmwake3, r1 +	bsrf	r1 +	 nop +.Lmwake3b: + +2: +	/* Wake up all waiters to make sure no signal gets lost.  */ +	tst	r10, r10 +	bf/s	5f +	 mov	r8, r4 +	add	#cond_futex, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +5: +        mov.l   .Lmlocki3, r1 +        bsrf    r1 +         mov     r9, r4 +.Lmlocki3b: + +.LcallUR: +	mov.l	.Lresume, r1 +#ifdef __PIC__ +	add	r12, r1 +#endif +	jsr	@r1 +	 mov	r11, r4 +	sleep + +	.align	2 +.Lmwait3: +	.long   __lll_mutex_lock_wait-.Lmwait3b +.Lmwake3: +        .long   __lll_mutex_unlock_wake-.Lmwake3b +.Lmlocki3: +	.long   __pthread_mutex_cond_lock-.Lmlocki3b +.Lresume: +#ifdef __PIC__ +	.long	_Unwind_Resume@GOTOFF +#else +	.long	_Unwind_Resume +#endif +.LENDCODE: +	.size	__condvar_w_cleanup, .-__condvar_w_cleanup + + +	.section .gcc_except_table,"a",@progbits +.LexceptSTART: +	.byte	0xff				! @LPStart format (omit) +	.byte	0xff				! @TType format (omit) +	.byte	0x0b				! call-site format +						! DW_EH_PE_sdata4 +	.uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: +	.ualong	.LcleanupSTART-.LSTARTCODE +	.ualong	.LcleanupEND-.LcleanupSTART +	.ualong	__condvar_w_cleanup-.LSTARTCODE +	.uleb128  0 +	.ualong	.LcallUR-.LSTARTCODE +	.ualong	.LENDCODE-.LcallUR +	.ualong	0 +	.uleb128  0 +.Lcstend: + +	.section .eh_frame,"a",@progbits +.LSTARTFRAME: +	.ualong	.LENDCIE-.LSTARTCIE		! Length of the CIE. +.LSTARTCIE: +	.ualong	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 -4				! Data alignment factor. +	.byte	0x11				! 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 +	.ualong	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 6				! Augmentation value length. +	.byte	0x0				! Personality: absolute +	.ualong	__gcc_personality_v0 +	.byte	0x0				! LSDA Encoding: absolute +#endif +	.byte 0x0c				! DW_CFA_def_cfa +	.uleb128 0xf +	.uleb128 0 +	.align 2 +.LENDCIE: + +	.ualong	.LENDFDE-.LSTARTFDE		! Length of the FDE. +.LSTARTFDE: +	.ualong	.LSTARTFDE-.LSTARTFRAME		! CIE pointer. +#ifdef SHARED +	.ualong	.LSTARTCODE-.			! PC-relative start address +						! of the code. +#else +	.ualong	.LSTARTCODE			! Start address of the code. +#endif +	.ualong	.LENDCODE-.LSTARTCODE		! Length of the code. +	.uleb128 4				! Augmentation size +#ifdef SHARED +	.ualong	.LexceptSTART-. +#else +	.ualong	.LexceptSTART +#endif +	.byte	0x4 +	.ualong	.Lpush_r8-.LSTARTCODE +	.byte	0xe +	.uleb128 4 +	.byte	0x88 +	.uleb128 1 +	.byte	0x4 +	.ualong	.Lpush_r9-.Lpush_r8 +	.byte	0xe +	.uleb128 8 +	.byte	0x89 +	.uleb128 2 +	.byte	0x4 +	.ualong	.Lpush_r10-.Lpush_r9 +	.byte	0xe +	.uleb128 12 +	.byte	0x8a +	.uleb128 3 +	.byte	0x4 +	.ualong	.Lpush_r11-.Lpush_r10 +	.byte	0xe +	.uleb128 16 +	.byte	0x8b +	.uleb128 4 +	.byte	0x4 +	.ualong	.Lpush_r12-.Lpush_r11 +	.byte	0xe +	.uleb128 20 +	.byte	0x8c +	.uleb128 5 +	.byte	0x4 +	.ualong	.Lpush_pr-.Lpush_r12 +	.byte	0xe +	.uleb128 24 +	.byte	0x91 +	.uleb128 6 +	.byte	0x4 +	.ualong	.Lalloc-.Lpush_pr +	.byte	0xe +	.uleb128 72 +	.align	2 +.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 4 +	.type   DW.ref.__gcc_personality_v0, @object +	.size   DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: +	.long   __gcc_personality_v0 +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S new file mode 100644 index 000000000..de83dec1b --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,245 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <unwindbuf.h> +#include <sysdep.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT	0 +#define FUTEX_WAKE	1 + +	.comm	__fork_generation, 4, 4 + +	.text +	.globl	__pthread_once +	.type	__pthread_once,@function +	.align	5 +	cfi_startproc +__pthread_once: +	mov.l	@r4, r0 +	tst	#2, r0 +	bt	1f +	rts +	 mov	#0, r0 + +1: +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r12, 0) +	mov.l	r9, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r9, 0) +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (r8, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset (4) +	cfi_rel_offset (pr, 0) +	mov	r5, r8 +	mov	r4, r9 + +	/* Not yet initialized or initialization in progress. +	   Get the fork generation counter now.  */ +6: +	mov.l	@r4, r1 +	mova	.Lgot, r0 +	mov.l	.Lgot, r12 +	add	r0, r12 + +5: +	mov	r1, r0 + +	tst	#2, r0 +	bf	4f + +	and	#3, r0 +	mov.l	.Lfgen, r2 +#ifdef __PIC__ +	add	r12, r2 +#endif +	mov.l	@r2, r3 +	or	r3, r0 +	or	#1, r0 +	mov	r0, r3 +	mov	r1, r5 + +	CMPXCHG (r5, @r4, r3, r2) +	bf	5b + +	/* Check whether another thread already runs the initializer.  */ +	mov	r2, r0 +	tst	#1, r0 +	bt	3f	/* No -> do it.  */ + +	/* Check whether the initializer execution was interrupted +	   by a fork.  */ +	xor	r3, r0 +	mov	#-4, r1	/* -4 = 0xfffffffc */ +	tst	r1, r0 +	bf	3f	/* Different for generation -> run initializer.  */ + +	/* Somebody else got here first.  Wait.  */ +	mov	#FUTEX_WAIT, r5 +	mov	r3, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	bra	6b +	 nop + +	.align	2 +.Lgot: +	.long	_GLOBAL_OFFSET_TABLE_ +#ifdef __PIC__ +.Lfgen: +	.long	__fork_generation@GOTOFF +#else +.Lfgen: +	.long	__fork_generation +#endif + +3: +	/* Call the initializer function after setting up the +	   cancellation handler.  Note that it is not possible here +	   to use the unwind-based cleanup handling.  This would require +	   that the user-provided function and all the code it calls +	   is compiled with exceptions.  Unfortunately this cannot be +	   guaranteed.  */ +	add	#-UNWINDBUFSIZE, r15 +	cfi_adjust_cfa_offset (UNWINDBUFSIZE) + +	mov.l	.Lsigsetjmp, r1 +	mov	#UWJMPBUF, r4 +	add	r15, r4 +	bsrf	r1 +	 mov	#0, r5 +.Lsigsetjmp0: +	tst	r0, r0 +	bf	7f + +	mov.l	.Lcpush, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lcpush0: + +	/* Call the user-provided initialization function.  */ +	jsr	@r8 +	 nop + +	/* Pop the cleanup handler.  */ +	mov.l	.Lcpop, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lcpop0: + +	add	#UNWINDBUFSIZE, r15 +	cfi_adjust_cfa_offset (-UNWINDBUFSIZE) + +	/* Sucessful run of the initializer.  Signal that we are done.  */ +	INC (@r9, r2) +	/* Wake up all other threads.  */ +	mov	r9, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +4: +	lds.l	@r15+, pr +	cfi_adjust_cfa_offset (-4) +	cfi_restore (pr) +	mov.l	@r15+, r8 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r8) +	mov.l	@r15+, r9 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r9) +	mov.l	@r15+, r12 +	cfi_adjust_cfa_offset (-4) +	cfi_restore (r12) +	rts +	 mov	#0, r0 + +7: +	/* __sigsetjmp returned for the second time.  */ +	cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) +	cfi_offset (r12, -4) +	cfi_offset (r9, -8) +	cfi_offset (r8, -12) +	cfi_offset (pr, -16) +	mov	#0, r7 +	mov.l	r7, @r9 +	mov	r9, r4 +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Lunext, r1 +	bsrf	r1 +	 mov	r15, r4 +.Lunext0: +	/* NOTREACHED */ +	sleep +	cfi_endproc + +	.align	2 +.Lsigsetjmp: +	.long	__sigsetjmp@PLT-(.Lsigsetjmp0-.) +.Lcpush: +	.long	HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0 +.Lcpop: +	.long	HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0 +.Lunext: +	.long	HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0 +	.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	5 +clear_once_control: +	mov	#0, r0 +	mov.l	r0, @r4 + +	mov	#FUTEX_WAKE, r5 +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	rts +	 nop +	.size	clear_once_control,.-clear_once_control diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S new file mode 100644 index 000000000..ce1ab37c8 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -0,0 +1,220 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_rdlock +	.type	__pthread_rwlock_rdlock,@function +	.align	5 +__pthread_rwlock_rdlock: +	mov.l	r12, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	5f +	mov.l	@(FLAGS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(READERS_WAKEUP,r8), r9 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f +11: +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r9, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Reget the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	12f +13: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#-1, r0 +	bra	2b +	 mov.l	r0, @(READERS_QUEUED,r8) + +5: +	mov	#0, r3 +	mov.l	@(NR_READERS,r8), r0 +	add	#1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bt	8f + +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait0, r1 +	bsrf	r1 +	 nop +.Lwait0b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	/* Deadlock detected.  */ +	bra	9b +	 mov	#EDEADLK, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake0, r1 +	bsrf	r1 +	 nop +.Lwake0b: +	bra	7b +	 mov	#0, r3 + +8: +	/* Overflow.  */ +	mov.l	@(NR_READERS,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(NR_READERS,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +4: +	/* Overflow.  */ +	mov.l	@(READERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(READERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake1, r1 +	bsrf	r1 +	 nop +.Lwake1b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait1, r1 +	bsrf	r1 +	 nop +.Lwait1b: +	bra	13b +	 nop + +	.align	2 +.Lwait0: +	.long	__lll_mutex_lock_wait-.Lwait0b +.Lwake0: +	.long	__lll_mutex_unlock_wake-.Lwake0b +.Lwait1: +	.long	__lll_mutex_lock_wait-.Lwait1b +.Lwake1: +	.long	__lll_mutex_unlock_wake-.Lwake1b +	.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/sh/pthread_rwlock_timedrdlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S new file mode 100644 index 000000000..8a4e7d3bc --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,280 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	pthread_rwlock_timedrdlock +	.type	pthread_rwlock_timedrdlock,@function +	.align	5 +pthread_rwlock_timedrdlock: +	mov.l	r12, @-r15 +	mov.l	r10, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	add	#-8, r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	5f +	mov.l	@(FLAGS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	/* Check the value of the timeout parameter.  */ +	mov.l	.L1g0, r1 +	mov.l	@(4,r9), r0 +	cmp/hs	r1, r0 +	bt	19f + +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(READERS_WAKEUP,r8), r10 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k0, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	15f +	mov.l	.L1g0, r1 +	add	r1, r3 +	add	#-1, r2 +15: +	cmp/pz	r2 +	bf	16f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r15, r7 +	mov	#FUTEX_WAIT, r5 +	mov	r10, r6 +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r3 + +17: +	/* Reget the lock.  */ +	mov	#0, r5 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r5, @r8, r4, r2) +#else +	CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif +	bf	12f + +13: +	mov.l	@(READERS_QUEUED,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(READERS_QUEUED,r8) +	mov	#-ETIMEDOUT, r0 +	cmp/eq	r0, r3 +	bf	2b + +18: +	bra	9f +	 mov	#ETIMEDOUT, r3 + +5: +	mov	#0, r3 +	mov.l	@(NR_READERS,r8), r0 +	add	#1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bt	8f + +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	add	#8,r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r10 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +	.align	2 +.L1k0: +	.long	1000 +.L1g0: +	.long	1000000000 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait2, r1 +	bsrf	r1 +	 nop +.Lwait2b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	/* Deadlock detected.  */ +	bra	9b +	 mov	#EDEADLK, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake2, r1 +	bsrf	r1 +	 nop +.Lwake2b: +	bra	7b +	 mov	#0, r3 + +8: +	/* Overflow.  */ +	mov.l	@(NR_READERS,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(NR_READERS,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +4: +	/* Overflow.  */ +	mov.l	@(READERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(READERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake3, r1 +	bsrf	r1 +	 nop +.Lwake3b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait3, r1 +	bsrf	r1 +	 nop +.Lwait3b: +	bra	13b +	 nop + +16: +	bra	17b +	 mov	#-ETIMEDOUT, r3 + +19: +	bra	9b +	 mov	#EINVAL, r3 + +	.align	2 +.Lwait2: +	.long	__lll_mutex_lock_wait-.Lwait2b +.Lwake2: +	.long	__lll_mutex_unlock_wake-.Lwake2b +.Lwait3: +	.long	__lll_mutex_lock_wait-.Lwait3b +.Lwake3: +	.long	__lll_mutex_unlock_wake-.Lwake3b +	.size	pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S new file mode 100644 index 000000000..6284140a6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,265 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	pthread_rwlock_timedwrlock +	.type	pthread_rwlock_timedwrlock,@function +	.align	5 +pthread_rwlock_timedwrlock: +	mov.l	r12, @-r15 +	mov.l	r10, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	add	#-8, r15 +	mov	r4, r8 +	mov	r5, r9 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(NR_READERS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	/* Check the value of the timeout parameter.  */ +	mov.l	.L1g1, r1 +	mov.l	@(4,r9), r0 +	cmp/hs	r1, r0 +	bt	19f + +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(WRITERS_WAKEUP,r8), r10 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f + +11: +	/* Get current time.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k1, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	15f +	mov.l	.L1g1, r1 +	add	r1, r3 +	add	#-1, r2 +15: +	cmp/pz	r2 +	bf	16f		/* Time is already up.  */ + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r15, r7 +	mov	#FUTEX_WAIT, r5 +	mov	r10, r6 +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD +	mov	r0, r3 + +17: +	/* Reget the lock.  */ +	mov	#0, r5 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r5, @r8, r4, r2) +#else +	CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif +	bf	12f + +13: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	mov	#-ETIMEDOUT, r0 +	cmp/eq	r0, r3 +	bf	2b + +18: +	bra	9f +	 mov	#ETIMEDOUT, r3 + +19: +	bra	9f +	 mov	#EINVAL, r3 + +5: +	mov	#0, r3 +	stc	gbr, r0 +	mov.w	.Ltidoff, r1 +	mov.l	@(r0,r1), r0 +	mov.l	r0, @(WRITER,r8) +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	add	#8,r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r10 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +.L1k1: +	.word	1000 +	.align	2 +.L1g1: +	.long	1000000000 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait6, r1 +	bsrf	r1 +	 nop +.Lwait6b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	bra	9b +	 mov	#EDEADLK, r3 +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake6, r1 +	bsrf	r1 +	 nop +.Lwake6b: +	bra	7b +	 mov	#0, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +4: +	/* Overflow.  */ +	mov.l	@(WRITERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(WRITERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake7, r1 +	bsrf	r1 +	 nop +.Lwake7b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait7, r1 +	bsrf	r1 +	 nop +.Lwait7b: +	bra	13b +	 nop + +16: +	bra	17b +	 mov	#-ETIMEDOUT, r3 + +	.align	2 +.Lwait6: +	.long	__lll_mutex_lock_wait-.Lwait6b +.Lwake6: +	.long	__lll_mutex_unlock_wake-.Lwake6b +.Lwait7: +	.long	__lll_mutex_lock_wait-.Lwait7b +.Lwake7: +	.long	__lll_mutex_unlock_wake-.Lwake7b +	.size	pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S new file mode 100644 index 000000000..74f32f8f9 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,169 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelrwlock.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_unlock +	.type	__pthread_rwlock_unlock,@function +	.align	5 +__pthread_rwlock_unlock: +	mov.l	r12, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	5f +	mov.l	@(NR_READERS,r8), r0 +	add	#-1, r0 +	mov.l	r0, @(NR_READERS,r8) +	tst	r0, r0 +	bf	6f +5: +	mov	#0, r0 +	mov.l	r0, @(WRITER,r8) +	mov	#1, r6 +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov.l	@(WRITERS_QUEUED,r8), r0 +	tst	r0, r0 +	bf	0f + +	/* If also no readers waiting nothing to do.  */ +	mov.l	@(READERS_QUEUED,r8), r0 +	tst	r0, r0 +	bt	6f + +	mov	#-1, r6 +	shlr	r6		/* r6 = 0x7fffffff */ +	mov	r8, r4 +	add	#READERS_WAKEUP, r4 + +0: +	mov.l	@r4, r0 +	add	#1, r0 +	mov.l	r0, @r4 +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	7f + +8: +	mov	#FUTEX_WAKE, r5 +	mov	#SYS_futex, r3 +	mov	#0, r7 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 +6: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	3f +4: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait8, r1 +	bsrf	r1 +	 nop +.Lwait8b: +	bra	2b +	 nop +3: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake8, r1 +	bsrf	r1 +	 nop +.Lwake8b: +	bra	4b +	 nop + +7: +	mov.l	r4, @-r15 +	mov.l	r6, @-r15 +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake9, r1 +	bsrf	r1 +	 nop +.Lwake9b: + +	mov.l	@r15+, r6 +	bra	8b +	 mov.l	@r15+, r4 + +	.align	2 +.Lwait8: +	.long	__lll_mutex_lock_wait-.Lwait8b +.Lwake8: +	.long	__lll_mutex_unlock_wake-.Lwake8b +.Lwake9: +	.long	__lll_mutex_unlock_wake-.Lwake9b +	.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/sh/pthread_rwlock_wrlock.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S new file mode 100644 index 000000000..d071f7f03 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -0,0 +1,202 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <lowlevelrwlock.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + + +	.text + +	.globl	__pthread_rwlock_wrlock +	.type	__pthread_rwlock_wrlock,@function +	.align	5 +__pthread_rwlock_wrlock: +	mov.l	r12, @-r15 +	mov.l	r9, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 + +	/* Get the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	1f +2: +	mov.l	@(WRITER,r8), r0 +	tst	r0, r0 +	bf	14f +	mov.l	@(NR_READERS,r8), r0 +	tst	r0, r0 +	bt	5f +3: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#1, r0 +	mov.l	r0, @(WRITERS_QUEUED,r8) +	tst	r0, r0 +	bt	4f + +	mov.l	@(WRITERS_WAKEUP,r8), r9 + +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	10f +11: +	mov	r8, r4 +	add	#WRITERS_WAKEUP, r4 +	mov	#FUTEX_WAIT, r5 +	mov	r9, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	/* Reget the lock.  */ +	mov	#0, r3 +	mov	#1, r4 +#if MUTEX == 0 +	CMPXCHG (r3, @r8, r4, r2) +#else +	CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif +	bf	12f +13: +	mov.l	@(WRITERS_QUEUED,r8), r0 +	add	#-1, r0 +	bra	2b +	 mov.l	r0, @(WRITERS_QUEUED,r8) + +5: +	mov	#0, r3 +	stc	gbr, r0 +	mov.w	.Ltidoff, r1 +	mov.l	@(r0,r1), r0 +	mov.l	r0, @(WRITER,r8) +9: +#if MUTEX == 0 +	DEC (@r8, r2) +#else +	DEC (@(MUTEX,r8), r2) +#endif +	tst	r2, r2 +	bf	6f +7: +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r9 +	mov.l	@r15+, r12 +	rts +	 mov	r3, r0 + +1: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait4, r1 +	bsrf	r1 +	 nop +.Lwait4b: +	bra	2b +	 nop +14: +	stc	gbr, r1 +	mov.w	.Ltidoff, r2 +	add	r2, r1 +	mov.l	@r1, r1 +	cmp/eq	r1, r0 +	bf	3b +	bra	9b +	 mov	#EDEADLK, r3 +6: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake4, r1 +	bsrf	r1 +	 nop +.Lwake4b: +	bra	7b +	 mov	#0, r3 + +.Ltidoff: +	.word	TID - TLS_PRE_TCB_SIZE + +4: +	mov.l	@(WRITERS_QUEUED,r8), r1 +	add	#-1, r1 +	mov.l	r1, @(WRITERS_QUEUED,r8) +	bra	9b +	 mov	#EAGAIN, r3 + +10: +	mov	r8, r4 +#if MUTEX != 0 +	add	#MUTEX, r4 +#endif +	mov.l	.Lwake5, r1 +	bsrf	r1 +	 nop +.Lwake5b: +	bra	11b +	 nop + +12: +	mov	r8, r5 +#if MUTEX != 0 +	add	#MUTEX, r5 +#endif +	mov	r2, r4 +	mov.l	.Lwait5, r1 +	bsrf	r1 +	 nop +.Lwait5b: +	bra	13b +	 nop + +	.align	2 +.Lwait4: +	.long	__lll_mutex_lock_wait-.Lwait4b +.Lwake4: +	.long	__lll_mutex_unlock_wake-.Lwake4b +.Lwait5: +	.long	__lll_mutex_lock_wait-.Lwait5b +.Lwake5: +	.long	__lll_mutex_unlock_wake-.Lwake5b +	.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/sh/sem_post.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S new file mode 100644 index 000000000..9755b7e16 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,84 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	__new_sem_post +	.type	__new_sem_post,@function +	.align	5 +__new_sem_post: +	INC	(@r4, r6) + +	mov	#FUTEX_WAKE, r5 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	cmp/pz	r0 +	bf	1f +	rts +	 mov	#0, r0 + +1: +	mov	#EINVAL, r2 +	mova	.Lgot3, r0 +	mov.l	.Lgot3, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno3, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno3: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc3, r1 +	bsrf	r1 +	 nop +.Lerrloc3b: +#endif +	mov.l	r2, @r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	rts +	 mov	#-1, r0 + +	.align	2 +.Lgot3: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc3: +	.long	__errno_location@PLT-(.Lerrloc3b-.) +#endif +	.size	__new_sem_post,.-__new_sem_post +	weak_alias(__new_sem_post, sem_post) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S new file mode 100644 index 000000000..40782fcaf --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,240 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	sem_timedwait +	.type	sem_timedwait,@function +	.align	5 +	cfi_startproc +sem_timedwait: +	/* First check for cancellation.  */ +	stc	gbr, r0 +	mov.w	.Lchand, r1 +	mov.l	@(r0,r1), r0 +	mov	#0xf9, r1 +	and	r1, r0 +	cmp/eq	#8, r0 +	bf	0f +	bra	10f +	 stc	gbr, r0 +0: +	mov.l	@r4, r0 +2: +	tst	r0, r0 +	bt	1f +	mov	r0, r3 +	mov	r0, r6 +	add	#-1, r3 +	CMPXCHG (r6, @r4, r3, r2) +	bf/s	2b +	 mov	r2, r0 +	rts +	 mov	#0, r0 + +1: +	/* Check whether the timeout value is valid.  */ +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r8, 0) +	mov.l	r9, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r9, 0) +	mov.l	r10, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r10, 0) +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r12, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (pr, 0) +	add	#-8, r15 +	cfi_adjust_cfa_offset(8) +	mov	r4, r8 +	mov	r5, r9 + +	/* Check for invalid nanosecond field.  */ +	mov.l	@(4,r9), r0 +	mov.l	.L1g, r1 +	cmp/hs	r1, r0 +	bt/s	6f +	 mov	#EINVAL, r0 +7: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov	r0, r10 + +	/* Compute relative timeout.  */ +	mov	r15, r4 +	mov	#0, r5 +	mov	#SYS_gettimeofday, r3 +	trapa	#0x12 +	SYSCALL_INST_PAD + +	mov.l	@(4,r15), r0 +	mov.w	.L1k, r1 +	dmulu.l	r0, r1		/* Milli seconds to nano seconds.  */ +	mov.l	@r9, r2 +	mov.l	@(4,r9), r3 +	mov.l	@r15, r0 +	sts	macl, r1 +	sub	r0, r2 +	clrt +	subc	r1, r3 +	bf	5f +	mov.l	.L1g, r1 +	add	r1, r3 +	add	#-1, r2 +5: +	cmp/pz	r2 +	bf/s	6f		/* Time is already up.  */ +	mov	#ETIMEDOUT, r0 + +	/* Store relative timeout.  */ +	mov.l	r2, @r15 +	mov.l	r3, @(4,r15) + +	/* Futex call.  */ +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	#0, r6 +	mov	r15, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	mov	r10, r4 +	bsrf	r1 +	 mov	r0, r10 +.Ldisable0b: +	mov	r10, r0 + +	tst	r0, r0 +	bt	9f +	cmp/eq	#-EWOULDBLOCK, r0 +	bf	3f +9: +	mov.l	@r8, r0 +8: +	tst	r0, r0 +	bt	7b + +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	8b +	 mov	r2, r0 + +	add	#8, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	mov.l	@r15+, r8 +	rts +	 mov	#0, r0 + +3: +	neg	r0, r0 +6: +	mov	r0, r8 +	mova	.Lgot2, r0 +	mov.l	.Lgot2, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno2, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno2: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc2, r1 +	bsrf	r1 +	 nop +.Lerrloc2b: +#endif +	mov.l	r8, @r0 +	add	#8, r15 +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	mov.l	@r15+, r9 +	mov.l	@r15+, r8 +	rts +	 mov	#-1, r0 + +10: +	/* Canceled.  */ +	mov.w	.Lresult, r1 +	mov	#-1, r2 +	mov.l	r2, @(r0,r1) +	mov.w	.Lchand, r0 +	or.b	#0x10, @(r0,gbr) +	stc	gbr, r0 +	mov.w	.Lclbuf, r1 +	mov.l	.Lunwind, r2 +	braf	r2 +	 mov.l	@(r0,r1), r4 +.Lunwindb: +	cfi_endproc + +.L1k: +	.word	1000 +.Lchand: +	.word	CANCELHANDLING - TLS_PRE_TCB_SIZE +.Lresult: +	.word	RESULT - TLS_PRE_TCB_SIZE +.Lclbuf: +	.word	CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE +	.align	2 +.L1g: +	.long	1000000000 +.Lgot2: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc2: +	.long	__errno_location@PLT-(.Lerrloc2b-.) +#endif +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lunwind: +	.long	HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb +	.size	sem_timedwait,.-sem_timedwait diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S new file mode 100644 index 000000000..00c61f3bb --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S @@ -0,0 +1,89 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include "lowlevel-atomic.h" + + +	.text + +	.globl	__new_sem_trywait +	.type	__new_sem_trywait,@function +	.align	5 +__new_sem_trywait: +	mov.l	r12, @-r15 +	mov.l	r8, @-r15 +	sts.l	pr, @-r15 +	mov	r4, r8 +	mov.l	@r8, r0 +2: +	tst	r0, r0 +	bt	1f + +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	2b +	 mov	r2, r0 + +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#0, r0 + +1: +	mov	#EAGAIN, r8 +	mova	.Lgot1, r0 +	mov.l	.Lgot1, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno1, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno1: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc1, r1 +	bsrf	r1 +	 nop +.Lerrloc1b: +#endif +	mov.l	r8, @r0 +	lds.l	@r15+, pr +	mov.l	@r15+, r8 +	mov.l	@r15+, r12 +	rts +	 mov	#-1, r0 + +	.align	2 +.Lgot1: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc1: +	.long	__errno_location@PLT-(.Lerrloc1b-.) +#endif +	.size	__new_sem_trywait,.-__new_sem_trywait +	weak_alias(__new_sem_trywait, sem_trywait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S new file mode 100644 index 000000000..7d13fa130 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,166 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#include <pthread-errnos.h> +#include <tcb-offsets.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday	__NR_gettimeofday +#define FUTEX_WAIT		0 +#define FUTEX_WAKE		1 + +	.text + +	.globl	__new_sem_wait +	.type	__new_sem_wait,@function +	.align	5 +	cfi_startproc +__new_sem_wait: +	/* First check for cancellation.  */ +	stc	gbr, r0 +	mov.w	.Lchand, r1 +	mov.l	@(r0,r1), r0 +	mov	#0xf9, r1 +	and	r1, r0 +	cmp/eq	#8, r0 +	bt	5f + +	mov.l	r8, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r8, 0) +	mov.l	r10, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r10, 0) +	mov.l	r12, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (r12, 0) +	sts.l	pr, @-r15 +	cfi_adjust_cfa_offset(4) +	cfi_rel_offset (pr, 0) +	mov	r4, r8 +3: +	mov.l	@r8, r0 +2: +	tst	r0, r0 +	bt	1f +	mov	r0, r3 +	mov	r0, r4 +	add	#-1, r3 +	CMPXCHG (r4, @r8, r3, r2) +	bf/s	2b +	 mov	r2, r0 +	bra	9f +	 mov	#0, r0 + +1: +	mov.l	.Lenable0, r1 +	bsrf	r1 +	 nop +.Lenable0b: +	mov	r0, r10 + +	mov	r8, r4 +	mov	#FUTEX_WAIT, r5 +	mov	#0, r6 +	mov	#0, r7 +	mov	#SYS_futex, r3 +	extu.b	r3, r3 +	trapa	#0x14 +	SYSCALL_INST_PAD + +	mov.l	.Ldisable0, r1 +	mov	r10, r4 +	bsrf	r1 +	 mov	r0, r10 +.Ldisable0b: +	mov	r10, r0 + +	tst	r0, r0 +	bt	3b +	cmp/eq	#-EWOULDBLOCK, r0 +	bt	3b +	neg	r0, r0 + +	mov	r0, r8 +	mova	.Lgot0, r0 +	mov.l	.Lgot0, r12 +	add	r0, r12 + +#if USE___THREAD +	mov.l	.Lerrno0, r0 +	stc	gbr, r1 +	mov.l	@(r0, r12), r0 +	bra .Lexit +	add	r1, r0 +	.align 2 +.Lerrno0: +	.long	errno@GOTTPOFF +.Lexit: +#else +	mov.l	.Lerrloc0, r1 +	bsrf	r1 +	 nop +.Lerrloc0b: +#endif +	mov.l	r8, @r0 +	mov	#-1, r0 +9: +	lds.l	@r15+, pr +	mov.l	@r15+, r12 +	mov.l	@r15+, r10 +	rts +	 mov.l	@r15+, r8 +5: +	/* Canceled.  */ +	stc	gbr, r0 +	mov.w	.Lresult, r1 +	mov	#-1, r2 +	mov.l	r2, @(r0,r1) +	mov.w	.Lchand, r0 +	or.b	#0x10, @(r0,gbr) +	stc	gbr, r0 +	mov.w	.Lclbuf, r1 +	mov.l	.Lunwind, r2 +	braf	r2 +	 mov.l	@(r0,r1), r4 +.Lunwindb: +	cfi_endproc + +.Lchand: +	.word	CANCELHANDLING - TLS_PRE_TCB_SIZE +.Lresult: +	.word	RESULT - TLS_PRE_TCB_SIZE +.Lclbuf: +	.word	CLEANUP_JMP_BUF - TLS_PRE_TCB_SIZE +	.align	2 +.Lgot0: +	.long	_GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc0: +	.long	__errno_location@PLT-(.Lerrloc0b-.) +#endif +.Lenable0: +	.long	__pthread_enable_asynccancel-.Lenable0b +.Ldisable0: +	.long	__pthread_disable_asynccancel-.Ldisable0b +.Lunwind: +	.long	HIDDEN_JUMPTARGET (__pthread_unwind)-.Lunwindb +	.size	__new_sem_wait,.-__new_sem_wait +	weak_alias(__new_sem_wait, sem_wait) diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h new file mode 100644 index 000000000..8cdcac556 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h @@ -0,0 +1,4 @@ +/*  4 instruction cycles not accessing cache and TLB are needed after +    trapa instruction to avoid an SH-4 silicon bug.  */ +#define NEED_SYSCALL_INST_PAD +#include <sysdeps/unix/sysv/linux/sh/lowlevellock.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h new file mode 100644 index 000000000..1aed1a14a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/sysdep.h @@ -0,0 +1,4 @@ +/*  4 instruction cycles not accessing cache and TLB are needed after +    trapa instruction to avoid an SH-4 silicon bug.  */ +#define NEED_SYSCALL_INST_PAD +#include_next <sysdep.h> diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 000000000..2c0cbe99a --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors.  SH version. +   Copyright (C) 2002 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Library General Public License as +   published by the Free Software Foundation; either version 2 of the +   License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Library General Public License for more details. + +   You should have received a copy of the GNU Library General Public +   License along with the GNU C Library; see the file COPYING.LIB.  If not, +   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +   Boston, MA 02111-1307, USA.  */ + +static inline int +is_smp_system (void) +{ +  return 0; +} diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 000000000..dbaa44385 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,247 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <tls.h> +#include <sysdep.h> +#ifndef __ASSEMBLER__ +# include <pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +  .text; \ +  ENTRY (name); \ +  .Lpseudo_start: \ +    SINGLE_THREAD_P; \ +    bf .Lpseudo_cancel; \ +    .type __##syscall_name##_nocancel,@function; \ +    .globl __##syscall_name##_nocancel; \ +    __##syscall_name##_nocancel: \ +    DO_CALL (syscall_name, args); \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bt .Lsyscall_error; \ +    bra .Lpseudo_end; \ +     nop; \ +    .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ +    sts.l pr,@-r15; \ + .LCFI0: \ +    add _IMM16,r15; \ +    SAVE_ARGS_##args; \ + .LCFI1: \ +    CENABLE; \ +    LOAD_ARGS_##args; \ +    add _IMP16,r15; \ + .LCFI2: \ +    lds.l @r15+,pr; \ + .LCFI3: \ +    DO_CALL(syscall_name, args); \ +    SYSCALL_INST_PAD; \ +    sts.l pr,@-r15; \ + .LCFI4: \ +    mov.l r0,@-r15; \ + .LCFI5: \ +    CDISABLE; \ +    mov.l @r15+,r0; \ + .LCFI6: \ +    lds.l @r15+,pr; \ + .LCFI7: \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bf .Lpseudo_end; \ + .Lsyscall_error: \ +    SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: \ + /* Create unwinding information for the syscall wrapper.  */ \ + .section .eh_frame,"a",@progbits; \ + .Lframe1: \ +    .ualong .LECIE1-.LSCIE1; \ + .LSCIE1: \ +    .ualong 0x0; \ +    .byte   0x1; \ +    AUGMENTATION_STRING; \ +    .uleb128 0x1; \ +    .sleb128 -4; \ +    .byte   0x11; \ +    AUGMENTATION_PARAM; \ +    .byte   0xc; \ +    .uleb128 0xf; \ +    .uleb128 0x0; \ +    .align 2; \ + .LECIE1: \ + .LSFDE1: \ +    .ualong .LEFDE1-.LASFDE1; \ + .LASFDE1: \ +    .ualong .LASFDE1-.Lframe1; \ +    START_SYMBOL_REF; \ +    .ualong .Lpseudo_end - .Lpseudo_start; \ +    AUGMENTATION_PARAM_FDE; \ +    .byte   0x4; \ +    .ualong .LCFI0-.Lpseudo_start; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x91; \ +    .uleb128 0x1; \ +    .byte   0x4; \ +    .ualong .LCFI1-.LCFI0; \ +    .byte   0xe; \ +    .uleb128 0x14; \ +    FRAME_REG_##args; \ +    .byte   0x4; \ +    .ualong .LCFI2-.LCFI1; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x4; \ +    .ualong .LCFI3-.LCFI2; \ +    .byte   0xe; \ +    .uleb128 0x0; \ +    .byte   0xd1; \ +    .byte   0x4; \ +    .ualong .LCFI4-.LCFI3; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0x91; \ +    .uleb128 0x1; \ +    .byte   0x4; \ +    .ualong .LCFI5-.LCFI4; \ +    .byte   0xe; \ +    .uleb128 0x8; \ +    .byte   0x80; \ +    .uleb128 0x2; \ +    .byte   0x4; \ +    .ualong .LCFI6-.LCFI5; \ +    .byte   0xe; \ +    .uleb128 0x4; \ +    .byte   0xc0; \ +    .byte   0x4; \ +    .ualong .LCFI7-.LCFI6; \ +    .byte   0xe; \ +    .uleb128 0x0; \ +    .byte   0xd1; \ +    .align 2; \ + .LEFDE1: \ + .previous + +# ifdef SHARED +#  define AUGMENTATION_STRING .string "zR" +#  define AUGMENTATION_PARAM .uleb128 1; .byte 0x1b +#  define AUGMENTATION_PARAM_FDE .uleb128 0 +#  define START_SYMBOL_REF .long .Lpseudo_start-. +# else +#  define AUGMENTATION_STRING .ascii "\0" +#  define AUGMENTATION_PARAM +#  define AUGMENTATION_PARAM_FDE +#  define START_SYMBOL_REF .long .Lpseudo_start +# endif + +# define FRAME_REG_0	/* Nothing.  */ +# define FRAME_REG_1	FRAME_REG_0; .byte 0x84; .uleb128 5 +# define FRAME_REG_2	FRAME_REG_1; .byte 0x85; .uleb128 4 +# define FRAME_REG_3	FRAME_REG_2; .byte 0x86; .uleb128 3 +# define FRAME_REG_4	FRAME_REG_3; .byte 0x87; .uleb128 2 +# define FRAME_REG_5	FRAME_REG_4 +# define FRAME_REG_6	FRAME_REG_5 + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ +  END (sym) + +# define SAVE_ARGS_0	/* Nothing.  */ +# define SAVE_ARGS_1	SAVE_ARGS_0; mov.l r4,@(0,r15) +# define SAVE_ARGS_2	SAVE_ARGS_1; mov.l r5,@(4,r15) +# define SAVE_ARGS_3	SAVE_ARGS_2; mov.l r6,@(8,r15) +# define SAVE_ARGS_4	SAVE_ARGS_3; mov.l r7,@(12,r15) +# define SAVE_ARGS_5	SAVE_ARGS_4 +# define SAVE_ARGS_6	SAVE_ARGS_5 + +# define LOAD_ARGS_0	/* Nothing.  */ +# define LOAD_ARGS_1	LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2	LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3	LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4	LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5	LOAD_ARGS_4 +# define LOAD_ARGS_6	LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +#  define __local_enable_asynccancel	__pthread_enable_asynccancel +#  define __local_disable_asynccancel	__pthread_disable_asynccancel +# elif !defined NOT_IN_libc +#  define __local_enable_asynccancel	__libc_enable_asynccancel +#  define __local_disable_asynccancel	__libc_disable_asynccancel +# elif defined IS_IN_librt +#  define __local_enable_asynccancel	__librt_enable_asynccancel +#  define __local_disable_asynccancel	__librt_disable_asynccancel +# else +#  error Unsupported library +# endif + +# define CENABLE \ +	mov.l 1f,r0; \ +	bsrf r0; \ +	 nop; \ +     0: bra 2f; \ +	 mov r0,r2; \ +	.align 2; \ +     1: .long __local_enable_asynccancel - 0b; \ +     2: + +# define CDISABLE \ +	mov.l 1f,r0; \ +	bsrf r0; \ +	 mov r2,r4; \ +     0: bra 2f; \ +	 nop; \ +	.align 2; \ +     1: .long __local_disable_asynccancel - 0b; \ +     2: + +# ifndef __ASSEMBLER__ +#  define SINGLE_THREAD_P \ +  __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ +				   header.multiple_threads) == 0, 1) +# else +#  define SINGLE_THREAD_P \ +	stc gbr,r0; \ +	mov.w 0f,r1; \ +	sub r1,r0; \ +	mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ +	bra 1f; \ +	 tst r0,r0; \ +     0: .word TLS_PRE_TCB_SIZE; \ +     1: + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h new file mode 100644 index 000000000..7e9223b70 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep.h @@ -0,0 +1,224 @@ +/* Copyright (C) 1992,1993,1995,1996,1997,1998,1999,2000,2002,2003,2004 +	Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995. +   Changed by Kaz Kojima, <kkojima@rr.iij4u.or.jp>. + +   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 _LINUX_SH_SYSDEP_H +#define _LINUX_SH_SYSDEP_H 1 + +/* There is some commonality.  */ +#include <sysdeps/unix/sh/sysdep.h> + +/* For Linux we can use the system call table in the header file +	/usr/include/asm/unistd.h +   of the kernel.  But these symbols do not follow the SYS_* syntax +   so we have to redefine the `SYS_ify' macro here.  */ +#undef SYS_ify +#define SYS_ify(syscall_name)	(__NR_##syscall_name) + + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, +   unlike most Unices, which use the condition codes' carry flag. + +   Since version 2.1 the return value of a system call might be +   negative even if the call succeeded.  E.g., the `lseek' system call +   might return a large offset.  Therefore we must not anymore test +   for < 0, but test for a real error by making sure the value in R0 +   is a real error number.  Linus said he will make sure the no syscall +   returns a value in -1 .. -4095 as a valid result so we can savely +   test with -4095.  */ + +#define _IMM1 #-1 +#define _IMM12 #-12 +#undef	PSEUDO +#define	PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args); \ +    mov r0,r1; \ +    mov _IMM12,r2; \ +    shad r2,r1; \ +    not r1,r1; \ +    tst r1,r1; \ +    bf .Lpseudo_end; \ +    SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +#undef	PSEUDO_END +#define	PSEUDO_END(name) \ +  END (name) + +#undef	PSEUDO_NOERRNO +#define	PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args) + +#undef	PSEUDO_END_NOERRNO +#define	PSEUDO_END_NOERRNO(name) \ +  END (name) + +#define ret_NOERRNO ret + +#define	PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ +    DO_CALL (syscall_name, args); + +#undef	PSEUDO_END_ERRVAL +#define	PSEUDO_END_ERRVAL(name) \ +  END (name) + +#define ret_ERRVAL ret + +#ifndef __PIC__ +# define SYSCALL_ERROR_HANDLER	\ +	mov.l 0f,r1; \ +	jmp @r1; \ +	 mov r0,r4; \ +	.align 2; \ +     0: .long __syscall_error + +#include <libc/sysdeps/linux/sh/syscall_error.S> +#else +# ifdef RTLD_PRIVATE_ERRNO + +#  define SYSCALL_ERROR_HANDLER	\ +	neg r0,r1; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	mov.l r1,@(r0,r12) +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long rtld_errno@GOTOFF + +# elif defined _LIBC_REENTRANT + +#  if USE___THREAD + +#   ifndef NOT_IN_libc +#    define SYSCALL_ERROR_ERRNO __libc_errno +#   else +#    define SYSCALL_ERROR_ERRNO errno +#   endif +#   define SYSCALL_ERROR_HANDLER \ +	neg r0,r1; \ +	mov r12,r2; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	stc gbr, r4; \ +	mov.l @(r0,r12),r0; \ +	bra .Lskip; \ +	add r4,r0; \ +	.align 2; \ +	1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF; \ +	.Lskip: \ +	mov r2,r12; \ +	mov.l r1,@r0; \ +	bra .Lpseudo_end; \ +	mov _IMM1,r0; \ +	.align 2; \ +	0: .long _GLOBAL_OFFSET_TABLE_ +#  else + +#   define SYSCALL_ERROR_HANDLER \ +	neg r0,r1; \ +	mov.l r14,@-r15; \ +	mov.l r12,@-r15; \ +	mov.l r1,@-r15; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	sts.l pr,@-r15; \ +	mov r15,r14; \ +	mov.l 1f,r1; \ +	bsrf r1; \ +         nop; \ +     2: mov r14,r15; \ +	lds.l @r15+,pr; \ +	mov.l @r15+,r1; \ +	mov.l r1,@r0; \ +	mov.l @r15+,r12; \ +	mov.l @r15+,r14; \ +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b-.) +/* A quick note: it is assumed that the call to `__errno_location' does +   not modify the stack!  */ +#  endif +# else + +/* Store (-r0) into errno through the GOT.  */ +#  define SYSCALL_ERROR_HANDLER						      \ +	neg r0,r1; \ +	mov r12,r2; \ +	mov.l 0f,r12; \ +	mova 0f,r0; \ +	add r0,r12; \ +	mov.l 1f,r0; \ +	mov.l @(r0,r12),r0; \ +	mov r2,r12; \ +	mov.l r1,@r0; \ +	bra .Lpseudo_end; \ +	 mov _IMM1,r0; \ +	.align 2; \ +     0: .long _GLOBAL_OFFSET_TABLE_; \ +     1: .long errno@GOT +# endif	/* _LIBC_REENTRANT */ +#endif	/* __PIC__ */ + +# ifdef NEED_SYSCALL_INST_PAD +#  define SYSCALL_INST_PAD \ +	or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0 +# else +#  define SYSCALL_INST_PAD +# endif + +#define SYSCALL_INST0	trapa #0x10 +#define SYSCALL_INST1	trapa #0x11 +#define SYSCALL_INST2	trapa #0x12 +#define SYSCALL_INST3	trapa #0x13 +#define SYSCALL_INST4	trapa #0x14 +#define SYSCALL_INST5	mov.l @(0,r15),r0; trapa #0x15 +#define SYSCALL_INST6	mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16 + +#undef	DO_CALL +#define DO_CALL(syscall_name, args)	\ +    mov.l 1f,r3;			\ +    SYSCALL_INST##args;			\ +    SYSCALL_INST_PAD;			\ +    bra 2f;				\ +     nop;				\ +    .align 2;				\ + 1: .long SYS_ify (syscall_name);	\ + 2: + +#endif	/* __ASSEMBLER__ */ + +#endif /* linux/sh/sysdep.h */ diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 000000000..a45c09fd6 --- /dev/null +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,71 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. +   This file is part of the GNU C Library. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <sysdep.h> +#define _ERRNO_H	1 +#include <bits/errno.h> +#include <tcb-offsets.h> + +/* Clone the calling process, but without copying the whole address space. +   The calling process is suspended until the new process exits or is +   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process, +   and the process ID of the new process to the old process.  */ + +ENTRY (__vfork) +	/* Save the PID value.  */ +	stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	@(r0,r2), r4 +	neg	r4, r1 +	tst	r1, r1 +	bf	1f +	mov	#1, r1 +	rotr	r1 +1: +	mov.l	r1, @(r0,r2) + +	mov.w	.L1, r3 +	trapa	#0x10 +	mov     r0, r1 + +	/* Restore the old PID value in the parent.  */ +	tst	r0, r0 +	bt.s	2f +	 stc	gbr, r2 +	mov.w	.L2, r0 +	mov.l	r4, @(r0,r2) +	mov	r1, r0 +2: +	mov	#-12, r2 +	shad	r2, r1 +	not	r1, r1			// r1=0 means r0 = -1 to -4095 +	tst	r1, r1			// i.e. error in linux +	bf	.Lpseudo_end +	SYSCALL_ERROR_HANDLER +.Lpseudo_end: +	rts +	 nop +.L1: +	.word	__NR_vfork +.L2: +	.word	PID - TLS_PRE_TCB_SIZE +	.align	2 +PSEUDO_END (__vfork) +hidden_def (vfork) + +weak_alias (__vfork, vfork) | 
