diff options
-rw-r--r-- | libpthread/nptl/sysdeps/arm/pthread_spin_lock.c | 66 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S | 33 | ||||
-rw-r--r-- | libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c (renamed from libpthread/nptl/sysdeps/arm/pthread_spin_lock.S) | 23 |
3 files changed, 76 insertions, 46 deletions
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 + <http://www.gnu.org/licenses/>. */ + +#include <atomic.h> +#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 - <http://www.gnu.org/licenses/>. */ - -#define _ERRNO_H 1 -#include <bits/errno.h> - -#include <sysdep.h> - - .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_lock.S b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c index a9c07c87d..4e1a96c03 100644 --- a/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S +++ b/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2005 Free Software Foundation, Inc. +/* 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 @@ -15,16 +16,12 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <sysdep.h> +#include <errno.h> +#include <atomic.h> +#include "pthreadP.h" - .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) +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return atomic_exchange_acq (lock, 1) ? EBUSY : 0; +} |