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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy