mirror of
https://github.com/postgres/postgres.git
synced 2025-05-02 11:44:50 +03:00
Improve spinlock performance for HP-UX, ia64, non-gcc.
At least on this architecture, it's very important to spin on a non-atomic instruction and only retry the atomic once it appears that it will succeed. To fix this, split TAS() into two macros: TAS(), for trying to grab the lock the first time, and TAS_SPIN(), for spinning until we get it. TAS_SPIN() defaults to same as TAS(), but we can override it when we know there's a better way. It's likely that some of the other cases in s_lock.h require similar treatment, but this is the only one we've got conclusive evidence for at present.
This commit is contained in:
parent
6e1f1fee97
commit
c01c25fbe5
@ -96,7 +96,7 @@ s_lock(volatile slock_t *lock, const char *file, int line)
|
|||||||
int delays = 0;
|
int delays = 0;
|
||||||
int cur_delay = 0;
|
int cur_delay = 0;
|
||||||
|
|
||||||
while (TAS(lock))
|
while (TAS_SPIN(lock))
|
||||||
{
|
{
|
||||||
/* CPU-specific delay each time through the loop */
|
/* CPU-specific delay each time through the loop */
|
||||||
SPIN_DELAY();
|
SPIN_DELAY();
|
||||||
|
@ -31,25 +31,33 @@
|
|||||||
* macros at the bottom of the file. Check if your platform can use
|
* macros at the bottom of the file. Check if your platform can use
|
||||||
* these or needs to override them.
|
* these or needs to override them.
|
||||||
*
|
*
|
||||||
* Usually, S_LOCK() is implemented in terms of an even lower-level macro
|
* Usually, S_LOCK() is implemented in terms of even lower-level macros
|
||||||
* TAS():
|
* TAS() and TAS_SPIN():
|
||||||
*
|
*
|
||||||
* int TAS(slock_t *lock)
|
* int TAS(slock_t *lock)
|
||||||
* Atomic test-and-set instruction. Attempt to acquire the lock,
|
* Atomic test-and-set instruction. Attempt to acquire the lock,
|
||||||
* but do *not* wait. Returns 0 if successful, nonzero if unable
|
* but do *not* wait. Returns 0 if successful, nonzero if unable
|
||||||
* to acquire the lock.
|
* to acquire the lock.
|
||||||
*
|
*
|
||||||
* TAS() is NOT part of the API, and should never be called directly.
|
* int TAS_SPIN(slock_t *lock)
|
||||||
|
* Like TAS(), but this version is used when waiting for a lock
|
||||||
|
* previously found to be contended. Typically, this is the
|
||||||
|
* same as TAS(), but on some architectures it's better to poll a
|
||||||
|
* contended lock using an unlocked instruction and retry the
|
||||||
|
* atomic test-and-set only when it appears free.
|
||||||
*
|
*
|
||||||
* CAUTION: on some platforms TAS() may sometimes report failure to acquire
|
* TAS() and TAS_SPIN() are NOT part of the API, and should never be called
|
||||||
* a lock even when the lock is not locked. For example, on Alpha TAS()
|
* directly.
|
||||||
* will "fail" if interrupted. Therefore TAS() should always be invoked
|
|
||||||
* in a retry loop, even if you are certain the lock is free.
|
|
||||||
*
|
*
|
||||||
* ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
|
* CAUTION: on some platforms TAS() and/or TAS_SPIN() may sometimes report
|
||||||
* points, ie, loads and stores of other values must not be moved across
|
* failure to acquire a lock even when the lock is not locked. For example,
|
||||||
* a lock or unlock. In most cases it suffices to make the operation be
|
* on Alpha TAS() will "fail" if interrupted. Therefore a retry loop must
|
||||||
* done through a "volatile" pointer.
|
* always be used, even if you are certain the lock is free.
|
||||||
|
*
|
||||||
|
* ANOTHER CAUTION: be sure that TAS(), TAS_SPIN(), and S_UNLOCK() represent
|
||||||
|
* sequence points, ie, loads and stores of other values must not be moved
|
||||||
|
* across a lock or unlock. In most cases it suffices to make the operation
|
||||||
|
* be done through a "volatile" pointer.
|
||||||
*
|
*
|
||||||
* On most supported platforms, TAS() uses a tas() function written
|
* On most supported platforms, TAS() uses a tas() function written
|
||||||
* in assembly language to execute a hardware atomic-test-and-set
|
* in assembly language to execute a hardware atomic-test-and-set
|
||||||
@ -727,6 +735,7 @@ typedef unsigned int slock_t;
|
|||||||
|
|
||||||
#include <ia64/sys/inline.h>
|
#include <ia64/sys/inline.h>
|
||||||
#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
|
#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
|
||||||
|
#define TAS_SPIN(lock) (*(lock) ? 1 : TAS(lock))
|
||||||
|
|
||||||
#endif /* HPUX on IA64, non gcc */
|
#endif /* HPUX on IA64, non gcc */
|
||||||
|
|
||||||
@ -925,6 +934,10 @@ extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
|
|||||||
#define TAS(lock) tas(lock)
|
#define TAS(lock) tas(lock)
|
||||||
#endif /* TAS */
|
#endif /* TAS */
|
||||||
|
|
||||||
|
#if !defined(TAS_SPIN)
|
||||||
|
#define TAS_SPIN(lock) TAS(lock)
|
||||||
|
#endif /* TAS_SPIN */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platform-independent out-of-line support routines
|
* Platform-independent out-of-line support routines
|
||||||
|
Loading…
x
Reference in New Issue
Block a user