From 3ac3d4e61a1de0c2d0e0d2bebf0d1b111f153f12 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 31 May 2016 20:51:29 +0200 Subject: arm: add non-assembly versions of pthread_spin_lock/pthread_spin_trylock Sync pthread_spin_lock/pthread_spin_trylock with GNU libc as it avoids any usage of deprecated SWP instruction. This allows to build uClibc-ng for ARMv8 Cortex-A53 CPU in 32 Bit mode. --- libpthread/nptl/sysdeps/arm/pthread_spin_lock.S | 30 ---------- libpthread/nptl/sysdeps/arm/pthread_spin_lock.c | 66 ++++++++++++++++++++++ libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S | 33 ----------- libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c | 27 +++++++++ 4 files changed, 93 insertions(+), 63 deletions(-) delete mode 100644 libpthread/nptl/sysdeps/arm/pthread_spin_lock.S create mode 100644 libpthread/nptl/sysdeps/arm/pthread_spin_lock.c delete mode 100644 libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S create mode 100644 libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c (limited to 'libpthread') diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S deleted file mode 100644 index a9c07c87d..000000000 --- a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S +++ /dev/null @@ -1,30 +0,0 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#include - - .text - .align 4 - -ENTRY (pthread_spin_lock) - mov r1, #1 -1: swp r2, r1, [r0] - teq r2, #0 - bne 1b - mov r0, #0 - PSEUDO_RET_NOERRNO -END (pthread_spin_lock) diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.c b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.c new file mode 100644 index 000000000..77f5f502e --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/pthread_spin_lock.c @@ -0,0 +1,66 @@ +/* pthread_spin_lock -- lock a spin lock. Generic version. + Copyright (C) 2012-2016 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, see + . */ + +#include +#include "pthreadP.h" + +/* A machine-specific version can define SPIN_LOCK_READS_BETWEEN_CMPXCHG + to the number of plain reads that it's optimal to spin on between uses + of atomic_compare_and_exchange_val_acq. If spinning forever is optimal + then use -1. If no plain reads here would ever be optimal, use 0. */ +#define SPIN_LOCK_READS_BETWEEN_CMPXCHG 1000 + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + /* atomic_exchange usually takes less instructions than + atomic_compare_and_exchange. On the other hand, + atomic_compare_and_exchange potentially generates less bus traffic + when the lock is locked. + We assume that the first try mostly will be successful, and we use + atomic_exchange. For the subsequent tries we use + atomic_compare_and_exchange. */ + if (atomic_exchange_acq (lock, 1) == 0) + return 0; + + do + { + /* The lock is contended and we need to wait. Going straight back + to cmpxchg is not a good idea on many targets as that will force + expensive memory synchronizations among processors and penalize other + running threads. + On the other hand, we do want to update memory state on the local core + once in a while to avoid spinning indefinitely until some event that + will happen to update local memory as a side-effect. */ + if (SPIN_LOCK_READS_BETWEEN_CMPXCHG >= 0) + { + int wait = SPIN_LOCK_READS_BETWEEN_CMPXCHG; + + while (*lock != 0 && wait > 0) + --wait; + } + else + { + while (*lock != 0) + ; + } + } + while (atomic_compare_and_exchange_val_acq (lock, 1, 0) != 0); + + return 0; +} diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S deleted file mode 100644 index 8ccaffd75..000000000 --- a/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -#define _ERRNO_H 1 -#include - -#include - - .text - .align 4 - -ENTRY (pthread_spin_trylock) - mov r1, #1 - swp r2, r1, [r0] - teq r2, #0 - moveq r0, #0 - movne r0, #EBUSY - PSEUDO_RET_NOERRNO -END (pthread_spin_trylock) diff --git a/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c new file mode 100644 index 000000000..4e1a96c03 --- /dev/null +++ b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c @@ -0,0 +1,27 @@ +/* pthread_spin_trylock -- trylock a spin lock. Generic version. + Copyright (C) 2012-2016 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, see + . */ + +#include +#include +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return atomic_exchange_acq (lock, 1) ? EBUSY : 0; +} -- cgit v1.2.3