Clean up BUSY_WAIT_NOP and atomic_delay.

This patch combines BUSY_WAIT_NOP and atomic_delay into a new
atomic_spin_nop function and adjusts all clients.  The new function is
put into atomic.h because what is best done in a spin loop is
architecture-specific, and atomics must be used for spinning.  The
function name is meant to tell users that this has no effect on
synchronization semantics but is a performance aid for spinning.
This commit is contained in:
Torvald Riegel 2015-06-23 15:22:25 +02:00
parent e02920bc02
commit 4eb984d3ab
14 changed files with 42 additions and 33 deletions

View File

@ -1,3 +1,26 @@
2015-06-30 Torvald Riegel <triegel@redhat.com>
* sysdeps/unix/sysv/linux/i386/lowlevellock.h (BUSY_WAIT_NOP): Remove.
* sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (BUSY_WAIT_NOP):
Likewise.
* sysdeps/i386/i486/bits/atomic.h (atomic_delay): Rename to
atomic_spin_nop.
* sysdeps/x86_64/bits/atomic.h: Likewise.
* sysdeps/unix/sysv/linux/sparc/lowlevellock.h (BUSY_WAIT_NOP): Rename
to atomic_spin_nop and move ...
* sysdeps/sparc/sparc32/sparcv9/bits/atomic.h (atomic_spin_nop):
... here and ...
* sysdeps/sparc/sparc64/bits/atomic.h: ... here.
* nptl/pthread_mutex_lock.c (__pthread_mutex_lock): Use
atomic_spin_nop instead of BUSY_WAIT_NOP.
* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock):
Likewise.
* sysdeps/nacl/lll_timedwait_tid.c (__lll_timedwait_tid): Likewise.
* sysdeps/nacl/lowlevellock.h (BUSY_WAIT_NOP): Remove.
(lll_wait_tid): Use atomic_spin_nop instead of BUSY_WAIT_NOP.
* nscd/nscd-client.h (__nscd_acquire_maplock): Use atomic_spin_nop
instead of atomic_delay.
2015-06-29 Joseph Myers <joseph@codesourcery.com> 2015-06-29 Joseph Myers <joseph@codesourcery.com>
[BZ #18613] [BZ #18613]

View File

@ -754,9 +754,10 @@ void __atomic_link_error (void);
#endif /* !USE_ATOMIC_COMPILER_BUILTINS */ #endif /* !USE_ATOMIC_COMPILER_BUILTINS */
/* This operation does not affect synchronization semantics but can be used
#ifndef atomic_delay in the body of a spin loop to potentially improve its efficiency. */
# define atomic_delay() do { /* nothing */ } while (0) #ifndef atomic_spin_nop
# define atomic_spin_nop() do { /* nothing */ } while (0)
#endif #endif
#endif /* atomic.h */ #endif /* atomic.h */

View File

@ -23,6 +23,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <not-cancel.h> #include <not-cancel.h>
#include "pthreadP.h" #include "pthreadP.h"
#include <atomic.h>
#include <lowlevellock.h> #include <lowlevellock.h>
#include <stap-probe.h> #include <stap-probe.h>
@ -135,10 +136,7 @@ __pthread_mutex_lock (mutex)
LLL_MUTEX_LOCK (mutex); LLL_MUTEX_LOCK (mutex);
break; break;
} }
atomic_spin_nop ();
#ifdef BUSY_WAIT_NOP
BUSY_WAIT_NOP;
#endif
} }
while (LLL_MUTEX_TRYLOCK (mutex) != 0); while (LLL_MUTEX_TRYLOCK (mutex) != 0);

View File

@ -22,6 +22,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
#include "pthreadP.h" #include "pthreadP.h"
#include <atomic.h>
#include <lowlevellock.h> #include <lowlevellock.h>
#include <not-cancel.h> #include <not-cancel.h>
@ -125,10 +126,7 @@ pthread_mutex_timedlock (mutex, abstime)
PTHREAD_MUTEX_PSHARED (mutex)); PTHREAD_MUTEX_PSHARED (mutex));
break; break;
} }
atomic_spin_nop ();
#ifdef BUSY_WAIT_NOP
BUSY_WAIT_NOP;
#endif
} }
while (lll_trylock (mutex->__data.__lock) != 0); while (lll_trylock (mutex->__data.__lock) != 0);

View File

@ -378,7 +378,7 @@ __nscd_acquire_maplock (volatile struct locked_map_ptr *mapptr)
if (__glibc_unlikely (++cnt > 5)) if (__glibc_unlikely (++cnt > 5))
return false; return false;
atomic_delay (); atomic_spin_nop ();
} }
return true; return true;

View File

@ -479,7 +479,7 @@ typedef uintmax_t uatomic_max_t;
__result; }) __result; })
#define atomic_delay() asm ("rep; nop") #define atomic_spin_nop() asm ("rep; nop")
#define __arch_and_body(lock, mem, mask) \ #define __arch_and_body(lock, mem, mask) \

