mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-23 19:39:53 +08:00
Improve spinlock code for recent x86 processors: insert a PAUSE
instruction in the s_lock() wait loop, and use test before test-and-set in TAS() macro to avoid unnecessary bus traffic. Patch from Manfred Spraul, reworked a bit by Tom.
This commit is contained in:
parent
2cdace962b
commit
f8eed65dfb
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.22 2003/12/23 22:15:07 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.23 2003/12/27 20:58:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -88,6 +88,10 @@ s_lock(volatile slock_t *lock, const char *file, int line)
|
|||||||
|
|
||||||
while (TAS(lock))
|
while (TAS(lock))
|
||||||
{
|
{
|
||||||
|
/* CPU-specific delay each time through the loop */
|
||||||
|
SPIN_DELAY();
|
||||||
|
|
||||||
|
/* Block the process every SPINS_PER_DELAY tries */
|
||||||
if (++spins > SPINS_PER_DELAY)
|
if (++spins > SPINS_PER_DELAY)
|
||||||
{
|
{
|
||||||
if (++delays > NUM_DELAYS)
|
if (++delays > NUM_DELAYS)
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
* Tests if the lock is free. Returns TRUE if free, FALSE if locked.
|
* Tests if the lock is free. Returns TRUE if free, FALSE if locked.
|
||||||
* This does *not* change the state of the lock.
|
* This does *not* change the state of the lock.
|
||||||
*
|
*
|
||||||
|
* void SPIN_DELAY(void)
|
||||||
|
* Delay operation to occur inside spinlock wait loop.
|
||||||
|
*
|
||||||
* Note to implementors: there are default implementations for all these
|
* Note to implementors: there are default implementations for all these
|
||||||
* 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.
|
||||||
@ -63,7 +66,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.123 2003/12/23 22:15:07 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.124 2003/12/27 20:58:58 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -107,14 +110,28 @@ tas(volatile slock_t *lock)
|
|||||||
{
|
{
|
||||||
register slock_t _res = 1;
|
register slock_t _res = 1;
|
||||||
|
|
||||||
|
/* Use a non-locking test before asserting the bus lock */
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
" cmpb $0,%1 \n"
|
||||||
|
" jne 1f \n"
|
||||||
" lock \n"
|
" lock \n"
|
||||||
" xchgb %0,%1 \n"
|
" xchgb %0,%1 \n"
|
||||||
|
"1: \n"
|
||||||
: "=q"(_res), "=m"(*lock)
|
: "=q"(_res), "=m"(*lock)
|
||||||
: "0"(_res));
|
: "0"(_res));
|
||||||
return (int) _res;
|
return (int) _res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SPIN_DELAY() spin_delay()
|
||||||
|
|
||||||
|
static __inline__ void
|
||||||
|
spin_delay(void)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" rep; nop \n"
|
||||||
|
: : : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __i386__ || __x86_64__ */
|
#endif /* __i386__ || __x86_64__ */
|
||||||
|
|
||||||
|
|
||||||
@ -708,6 +725,10 @@ extern int tas_sema(volatile slock_t *lock);
|
|||||||
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
|
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
|
||||||
#endif /* S_INIT_LOCK */
|
#endif /* S_INIT_LOCK */
|
||||||
|
|
||||||
|
#if !defined(SPIN_DELAY)
|
||||||
|
#define SPIN_DELAY() ((void) 0)
|
||||||
|
#endif /* SPIN_DELAY */
|
||||||
|
|
||||||
#if !defined(TAS)
|
#if !defined(TAS)
|
||||||
extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
|
extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
|
||||||
* s_lock.c */
|
* s_lock.c */
|
||||||
|
Loading…
Reference in New Issue
Block a user