aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-12-27 20:58:58 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-12-27 20:58:58 +0000
commitf8eed65dfb580f0971e2e6ead83135bfa3ddeb06 (patch)
tree5fd8b3b152cfa785e14a4489b628081a67dcf2d9 /src
parent2cdace962b5fd56a4bd2fae1c1ba6e99434f33f3 (diff)
downloadpostgresql-f8eed65dfb580f0971e2e6ead83135bfa3ddeb06.tar.gz
postgresql-f8eed65dfb580f0971e2e6ead83135bfa3ddeb06.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/lmgr/s_lock.c6
-rw-r--r--src/include/storage/s_lock.h23
2 files changed, 27 insertions, 2 deletions
diff --git a/src/backend/storage/lmgr/s_lock.c b/src/backend/storage/lmgr/s_lock.c
index e5e372bb39d..fac77aef0af 100644
--- a/src/backend/storage/lmgr/s_lock.c
+++ b/src/backend/storage/lmgr/s_lock.c
@@ -9,7 +9,7 @@
*
*
* 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))
{
+ /* CPU-specific delay each time through the loop */
+ SPIN_DELAY();
+
+ /* Block the process every SPINS_PER_DELAY tries */
if (++spins > SPINS_PER_DELAY)
{
if (++delays > NUM_DELAYS)
diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h
index e1851fb9cec..9ab24f93ae7 100644
--- a/src/include/storage/s_lock.h
+++ b/src/include/storage/s_lock.h
@@ -24,6 +24,9 @@
* Tests if the lock is free. Returns TRUE if free, FALSE if locked.
* 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
* macros at the bottom of the file. Check if your platform can use
* these or needs to override them.
@@ -63,7 +66,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* 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;
+ /* Use a non-locking test before asserting the bus lock */
__asm__ __volatile__(
+ " cmpb $0,%1 \n"
+ " jne 1f \n"
" lock \n"
" xchgb %0,%1 \n"
+ "1: \n"
: "=q"(_res), "=m"(*lock)
: "0"(_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__ */
@@ -708,6 +725,10 @@ extern int tas_sema(volatile slock_t *lock);
#define S_INIT_LOCK(lock) S_UNLOCK(lock)
#endif /* S_INIT_LOCK */
+#if !defined(SPIN_DELAY)
+#define SPIN_DELAY() ((void) 0)
+#endif /* SPIN_DELAY */
+
#if !defined(TAS)
extern int tas(volatile slock_t *lock); /* in port/.../tas.s, or
* s_lock.c */