View File

@ -40,7 +40,7 @@ __lll_timedwait_tid (int *tidp, const struct timespec *abstime)
finish quick enough that the timeout doesn't matter. If any finish quick enough that the timeout doesn't matter. If any
thread ever stays in this state for long, there is something thread ever stays in this state for long, there is something
catastrophically wrong. */ catastrophically wrong. */
BUSY_WAIT_NOP; atomic_spin_nop ();
else else
{ {
assert (tid > 0); assert (tid > 0);

View File

@ -21,10 +21,6 @@
/* Everything except the exit handling is the same as the generic code. */ /* Everything except the exit handling is the same as the generic code. */
# include <sysdeps/nptl/lowlevellock.h> # include <sysdeps/nptl/lowlevellock.h>
# ifndef BUSY_WAIT_NOP
# define BUSY_WAIT_NOP __sync_synchronize ()
# endif
/* See exit-thread.h for details. */ /* See exit-thread.h for details. */
# define NACL_EXITING_TID 1 # define NACL_EXITING_TID 1
@ -36,7 +32,7 @@
while ((__tid = atomic_load_relaxed (__tidp)) != 0) \ while ((__tid = atomic_load_relaxed (__tidp)) != 0) \
{ \ { \
if (__tid == NACL_EXITING_TID) \ if (__tid == NACL_EXITING_TID) \
BUSY_WAIT_NOP; \ atomic_spin_nop (); \
else \ else \
lll_futex_wait (__tidp, __tid, LLL_PRIVATE); \ lll_futex_wait (__tidp, __tid, LLL_PRIVATE); \
} \ } \

View File

@ -100,3 +100,6 @@ typedef uintmax_t uatomic_max_t;
__asm __volatile ("membar #LoadLoad | #LoadStore" : : : "memory") __asm __volatile ("membar #LoadLoad | #LoadStore" : : : "memory")
#define atomic_write_barrier() \ #define atomic_write_barrier() \
__asm __volatile ("membar #LoadStore | #StoreStore" : : : "memory") __asm __volatile ("membar #LoadStore | #StoreStore" : : : "memory")
extern void __cpu_relax (void);
#define atomic_spin_nop () __cpu_relax ()

View File

@ -121,3 +121,6 @@ typedef uintmax_t uatomic_max_t;
__asm __volatile ("membar #LoadLoad | #LoadStore" : : : "memory") __asm __volatile ("membar #LoadLoad | #LoadStore" : : : "memory")
#define atomic_write_barrier() \ #define atomic_write_barrier() \
__asm __volatile ("membar #LoadStore | #StoreStore" : : : "memory") __asm __volatile ("membar #LoadStore | #StoreStore" : : : "memory")
extern void __cpu_relax (void);
#define atomic_spin_nop () __cpu_relax ()

View File

@ -58,10 +58,6 @@
#define LLL_LOCK_INITIALIZER_WAITERS (2) #define LLL_LOCK_INITIALIZER_WAITERS (2)
/* Delay in spinlock loop. */
#define BUSY_WAIT_NOP asm ("rep; nop")
/* NB: in the lll_trylock macro we simply return the value in %eax /* NB: in the lll_trylock macro we simply return the value in %eax
after the cmpxchg instruction. In case the operation succeded this after the cmpxchg instruction. In case the operation succeded this
value is zero. In case the operation failed, the cmpxchg instruction value is zero. In case the operation failed, the cmpxchg instruction

View File

@ -25,12 +25,6 @@
#include <atomic.h> #include <atomic.h>
#include <kernel-features.h> #include <kernel-features.h>
#ifndef __sparc32_atomic_do_lock
/* Delay in spinlock loop. */
extern void __cpu_relax (void);
#define BUSY_WAIT_NOP __cpu_relax ()
#endif
#include <lowlevellock-futex.h> #include <lowlevellock-futex.h>
static inline int static inline int

View File

@ -57,9 +57,6 @@
#define LLL_LOCK_INITIALIZER_LOCKED (1) #define LLL_LOCK_INITIALIZER_LOCKED (1)
#define LLL_LOCK_INITIALIZER_WAITERS (2) #define LLL_LOCK_INITIALIZER_WAITERS (2)
/* Delay in spinlock loop. */
#define BUSY_WAIT_NOP asm ("rep; nop")
/* NB: in the lll_trylock macro we simply return the value in %eax /* NB: in the lll_trylock macro we simply return the value in %eax
after the cmpxchg instruction. In case the operation succeded this after the cmpxchg instruction. In case the operation succeded this

View File

@ -410,7 +410,7 @@ typedef uintmax_t uatomic_max_t;
__result; }) __result; })
#define atomic_delay() asm ("rep; nop") #define atomic_spin_nop() asm ("rep; nop")
#define __arch_and_body(lock, mem, mask) \ #define __arch_and_body(lock, mem, mask) \