diff options
40 files changed, 5396 insertions, 0 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog index a21ecfb0a3..51141e23c2 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,3 +1,46 @@ +2003-02-08 kaz Kojima <kkojima@rr.iij4u.or.jp> + + * sysdeps/sh/Makefile: New file. + * sysdeps/sh/bits/atomic.h: New file. + * sysdeps/sh/pthread_spin_init.c: New file. + * sysdeps/sh/pthread_spin_lock.c: New file. + * sysdeps/sh/pthread_spin_trylock.S: New file. + * sysdeps/sh/pthread_spin_unlock.S: New file. + * sysdeps/sh/pthreaddef.h: New file. + * sysdeps/sh/tcb-offsets.sym: New file. + * sysdeps/sh/td_ta_map_lwp2thr.c: New file. + * sysdeps/sh/tls.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/sh/createthread.c: New file. + * sysdeps/unix/sysv/linux/sh/fork.c: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelcond.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: New file. + * sysdeps/unix/sysv/linux/sh/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/sh/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_post.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: New file. + 2003-02-08 Ulrich Drepper <drepper@redhat.com> * tst-cond2.c: Rearrange code to not rely on behavior undefined diff --git a/nptl/sysdeps/sh/bits/atomic.h b/nptl/sysdeps/sh/bits/atomic.h new file mode 100644 index 0000000000..de176ca2c5 --- /dev/null +++ b/nptl/sysdeps/sh/bits/atomic.h @@ -0,0 +1,405 @@ +/* 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 <stdint.h> + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#define __arch_compare_and_exchange_8_acq(mem, newval, oldval) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.b @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.b %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define __arch_compare_and_exchange_16_acq(mem, newval, oldval) \ + ({ unsigned char __result; \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.w @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.w %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define __arch_compare_and_exchange_32_acq(mem, newval, oldval) \ + ({ 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" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +/* XXX We do not really need 64-bit compare-and-exchange. At least + not in the moment. Using it would mean causing portability + problems since not many other 32-bit architectures have support for + such an operation. So don't define any code for now. */ + +# define __arch_compare_and_exchange_64_acq(mem, newval, oldval) \ + (abort (), 0) + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) __result; \ + if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,%0\n\ + add %0,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,%0\n\ + add %0,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,%0\n\ + add %0,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "memory"); \ + else \ + { \ + __typeof (value) addval = (value); \ + __typeof (*mem) oldval; \ + __typeof (mem) memp = (mem); \ + do \ + __result = (oldval = *memp) + addval; \ + while (!__arch_compare_and_exchange_64_acq (memp, __result, oldval));\ + (void) addval; \ + } \ + __result; }) + +#define atomic_add(mem, value) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%1,r2\n\ + add r2,%0\n\ + mov.b %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (value) : "r" (mem), "0" (value) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%1,r2\n\ + add r2,%0\n\ + mov.w %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (value) : "r" (mem), "0" (value) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,r2\n\ + add r2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (value) : "r" (mem), "0" (value) \ + : "r0", "r1", "r2", "memory"); \ + else \ + { \ + __typeof (value) addval = (value); \ + __typeof (*mem) oldval; \ + __typeof (mem) memp = (mem); \ + do \ + oldval = *memp; \ + while (! __arch_compare_and_exchange_64_acq (memp, \ + oldval + addval, \ + oldval)); \ + (void) addval; \ + } \ + }) + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,r2\n\ + add r2,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,r2\n\ + add r2,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,r2\n\ + add r2,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15\n\ + shal %1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else \ + abort (); \ + __result; }) + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%2,r2\n\ + add r2,%1\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%2,r2\n\ + add r2,%1\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,r2\n\ + add r2,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15\n\ + tst %1,%1\n\ + movt %0"\ + : "=r" (__result), "=&r" (value) : "r" (mem), "1" (value) \ + : "r0", "r1", "r2", "t", "memory"); \ + else \ + abort (); \ + __result; }) + +#define atomic_increment_and_test(mem) atomic_add_zero((mem), 1) +#define atomic_decrement_and_test(mem) atomic_add_zero((mem), -1) + +#define atomic_bit_set(mem, bit) \ + (void) ({ unsigned int __mask = 1 << (bit); \ + if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.b @%0,r2\n\ + or %1,r2\n\ + mov.b r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.w @%0,r2\n\ + or %1,r2\n\ + mov.w r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%0,r2\n\ + or %1,r2\n\ + mov.l r2,@%0\n\ + 1: mov r1,r15"\ + : : "r" (mem), "r" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else \ + abort (); \ + }) + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned int __mask = 1 << (bit); \ + unsigned int __result = __mask; \ + if (sizeof (*mem) == 1) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.b @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.b %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 2) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.w @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.w %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else if (sizeof (*mem) == 4) \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,r2\n\ + or r2,%1\n\ + and r2,%0\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (__mask) \ + : "r" (mem), "0" (__result), "1" (__mask) \ + : "r0", "r1", "r2", "memory"); \ + else \ + abort (); \ + __result; }) diff --git a/nptl/sysdeps/sh/pthread_spin_init.c b/nptl/sysdeps/sh/pthread_spin_init.c new file mode 100644 index 0000000000..0a47981aa2 --- /dev/null +++ b/nptl/sysdeps/sh/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* 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. */ + +/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */ diff --git a/nptl/sysdeps/sh/pthread_spin_lock.c b/nptl/sysdeps/sh/pthread_spin_lock.c new file mode 100644 index 0000000000..e732641083 --- /dev/null +++ b/nptl/sysdeps/sh/pthread_spin_lock.c @@ -0,0 +1,35 @@ +/* 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 "pthreadP.h" + +int +pthread_spin_lock (lock) + pthread_spinlock_t *lock; +{ + unsigned int val; + + do + asm volatile ("tas.b @%1; movt %0" + : "=&r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} diff --git a/nptl/sysdeps/sh/pthread_spin_trylock.S b/nptl/sysdeps/sh/pthread_spin_trylock.S new file mode 100644 index 0000000000..63ae4d36af --- /dev/null +++ b/nptl/sysdeps/sh/pthread_spin_trylock.S @@ -0,0 +1,32 @@ +/* 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. */ + +#define EBUSY 16 + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 5 +pthread_spin_trylock: + tas.b @r4 + bf/s 1f + mov #EBUSY, r0 + mov #0, r0 +1: + rts + nop + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/nptl/sysdeps/sh/pthread_spin_unlock.S b/nptl/sysdeps/sh/pthread_spin_unlock.S new file mode 100644 index 0000000000..c77acaffe3 --- /dev/null +++ b/nptl/sysdeps/sh/pthread_spin_unlock.S @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 5 +pthread_spin_unlock: + mov #0,r0 + rts + mov.l r0,@r4 + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/nptl/sysdeps/sh/pthreaddef.h b/nptl/sysdeps/sh/pthreaddef.h new file mode 100644 index 0000000000..c66e838bdc --- /dev/null +++ b/nptl/sysdeps/sh/pthreaddef.h @@ -0,0 +1,52 @@ +/* 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> + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 8 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 8 + +/* The signal used for asynchronous cancelation. */ +#define SIGCANCEL __SIGRTMIN + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + while (1) { \ + if (__builtin_constant_p (val) && (val) == 0) \ + asm volatile ("mov #0,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit)); \ + else \ + asm volatile ("mov %1,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit), "r" (val)); \ + } diff --git a/nptl/sysdeps/sh/tcb-offsets.sym b/nptl/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 0000000000..ae14fa00e9 --- /dev/null +++ b/nptl/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,5 @@ +#include <sysdep.h> +#include <tls.h> + +MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.data.multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct pthread) diff --git a/nptl/sysdeps/sh/td_ta_map_lwp2thr.c b/nptl/sysdeps/sh/td_ta_map_lwp2thr.c new file mode 100644 index 0000000000..75853009da --- /dev/null +++ b/nptl/sysdeps/sh/td_ta_map_lwp2thr.c @@ -0,0 +1,44 @@ +/* Which thread is running on an LWP? Stub version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include <tls.h> +#include <sys/reg.h> + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + prgregset_t regs; + if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) + return TD_ERR; + + th->th_unique = regs[REG_GBR]; + + /* Found it. Now complete the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + + return TD_OK; +} diff --git a/nptl/sysdeps/sh/tls.h b/nptl/sysdeps/sh/tls.h new file mode 100644 index 0000000000..b92b0b81d5 --- /dev/null +++ b/nptl/sysdeps/sh/tls.h @@ -0,0 +1,135 @@ +/* Definition for thread-local data handling. NPTL/SH version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include <dl-sysdep.h> + +#ifndef __ASSEMBLER__ +# include <stddef.h> +# include <stdint.h> + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include <tcb-offsets.h> +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include <sysdep.h> + +/* Get the thread descriptor definition. */ +# include <nptl/descr.h> + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm __volatile ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. + The contained asm must *not* be marked volatile since otherwise + assignments like + struct pthread *self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) ((THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) ((THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + (THREAD_SELF)->member = (value) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + (THREAD_SELF)->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h new file mode 100644 index 0000000000..97b94a3074 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,152 @@ +/* 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 _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 struct __opaque_pthread *pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __count; + struct pthread *__owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + } __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 long long int __total_seq; + unsigned long long int __wakeup_seq; + unsigned long long int __woken_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + 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; + + +#ifdef __USE_UNIX98 +/* 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/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h new file mode 100644 index 0000000000..ab46ac099b --- /dev/null +++ b/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 ((int) ((~0u) >> 1)) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/nptl/sysdeps/unix/sysv/linux/sh/createthread.c b/nptl/sysdeps/unix/sysv/linux/sh/createthread.c new file mode 100644 index 0000000000..8e68215385 --- /dev/null +++ b/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 <nptl/sysdeps/pthread/createthread.c> diff --git a/nptl/sysdeps/unix/sysv/linux/sh/fork.c b/nptl/sysdeps/unix/sysv/linux/sh/fork.c new file mode 100644 index 0000000000..6868b9bcd4 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sched.h> +#include <signal.h> +#include <sysdep.h> +#include <tls.h> + +/* 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/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S new file mode 100644 index 0000000000..350a935388 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -0,0 +1,221 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#include "lowlevel-atomic.h" + + .text + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define ETIMEDOUT 110 + + + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 5 +__lll_lock_wait: + mov r4, r6 + mov r5, r4 + mov #0, r7 /* No timeout. */ + mov #FUTEX_WAIT, r5 +2: + add #-1, r6 /* account for the preceeded xadd. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #-1, r3 + XADD (r3, @r4, r2) + tst r3, r3 + bf/s 2b + mov r2, r6 + + mov #-1, r1 + mov.l r1, @r4 + rts + mov r2, r0 + .size __lll_lock_wait,.-__lll_lock_wait + + + .type lll_unlock_wake_cb,@function + .align 5 +lll_unlock_wake_cb: + + .align 2 + mova 1f, r0 + mov r15, r1 + mov #-6, r15 +0: + mov.l @r4, r2 + add #1, r2 + mov.l r2, @r4 +1: + mov r1, r15 + cmp/pl r2 + bf 2f + rts + nop + .size lll_unlock_wake_cb,.-lll_unlock_wake_cb + + + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake +__lll_unlock_wake: +2: + mov #FUTEX_WAKE, r5 + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r6, @r4 /* Stores 1. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + .size __lll_unlock_wake,.-__lll_unlock_wake + + + .globl __lll_wait_tid + .type __lll_wait_tid,@function + .hidden __lll_wait_tid +__lll_wait_tid: + mov.l @r4, r6 +1: + mov #FUTEX_WAIT, r5 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov r0, r1 + + mov.l @r4, r0 + tst r0, r0 + bf/s 1b + mov r0, r6 + rts + nop + .size __lll_wait_tid,.-__lll_wait_tid + + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid +__lll_timedwait_tid: + mov.l r9, @-r15 + mov.l r8, @-r15 + mov r4, r8 + mov r5, r9 + 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 .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 6f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov.l @r8, r6 + tst r6, r6 + bt 4f + + 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, r1 + + mov.l @r8, r0 + tst r0, r0 + bf 1f +4: + mov #0, r0 +3: + add #8, r15 + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +1: + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bf 2b +6: + bra 3b + mov #ETIMEDOUT, r0 + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 + + .size __lll_timedwait_tid,.-__lll_timedwait_tid + + + .globl __lll_wake_tid + .type __lll_wake_tid,@function + .hidden __lll_wake_tid +__lll_wake_tid: + 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 __lll_wake_tid,.-__lll_wake_tid diff --git a/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S new file mode 100644 index 0000000000..8a837de7b1 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S @@ -0,0 +1,174 @@ +/* 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 "lowlevel-atomic.h" + + .text + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EWOULDBLOCK 11 +#define EINVAL 22 +#define ETIMEDOUT 110 + + + .globl __lll_mutex_lock_wait + .type __lll_mutex_lock_wait,@function + .hidden __lll_mutex_lock_wait + .align 5 +__lll_mutex_lock_wait: + mov r4, r6 + mov r5, r4 + mov #0, r7 /* No timeout. */ + mov #FUTEX_WAIT, r5 +1: + add #1, r6 /* account for the preceeded xadd. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #1, r3 + XADD (r3, @r4, r6) + tst r6, r6 + bf 1b + mov #2, r1 + mov.l r1, @r4 + ret + mov #0, r0 + .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + + .globl __lll_mutex_timedlock_wait + .type __lll_mutex_timedlock_wait,@function + .hidden __lll_mutex_timedlock_wait + .align 5 +__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 r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + mov r5, r8 + mov r6, r9 + mov r4, r10 + add #1, r10 + + /* 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 r8, r4 + mov #FUTEX_WAIT, r5 + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #1, r3 + XADD (r3, @r8, r10) + tst r10, r10 + bf 7f + + mov #2, r1 + mov.l r1, @r8 + mov #0, r0 +6: + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 +7: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bt 5f + 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 + + + .globl __lll_mutex_unlock_wake + .type __lll_mutex_unlock_wake,@function + .hidden __lll_mutex_unlock_wake + .align 5 +__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 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h new file mode 100644 index 0000000000..3a80ec8e14 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,68 @@ +/* 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. */ + +#ifdef __ASSEMBLER__ + +#define _IMP1 #1 +#define _IMM1 #-1 +#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, old) \ + .align 2; \ + mova 99f, r0; \ + mov r15, r1; \ + mov _IMM6, r15; \ +98: mov.l mem, old; \ + add old, reg; \ + 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/nptl/sysdeps/unix/sysv/linux/sh/lowlevelcond.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelcond.h new file mode 100644 index 0000000000..78e585f813 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelcond.h @@ -0,0 +1,23 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define cond_lock 0 +#define total_seq 4 +#define wakeup_seq 12 +#define woken_seq 20 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S new file mode 100644 index 0000000000..8352ef0450 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,224 @@ +/* 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 "lowlevel-atomic.h" + + .text + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define ETIMEDOUT 110 + + + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 5 +__lll_lock_wait: + mov r4, r6 + mov r5, r4 + mov #0, r7 /* No timeout. */ + mov #FUTEX_WAIT, r5 +2: + add #-1, r6 /* account for the preceeded xadd. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #-1, r3 + XADD (r3, @r4, r2) + tst r3, r3 + bf/s 2b + mov r2, r6 + + mov #-1, r1 + mov.l r1, @r4 + rts + mov r2, r0 + .size __lll_lock_wait,.-__lll_lock_wait + + + .globl lll_unlock_wake_cb + .type lll_unlock_wake_cb,@function + .hidden lll_unlock_wake_cb + .align 5 +lll_unlock_wake_cb: + + .align 2 + mova 1f, r0 + mov r15, r1 + mov #-6, r15 +0: + mov.l @r4, r2 + add #1, r2 + mov.l r2, @r4 +1: + mov r1, r15 + cmp/pl r2 + bf 2f + rts + nop + .size lll_unlock_wake_cb,.-lll_unlock_wake_cb + + + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake +__lll_unlock_wake: +2: + mov #FUTEX_WAKE, r5 + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r6, @r4 /* Stores 1. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + .size __lll_unlock_wake,.-__lll_unlock_wake + + + .globl __lll_wait_tid + .type __lll_wait_tid,@function + .hidden __lll_wait_tid +__lll_wait_tid: + mov.l @r4, r6 +1: + mov #FUTEX_WAIT, r5 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov r0, r1 + + mov.l @r4, r0 + tst r0, r0 + bf/s 1b + mov r0, r6 + rts + nop + .size __lll_wait_tid,.-__lll_wait_tid + + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid +__lll_timedwait_tid: + mov.l r9, @-r15 + mov.l r8, @-r15 + mov r4, r8 + mov r5, r9 + 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 .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 6f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov.l @r8, r6 + tst r6, r6 + bt 4f + + 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, r1 + + mov.l @r8, r0 + tst r0, r0 + bf 1f +4: + mov #0, r0 +3: + add #8, r15 + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +1: + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bf 2b +6: + bra 3b + mov #ETIMEDOUT, r0 + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 + + .size __lll_timedwait_tid,.-__lll_timedwait_tid + + + .globl __lll_wake_tid + .type __lll_wake_tid,@function + .hidden __lll_wake_tid +__lll_wake_tid: + 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 __lll_wake_tid,.-__lll_wake_tid + + diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h new file mode 100644 index 0000000000..d9a69c7a48 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,245 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include <time.h> +#include <sys/param.h> +#include <bits/pthreadtypes.h> + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + + +/* Initializer for compatibility lock. */ +#define LLL_MUTEX_LOCK_INITIALIZER (0) + +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" (1), "r" (0) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_mutex_lock(futex) \ + (void) ({ int __result, val, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,%0\n\ + add %0,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (val) : "r" (__futex), "1" (1) \ + : "r0", "r1", "memory"); \ + if (__result) \ + __lll_mutex_lock_wait (__result, __futex); }) + +#define lll_mutex_timedlock(futex, timeout) \ + ({ int __result, val, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,%0\n\ + add %0,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (val) : "r" (__futex), "1" (1) \ + : "r0", "r1", "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 (1) +#define LLL_LOCK_INITIALIZER_LOCKED (0) + + +extern int __lll_lock_wait (int val, int *__futex) attribute_hidden; +extern int __lll_unlock_wake (int *__futex) attribute_hidden; +extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; + + +/* The states of a lock are: + 1 - untaken + 0 - taken by one user + <0 - taken by more users */ + + +#define lll_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" (0), "r" (1) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_lock(futex) \ + (void) ({ int __result, val, *__futex = &(futex); \ + __asm __volatile ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%2,%0\n\ + add %0,%1\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result), "=&r" (val) : "r" (__futex), "1" (-1) \ + : "r0", "r1", "memory"); \ + if (val < 0) \ + __lll_lock_wait (__result, __futex); }) + +#define lll_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 <= 0) \ + __lll_unlock_wake (__futex); }) + +#define lll_islocked(futex) \ + (futex <= 0) + + +/* 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); \ + if (*__tid != 0) \ + __lll_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 == NULL || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + + +extern int __lll_wake_tid (int *tid) attribute_hidden; +#define lll_wake_tid(tid) \ + do { \ + (tid) = 0; \ + ___lll_wake_tid (&tid); \ + } while (0) + + +/* 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/nptl/sysdeps/unix/sysv/linux/sh/lowlevelmutex.S b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelmutex.S new file mode 100644 index 0000000000..8a837de7b1 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelmutex.S @@ -0,0 +1,174 @@ +/* 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 "lowlevel-atomic.h" + + .text + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EWOULDBLOCK 11 +#define EINVAL 22 +#define ETIMEDOUT 110 + + + .globl __lll_mutex_lock_wait + .type __lll_mutex_lock_wait,@function + .hidden __lll_mutex_lock_wait + .align 5 +__lll_mutex_lock_wait: + mov r4, r6 + mov r5, r4 + mov #0, r7 /* No timeout. */ + mov #FUTEX_WAIT, r5 +1: + add #1, r6 /* account for the preceeded xadd. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #1, r3 + XADD (r3, @r4, r6) + tst r6, r6 + bf 1b + mov #2, r1 + mov.l r1, @r4 + ret + mov #0, r0 + .size __lll_mutex_lock_wait,.-__lll_mutex_lock_wait + + + .globl __lll_mutex_timedlock_wait + .type __lll_mutex_timedlock_wait,@function + .hidden __lll_mutex_timedlock_wait + .align 5 +__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 r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + mov r5, r8 + mov r6, r9 + mov r4, r10 + add #1, r10 + + /* 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 r8, r4 + mov #FUTEX_WAIT, r5 + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov #1, r3 + XADD (r3, @r8, r10) + tst r10, r10 + bf 7f + + mov #2, r1 + mov.l r1, @r8 + mov #0, r0 +6: + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 +7: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bt 5f + 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 + + + .globl __lll_mutex_unlock_wake + .type __lll_mutex_unlock_wake,@function + .hidden __lll_mutex_unlock_wake + .align 5 +__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 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h new file mode 100644 index 0000000000..4357e80a0b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Offsets in the pthread_rwlock_t structure. */ +#define MUTEX 0 +#define NR_READERS 4 +#define READERS_WAKEUP 8 +#define WRITERS_WAKEUP 12 +#define READERS_QUEUED 16 +#define WRITERS_QUEUED 20 +#define FLAGS 24 +#define WRITER 28 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 0000000000..5391d5cc8b --- /dev/null +++ b/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/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S new file mode 100644 index 0000000000..5b13639c77 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/sh/vfork.S> diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S new file mode 100644 index 0000000000..eead7c6044 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,164 @@ +/* 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 "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define CURR_EVENT 0 +#define MUTEX 4 +#define LEFT 8 +#define INIT_COUNT 12 + + + .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 #-1, r3 + XADD (r3, @(MUTEX,r8), r2) + tst r3, r3 + 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. */ + INC (@(MUTEX,r8), r2) + cmp/pl 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 + + 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 @(INIT_COUNT,r8), r0 + mov.l r0, @(LEFT,r8) + 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 + + /* Release the mutex. */ + INC (@(MUTEX,r8), r2) + cmp/pl r2 + bf 4f +5: + mov #-1, r0 /* == PTHREAD_BARRIER_SERIAL_THREAD */ + lds.l @r15+, pr + mov.l @r15+, r8 + ret + 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 + + .align 2 +.Lall: + .long 0x7fffffff +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S new file mode 100644 index 0000000000..93818f96df --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,126 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + + + .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 r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + 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: + /* Case all currently waiting threads to wake up. */ + mov.l r1, @(wakeup_seq,r8) + mov.l r0, @(wakeup_seq+4,r8) + + /* Wake up all threads. */ + mov r8, r4 + add #wakeup_seq, 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: + /* 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 .Lmwait5, r1 + bsrf r1 + mov r2, r4 +.Lmwait5b: + bra 2b + nop + +5: + /* Unlock in loop requires waekup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l .Lmwake5, r1 + bsrf r1 + nop +.Lmwake5b: + bra 6b + nop + + .align 2 +.Lmwait5: + .long __lll_mutex_lock_wait-.Lmwait5b +.Lmwake5: + .long __lll_mutex_unlock_wake-.Lmwake5b + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, + GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S new file mode 100644 index 0000000000..a00064153f --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,133 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + + + .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 #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + 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) + + /* Wake up one thread. */ + mov r8, r4 + add #wakeup_seq, 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 +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, + GLIBC_2_3_2) + diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S new file mode 100644 index 0000000000..f0be38a797 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,361 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define ETIMEDOUT 110 + + + .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: + mov.l r12, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-48, r15 + mov r4, r8 + mov r5, r9 + mov r6, r10 + + /* Get internal lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + bt 2f + bra 1f + nop +2: + /* Unlock the mutex. */ + mov.l .Lmunlock1, r1 + bsrf r1 + mov r9, r4 +.Lmunlock1b: + + 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) + + /* Install cancellation handler. */ +#ifdef PIC + mova .Lgot1, r0 + mov.l .Lgot1, r12 + add r0, r12 + mov.l .Lccleanup1, r5 + add r12, r5 +#else + mov.l .Lccleanup1, r5 +#endif + mov r15, r4 + add #28, r4 + + mov.l .Lccpush1, r1 + bsrf r1 + mov r8, r6 +.Lccpush1b: + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + mov.l r0, @(12,r15) + mov.l r1, @(16,r15) + + /* Unlock. */ +8: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 4f + bra 3f + nop +4: + mov.l .Lenable1, r1 + bsrf r1 + nop +.Lenable1b: + mov.l r0, @r15 + + /* Get current time. */ + mov r15, r4 + add #4, r4 + mov #0, r5 + mov #SYS_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(8,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r10, r2 + mov.l @(4,r10), r3 + mov.l @(4,r15), r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 12f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +12: + cmp/pz r2 + bf 13f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @(4,r15) + mov.l r3, @(8,r15) + + mov r15, r7 + add #4, r7 + mov #FUTEX_WAIT, r5 + mov.l @(12,r15), r6 + mov r8, r4 + add #wakeup_seq, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov.l r0, @(20,r15) + + mov.l .Ldisable1, r1 + bsrf r1 + mov.l @r15, r4 +.Ldisable1b: + + /* Lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + bf 5f +6: + 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 + + mov.l @(16,r15), r5 + cmp/hi r5, r1 + bt 7f + cmp/hi r1, r5 + bt 15f + + mov.l @(12,r15), r5 + cmp/hi r0, r5 + bt 15f +7: + cmp/hi r1, r3 + bt 9f + cmp/hi r3, r1 + bt 15f + cmp/hi r0, r2 + bt 9f +15: + mov.l @(20,r15),r0 + cmp/eq #-ETIMEDOUT, r0 + bf 8b +13: + 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 #ETIMEDOUT, r0 + bra 14f + 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) + +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Remove cancellation handler. */ + mov r15, r4 + add #28, r4 + mov.l .Lcpop1, r1 + bsrf r1 + mov #0, r5 +.Lcpop1b: + + mov r9, r4 + mov.l .Lmlocki1, r1 + bsrf r1 + mov #0, r5 +.Lmlocki1b: + + mov.l @(24,r15), r0 + + add #48, r15 + + /* We return the result of the mutex_lock operation. */ + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + rts + mov.l @r15+, r12 + ret + +.L1k: + .word 1000 + .align 2 +.Lmunlock1: + .long __pthread_mutex_unlock_internal-.Lmunlock1b +#ifdef PIC +.Lgot1: + .long _GLOBAL_OFFSET_TABLE_ +.Lccleanup1: + .long __condvar_cleanup@GOTOFF +#else +.Lccleanup1: + .long __condvar_cleanup +#endif +.Lccpush1: + .long __pthread_cleanup_push-.Lccpush1b +.Lenable1: + .long __pthread_enable_asynccancel-.Lenable1b +.Ldisable1: + .long __pthread_disable_asynccancel-.Ldisable1b +.Lcpop1: + .long __pthread_cleanup_pop-.Lcpop1b +.Lmlocki1: + .long __pthread_mutex_lock_internal-.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 waekup. */ + 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 waekup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l .Lmwake3, r1 + bsrf r1 + nop +.Lmwake3b: + bra 11b + nop + + .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 + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, + GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S new file mode 100644 index 0000000000..342e78ed6e --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,364 @@ +/* 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 <shlib-compat.h> +#include <lowlevelcond.h> +#include "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + + + .text + + .align 5 + .type __condvar_cleanup, @function + .globl __condvar_cleanup + .hidden __condvar_cleanup +__condvar_cleanup: + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + bt 1f + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov r2, r4 + mov.l .Lwait0, r1 + bsrf r1 + nop +.Lwait0b: +1: + 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) + + 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) + + /* Release internal lock. */ +#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 .Lwake0, r1 + bsrf r1 + nop +.Lwake0b: +2: + lds.l @r15+, pr + rts + mov.l @r15+, r8 + + .align 2 +.Lwait0: + .long __lll_mutex_lock_wait-.Lwait0b +.Lwake0: + .long __lll_mutex_unlock_wake-.Lwake0b + .size __condvar_cleanup, .-__condvar_cleanup + + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .align 5 +__pthread_cond_wait: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-32, r15 + mov r4, r8 + mov r5, r9 + + /* Get internal lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + bf 1f +2: + /* Unlock the mutex. */ + mov.l .Lmunlock0, r1 + bsrf r1 + mov r9, r4 +.Lmunlock0b: + + 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) + + /* Install cancellation handler. */ +#ifdef PIC + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 + mov.l .Lccleanup0, r5 + add r12, r5 +#else + mov.l .Lccleanup0, r5 +#endif + mov r15, r4 + add #12, r4 + + mov.l .Lccpush0, r1 + bsrf r1 + mov r8, r6 +.Lccpush0b: + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + mov.l r0, @(4,r15) + mov.l r1, @(8,r15) + +8: + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 3f +4: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov.l r0, @r15 + + mov #0, r7 + mov #FUTEX_WAIT, r5 + mov.l @(4,r15), r6 + mov r8, r4 + add #wakeup_seq, 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: + + /* Lock. */ + mov #1, r3 +#if cond_lock != 0 + XADD (r3, @(cond_lock,r8), r2) +#else + XADD (r3, @r8, r2) +#endif + tst r2, r2 + bf 5f +6: + 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 + + mov.l @(8,r15), r5 + cmp/hi r5, r1 + bt 7f + cmp/hi r1, r5 + bt 8b + + mov.l @(4,r15), r5 + cmp/hi r0, r5 + bt 8b +7: + cmp/hi r1, r3 + bt 9f + cmp/hi r3, r1 + bt 8b + cmp/hi r0, r2 + bf 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) + +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Remove cancellation handler. */ + mov r15, r4 + add #12, r4 + mov.l .Lcpop0, r1 + bsrf r1 + mov #0, r5 +.Lcpop0b: + + mov r9, r4 + mov.l .Lmlocki0, r1 + bsrf r1 + mov #0, r5 +.Lmlocki0b: + + add #32, r15 + + /* We return the result of the mutex_lock operation. */ + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r12 + + .align 2 +.Lmunlock0: + .long __pthread_mutex_unlock_internal-.Lmunlock0b +#ifdef PIC +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +.Lccleanup0: + .long __condvar_cleanup@GOTOFF +#else +.Lccleanup0: + .long __condvar_cleanup +#endif +.Lccpush0: + .long __pthread_cleanup_push-.Lccpush0b +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b +.Lcpop0: + .long __pthread_cleanup_pop-.Lcpop0b +.Lmlocki0: + .long __pthread_mutex_lock_internal-.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 + + .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 + .size __pthread_cond_wait, .-__pthread_cond_wait +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2) diff --git a/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S new file mode 100644 index 0000000000..c17701cffc --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,197 @@ +/* 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 "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + + .comm __fork_generation, 4, 4 + + .text + .globl __pthread_once + .type __pthread_once,@function + .align 5 +__pthread_once: + mov.l @r4, r0 + tst #2, r0 + bt 1f + rts + mov #0, r0 + +1: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r5, r8 + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: + mov.l @r4, r1 +#ifdef PIC + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 +#endif + +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 +#ifdef PIC +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lfgen: + .long __fork_generation@GOTOFF +#else +.Lfgen: + .long __fork_generation +#endif + +3: + /* Call the initializer function after setting up the + cancellation handler. */ + /* Allocate a _pthread_cleanup_buffer on stack. */ + add #-16, r15 + + /* Push the cleanup handler. */ + mov r4, r9 + mov r15, r4 + mov.l .Lconce, r5 +#ifdef PIC + add r12, r5 +#endif + mov.l .Lcpush, r1 + bsrf r1 + mov r3, r6 +.Lcpush0: + jsr @r8 + nop + + /* Pop the cleanup handler. */ + mov r15, r4 + mov.l .Lcpop, r1 + bsrf r1 + mov #0, r5 +.Lcpop0: + add #16, r15 + + /* 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 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov #0, r0 + + .align 2 +.Lconce: +#ifdef PIC + .long clear_once_control@GOTOFF +#else + .long clear_once_control +#endif +.Lcpush: + .long __pthread_cleanup_push - .Lcpush0 /* Note: no @PLT. */ +.Lcpop: + .long __pthread_cleanup_pop - .Lcpop0 /* Note: no @PLT. */ + + .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/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S new file mode 100644 index 0000000000..2c6adf81c2 --- /dev/null +++ b/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 <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EAGAIN 11 +#define EDEADLK 35 + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .align 5 +__pthread_rwlock_rdlock: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + 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 + +#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 #0, r6 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + bf 12f +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bf 2b + bra 2b + mov.l r0, @(READERS_WAKEUP,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+, 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 .Ltcboff,r2 + sub r2,r1 + mov.l @(8,r1),r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +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 + +.Ltcboff: + .word TLS_PRE_TCB_SIZE + .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/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S new file mode 100644 index 0000000000..b287dd434b --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,274 @@ +/* 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 <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EAGAIN 11 +#define EDEADLK 35 +#define ETIMEDOUT 110 + + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 5 +pthread_rwlock_timedrdlock: + mov.l r12, @-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 #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + 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 + +#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 #0, 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 r8, r4 + mov #1, r5 +#if MUTEX == 0 + XADD (r5, @r4, r2) +#else + XADD (r5, @(MUTEX,r4), r2) +#endif + tst r2, r2 + bf 12f + +13: + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bt 18f + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bf 2b + bra 2b + mov.l r0, @(READERS_WAKEUP,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: + add #8,r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + 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 .Ltcboff,r2 + sub r2,r1 + mov.l @(8,r1),r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +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 + +18: + bra 9b + mov #ETIMEDOUT, r3 + +.Ltcboff: + .word TLS_PRE_TCB_SIZE + .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/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S new file mode 100644 index 0000000000..2e9bf05b00 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,259 @@ +/* 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 <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EAGAIN 11 +#define EDEADLK 35 +#define ETIMEDOUT 110 + + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 5 +pthread_rwlock_timedwrlock: + mov.l r12, @-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 #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + 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 + +#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 #0, 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 r8, r4 + mov #1, r5 +#if MUTEX == 0 + XADD (r5, @r4, r2) +#else + XADD (r5, @(MUTEX,r4), r2) +#endif + tst r2, r2 + bf 12f + +13: + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bt 18f + mov.l @(WRITERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + mov #0, r0 + bra 2b + mov.l r0, @(WRITERS_WAKEUP,r8) + +5: + mov #0, r3 + stc gbr, r1 + mov.w .Ltcboff,r2 + sub r2,r1 + mov.l @(8,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+, 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 .Ltcboff,r2 + sub r2,r1 + mov.l @(8,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 + +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 + +18: + bra 9b + mov #ETIMEDOUT, r3 + +.Ltcboff: + .word TLS_PRE_TCB_SIZE + .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/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S new file mode 100644 index 0000000000..af046aad47 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,128 @@ +/* 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 SYS_futex 240 +#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 #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + 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 r8, r4 + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bf 9f + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + bra 0f + add #READERS_WAKEUP, r4 +9: + mov #1, r6 + add #WRITERS_WAKEUP, r4 +0: + mov #FUTEX_WAKE, r5 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +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 + + .align 2 +.Lwait8: + .long __lll_mutex_lock_wait-.Lwait8b +.Lwake8: + .long __lll_mutex_unlock_wake-.Lwake8b + .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/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S b/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S new file mode 100644 index 0000000000..20c84235ce --- /dev/null +++ b/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 <tcb-offsets.h> +#include "lowlevel-atomic.h" + +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EAGAIN 11 +#define EDEADLK 35 + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .align 5 +__pthread_rwlock_wrlock: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + 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 + +#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 #0, r6 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #1, r3 +#if MUTEX == 0 + XADD (r3, @r4, r2) +#else + XADD (r3, @(MUTEX,r4), r2) +#endif + tst r2, r2 + bf 12f +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(READERS_QUEUED,r8) + mov #0, r0 + bra 2b + mov.l r0, @(WRITERS_WAKEUP,r8) + +5: + mov #0, r3 + stc gbr, r1 + mov.w .Ltcboff,r2 + sub r2,r1 + mov.l @(8,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+, 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 .Ltcboff,r2 + sub r2,r1 + mov.l @(8,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 + +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 + +.Ltcboff: + .word TLS_PRE_TCB_SIZE + .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/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S new file mode 100644 index 0000000000..9f33847339 --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,92 @@ +/* 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 <shlib-compat.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EINTR 4 +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EINVAL 22 +#define ETIMEDOUT 110 + + .text + + .globl __new_sem_post + .type __new_sem_post,@function + .align 5 +__new_sem_post: + mov #1, r3 + XADD (r3, @r4, r2) + + mov #FUTEX_WAKE, r5 + mov r2, r6 + add #1, r6 + 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 #EAGAIN, 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 + add r1, r0 +#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 +.Lerrno3: + .long errno@GOTTPOFF +#else +.Lerrloc3: + .long __errno_location@PLT-(.Lerrloc3b+2-.) +#endif + .size __new_sem_post,.-__new_sem_post + .symver __new_sem_post, sem_post@@GLIBC_2.2 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S new file mode 100644 index 0000000000..741d66383f --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,178 @@ +/* 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 <shlib-compat.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EINTR 4 +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EINVAL 22 +#define ETIMEDOUT 110 + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 5 +sem_timedwait: + 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 r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-8, r15 + 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: + /* 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 6f /* Time is already up. */ + + /* 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 + + 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+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + 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 + add r1, r0 + mov.l r8, @r0 +#else + mov.l .Lerrloc2, r1 + bsrf r1 + nop +.Lerrloc2b: + mov.l r8, @r0 +#endif + add #8, r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov #-1, r0 + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 +.Lgot2: + .long _GLOBAL_OFFSET_TABLE_ +#if USE___THREAD +.Lerrno2: + .long errno@GOTTPOFF +#else +.Lerrloc2: + .long __errno_location@PLT-(.Lerrloc2b+2-.) +#endif + .size sem_timedwait,.-sem_timedwait diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S new file mode 100644 index 0000000000..130536234d --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S @@ -0,0 +1,99 @@ +/* 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 <shlib-compat.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EINTR 4 +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EINVAL 22 +#define ETIMEDOUT 110 + + .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 + add r1, r0 + mov.l r8, @r0 +#else + mov.l .Lerrloc1, r1 + bsrf r1 + nop +.Lerrloc1b: + mov.l r8, @r0 +#endif + 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 +.Lerrno1: + .long errno@GOTTPOFF +#else +.Lerrloc1: + .long __errno_location@PLT-(.Lerrloc1b+2-.) +#endif + .size __new_sem_trywait,.-__new_sem_trywait + .symver __new_sem_trywait, sem_trywait@@GLIBC_2.2 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S new file mode 100644 index 0000000000..c275f204db --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,112 @@ +/* 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 <shlib-compat.h> +#include "lowlevel-atomic.h" + + +#define SYS_gettimeofday __NR_gettimeofday +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 + +#define EINTR 4 +#define EAGAIN 11 +#define EWOULDBLOCK EAGAIN +#define EINVAL 22 +#define ETIMEDOUT 110 + + .text + + .globl __new_sem_wait + .type __new_sem_wait,@function + .align 5 +__new_sem_wait: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + 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 2b + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 + +1: + 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 + + 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 + add r1, r0 + mov.l r8, @r0 +#else + mov.l .Lerrloc0, r1 + bsrf r1 + nop +.Lerrloc0b: + mov.l r8, @r0 +#endif + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #-1, r0 + + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#if USE___THREAD +.Lerrno0: + .long errno@GOTTPOFF +#else +.Lerrloc0: + .long __errno_location@PLT-(.Lerrloc0b+2-.) +#endif + .size __new_sem_wait,.-__new_sem_wait + .symver __new_sem_wait, sem_wait@@GLIBC_2.2 diff --git a/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 0000000000..07bac6d35d --- /dev/null +++ b/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#ifndef __ASSEMBLER__ +# include <nptl/pthreadP.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + 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; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + add _IMM16,r15; \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + lds.l @r15+,pr; \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + mov.l r0,@-r15; \ + CDISABLE; \ + mov.l @r15+,r0; \ + lds.l @r15+,pr; \ + 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: + +# 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 +# else +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# endif + +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 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.data.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__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif |