From a2b99c04d8359a8a2098d1217f3c7475547fa0cf Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Fri, 15 Dec 2017 21:34:23 +0100 Subject: sh: remove assembly code from NPTL --- .../nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h | 532 ++++++++------------- 1 file changed, 203 insertions(+), 329 deletions(-) (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h') diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h index a9652bbb1..abe6e9c37 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -1,5 +1,4 @@ -/* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. +/* Copyright (C) 2005-2013 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 @@ -9,27 +8,29 @@ 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 + 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, see + License along with the GNU C Library. If not, see . */ #ifndef _LOWLEVELLOCK_H #define _LOWLEVELLOCK_H 1 -#ifndef __ASSEMBLER__ #include #include #include +#include +#include #include -#endif #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 @@ -40,13 +41,11 @@ #define FUTEX_BITSET_MATCH_ANY 0xffffffff -#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) - /* Values for 'private' parameter of locking macros. Yes, the definition seems to be backwards. But it is not. The bit will be reversed before passing to the system call. */ -#define LLL_PRIVATE 0 -#define LLL_SHARED FUTEX_PRIVATE_FLAG +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG #if !defined NOT_IN_libc || defined IS_IN_rtld @@ -73,347 +72,222 @@ # endif #endif -#ifndef __ASSEMBLER__ -/* Initializer for compatibility lock. */ -#define LLL_LOCK_INITIALIZER (0) -#define LLL_LOCK_INITIALIZER_LOCKED (1) -#define LLL_LOCK_INITIALIZER_WAITERS (2) - -extern int __lll_lock_wait_private (int val, int *__futex) - attribute_hidden; -extern int __lll_lock_wait (int val, int *__futex, int private) - attribute_hidden; -extern int __lll_timedlock_wait (int val, int *__futex, - const struct timespec *abstime, int private) - attribute_hidden; -extern int __lll_robust_lock_wait (int val, int *__futex, int private) - attribute_hidden; -extern int __lll_robust_timedlock_wait (int val, int *__futex, - const struct timespec *abstime, - int private) - attribute_hidden; -extern int __lll_unlock_wake_private (int *__futex) attribute_hidden; -extern int __lll_unlock_wake (int *__futex, int private) attribute_hidden; - -#define lll_trylock(futex) \ - ({ unsigned char __ret; \ - __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" (__ret) \ - : "r" (&(futex)), \ - "r" (LLL_LOCK_INITIALIZER_LOCKED), \ - "r" (LLL_LOCK_INITIALIZER) \ - : "r0", "r1", "r2", "t", "memory"); \ - __ret; }) - -#define lll_robust_trylock(futex, id) \ - ({ unsigned char __ret; \ - __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" (__ret) \ - : "r" (&(futex)), \ - "r" (id), \ - "r" (LLL_LOCK_INITIALIZER) \ - : "r0", "r1", "r2", "t", "memory"); \ - __ret; }) - -#define lll_cond_trylock(futex) \ - ({ unsigned char __ret; \ - __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" (__ret) \ - : "r" (&(futex)), \ - "r" (LLL_LOCK_INITIALIZER_WAITERS), \ - "r" (LLL_LOCK_INITIALIZER) \ - : "r0", "r1", "r2", "t", "memory"); \ - __ret; }) - -#define lll_lock(futex, private) \ - (void) ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (1), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - { \ - if (__builtin_constant_p (private) \ - && (private) == LLL_PRIVATE) \ - __lll_lock_wait_private (__ret, __futex); \ - else \ - __lll_lock_wait (__ret, __futex, (private)); \ - } \ - }) +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait(futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + int __op = FUTEX_WAIT_BITSET | clockbit; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (__op, private), \ + (val), (timespec), NULL /* Unused. */, \ + FUTEX_BITSET_MATCH_ANY); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +#define lll_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 1, 0) + +#define lll_cond_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 2, 0) + +#define __lll_robust_trylock(futex, id) \ + (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0) +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \ + 1, 0), 0)) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + })) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) #define lll_robust_lock(futex, id, private) \ - ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (id), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - __ret = __lll_robust_lock_wait (__ret, __futex, private); \ - __ret; }) - -/* Special version of lll_mutex_lock which causes the unlock function to - always wakeup waiters. */ -#define lll_cond_lock(futex, private) \ - (void) ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (2), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - __lll_lock_wait (__ret, __futex, private); }) + __lll_robust_lock (&(futex), id, private) + + +#define __lll_cond_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \ + __lll_lock_wait (__futex, private); \ + })) +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + #define lll_robust_cond_lock(futex, id, private) \ - ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (id | FUTEX_WAITERS), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - __ret = __lll_robust_lock_wait (__ret, __futex, private); \ - __ret; }) - -#define lll_timedlock(futex, timeout, private) \ - ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (1), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - __ret = __lll_timedlock_wait (__ret, __futex, timeout, private); \ - __ret; }) - -#define lll_robust_timedlock(futex, timeout, id, private) \ - ({ int __ret, *__futex = &(futex); \ - __asm__ __volatile__ ("\ - .align 2\n\ - mova 1f,r0\n\ - nop\n\ - mov r15,r1\n\ - mov #-8,r15\n\ - 0: mov.l @%2,%0\n\ - tst %0,%0\n\ - bf 1f\n\ - mov.l %1,@%2\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (id), "r" (__futex) \ - : "r0", "r1", "t", "memory"); \ - if (__ret) \ - __ret = __lll_robust_timedlock_wait (__ret, __futex, \ - timeout, private); \ - __ret; }) - -#define lll_unlock(futex, private) \ - (void) ({ int __ret, *__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" (__ret) : "r" (__futex) \ - : "r0", "r1", "memory"); \ - if (__ret) \ - { \ - if (__builtin_constant_p (private) \ - && (private) == LLL_PRIVATE) \ - __lll_unlock_wake_private (__futex); \ - else \ - __lll_unlock_wake (__futex, (private)); \ - } \ - }) + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) -#define lll_robust_unlock(futex, private) \ - (void) ({ int __ret, *__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\ - and %2,%0\n\ - mov.l %0,@%1\n\ - 1: mov r1,r15"\ - : "=&r" (__ret) : "r" (__futex), "r" (FUTEX_WAITERS) \ - : "r0", "r1", "memory"); \ - if (__ret) \ - __lll_unlock_wake (__futex, private); }) - -#define lll_robust_dead(futex, private) \ - (void) ({ int __ignore, *__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\ - or %2,%0\n\ - mov.l %0,@%1\n\ - 1: mov r1,r15"\ - : "=&r" (__ignore) : "r" (__futex), "r" (FUTEX_OWNER_DIED) \ - : "r0", "r1", "memory"); \ - lll_futex_wake (__futex, 1, private); }) - -# ifdef NEED_SYSCALL_INST_PAD -# define SYSCALL_WITH_INST_PAD "\ - trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" -# else -# define SYSCALL_WITH_INST_PAD "\ - trapa #0x14" -# endif -#define lll_futex_wait(futex, val, private) \ - lll_futex_timed_wait (futex, val, NULL, private) +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +#define __lll_timedlock(futex, abstime, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) -#define lll_futex_timed_wait(futex, val, timeout, private) \ +#define __lll_robust_timedlock(futex, abstime, id, private) \ ({ \ - int __status; \ - register unsigned long __r3 __asm__ ("r3") = SYS_futex; \ - register unsigned long __r4 __asm__ ("r4") = (unsigned long) (futex); \ - register unsigned long __r5 __asm__ ("r5") \ - = __lll_private_flag (FUTEX_WAIT, private); \ - register unsigned long __r6 __asm__ ("r6") = (unsigned long) (val); \ - register unsigned long __r7 __asm__ ("r7") = (unsigned long) (timeout); \ - __asm__ __volatile__ (SYSCALL_WITH_INST_PAD \ - : "=z" (__status) \ - : "r" (__r3), "r" (__r4), "r" (__r5), \ - "r" (__r6), "r" (__r7) \ - : "memory", "t"); \ - __status; \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ }) +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) -#define lll_futex_wake(futex, nr, private) \ - do { \ - int __ignore; \ - register unsigned long __r3 __asm__ ("r3") = SYS_futex; \ - register unsigned long __r4 __asm__ ("r4") = (unsigned long) (futex); \ - register unsigned long __r5 __asm__ ("r5") \ - = __lll_private_flag (FUTEX_WAKE, private); \ - register unsigned long __r6 __asm__ ("r6") = (unsigned long) (nr); \ - register unsigned long __r7 __asm__ ("r7") = 0; \ - __asm__ __volatile__ (SYSCALL_WITH_INST_PAD \ - : "=z" (__ignore) \ - : "r" (__r3), "r" (__r4), "r" (__r5), \ - "r" (__r6), "r" (__r7) \ - : "memory", "t"); \ - } while (0) +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) #define lll_islocked(futex) \ - (futex != LLL_LOCK_INITIALIZER) + (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible + mutex implementation. */ + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ -/* The kernel notifies a process with uses CLONE_CLEARTID via futex +/* The kernel notifies a process which uses CLONE_CHILD_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. */ - + afterwards. */ #define lll_wait_tid(tid) \ - do { \ - __typeof (tid) __tid; \ - while ((__tid = (tid)) != 0) \ - lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED);\ } while (0) -extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) +extern int __lll_timedwait_tid (int *, const struct timespec *) attribute_hidden; -#define lll_timedwait_tid(tid, abstime) \ - ({ \ - int __ret = 0; \ - if (tid != 0) \ - { \ - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ - __ret = EINVAL; \ - else \ - __ret = __lll_timedwait_tid (&tid, abstime); \ - } \ - __ret; }) -#endif /* !__ASSEMBLER__ */ +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) -#endif /* lowlevellock.h */ +#endif /* lowlevellock.h */ -- cgit v1.2.3