diff options
author | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-31 18:05:44 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-11-03 20:37:48 +0100 |
commit | 191739597c6d380692885cfdd8dd8aa4f31f029d (patch) | |
tree | b3f05ce72f7a87433905698dd58371048c904812 /libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c | |
parent | 7825930078208462655e107677656c45014e91b4 (diff) |
microblaze: add NPTL/TLS support from GNU libc
Not perfect, but a starting point.
Some tests of the test suite are failing.
Diffstat (limited to 'libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c')
-rw-r--r-- | libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c b/libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c new file mode 100644 index 000000000..e393a73ac --- /dev/null +++ b/libpthread/nptl/sysdeps/microblaze/pthread_spin_lock.c @@ -0,0 +1,62 @@ +/* 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" + +#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; +} |