Skip to content

Commit f8eed65

Browse files
committed
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.
1 parent 2cdace9 commit f8eed65

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/backend/storage/lmgr/s_lock.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.22 2003/12/23 22:15:07 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.23 2003/12/27 20:58:58 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -88,6 +88,10 @@ s_lock(volatile slock_t *lock, const char *file, int line)
8888

8989
while (TAS(lock))
9090
{
91+
/* CPU-specific delay each time through the loop */
92+
SPIN_DELAY();
93+
94+
/* Block the process every SPINS_PER_DELAY tries */
9195
if (++spins > SPINS_PER_DELAY)
9296
{
9397
if (++delays > NUM_DELAYS)

src/include/storage/s_lock.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
* Tests if the lock is free. Returns TRUE if free, FALSE if locked.
2525
* This does *not* change the state of the lock.
2626
*
27+
* void SPIN_DELAY(void)
28+
* Delay operation to occur inside spinlock wait loop.
29+
*
2730
* Note to implementors: there are default implementations for all these
2831
* macros at the bottom of the file. Check if your platform can use
2932
* these or needs to override them.
@@ -63,7 +66,7 @@
6366
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
6467
* Portions Copyright (c) 1994, Regents of the University of California
6568
*
66-
* $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.123 2003/12/23 22:15:07 tgl Exp $
69+
* $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.124 2003/12/27 20:58:58 tgl Exp $
6770
*
6871
*-------------------------------------------------------------------------
6972
*/
@@ -107,14 +110,28 @@ tas(volatile slock_t *lock)
107110
{
108111
register slock_t _res = 1;
109112

113+
/* Use a non-locking test before asserting the bus lock */
110114
__asm__ __volatile__(
115+
" cmpb $0,%1 \n"
116+
" jne 1f \n"
111117
" lock \n"
112118
" xchgb %0,%1 \n"
119+
"1: \n"
113120
: "=q"(_res), "=m"(*lock)
114121
: "0"(_res));
115122
return (int) _res;
116123
}
117124

125+
#define SPIN_DELAY() spin_delay()
126+
127+
static __inline__ void
128+
spin_delay(void)
129+
{
130+
__asm__ __volatile__(
131+
" rep; nop \n"
132+
: : : "memory");
133+
}
134+
118135
#endif /* __i386__ || __x86_64__ */
119136

120137

@@ -708,6 +725,10 @@ extern int tas_sema(volatile slock_t *lock);
708725
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
709726
#endif /* S_INIT_LOCK */
710727

728+
#if !defined(SPIN_DELAY)
729+
#define SPIN_DELAY() ((void) 0)
730+
#endif /* SPIN_DELAY */
731+
711732
#if !defined(TAS)
712733
extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
713734
* s_lock.c */

0 commit comments

Comments
 (0)