From 631beeac3598a73dee2c2afa38fa2e734148031b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 2 Jan 2012 00:01:33 -0500 Subject: [PATCH] Use LWSYNC in place of SYNC/ISYNC in PPC spinlocks, where possible. This is allegedly a win, at least on some PPC implementations, according to the PPC ISA documents. However, as with LWARX hints, some PPC platforms give an illegal-instruction failure. Use the same trick as before of assuming that PPC64 platforms will accept it; we might need to refine that based on experience, but there are other projects doing likewise according to google. I did not add an assembler compatibility test because LWSYNC has been around much longer than hint bits, and it seems unlikely that any toolchains currently in use don't recognize it. --- src/include/pg_config_manual.h | 11 +++++++++++ src/include/storage/s_lock.h | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/include/pg_config_manual.h b/src/include/pg_config_manual.h index 810be27e81..ac45ee6426 100644 --- a/src/include/pg_config_manual.h +++ b/src/include/pg_config_manual.h @@ -188,6 +188,17 @@ #endif #endif +/* + * On PPC machines, decide whether to use LWSYNC instructions in place of + * ISYNC and SYNC. This provides slightly better performance, but will + * result in illegal-instruction failures on some pre-POWER4 machines. + * By default we use LWSYNC when building for 64-bit PPC, which should be + * safe in nearly all cases. + */ +#if defined(__ppc64__) || defined(__powerpc64__) +#define USE_PPC_LWSYNC +#endif + /* *------------------------------------------------------------------------ * The following symbols are for enabling debugging code, not for diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 2e5163eabf..ff7eb1418e 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -361,6 +361,7 @@ typedef unsigned int slock_t; /* * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002, * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop. + * On newer machines, we can use lwsync instead for better performance. */ static __inline__ int tas(volatile slock_t *lock) @@ -382,7 +383,11 @@ tas(volatile slock_t *lock) "1: li %1,1 \n" " b 3f \n" "2: \n" +#ifdef USE_PPC_LWSYNC +" lwsync \n" +#else " isync \n" +#endif " li %1,0 \n" "3: \n" @@ -392,13 +397,25 @@ tas(volatile slock_t *lock) return _res; } -/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */ +/* + * PowerPC S_UNLOCK is almost standard but requires a "sync" instruction. + * On newer machines, we can use lwsync instead for better performance. + */ +#ifdef USE_PPC_LWSYNC +#define S_UNLOCK(lock) \ +do \ +{ \ + __asm__ __volatile__ (" lwsync \n"); \ + *((volatile slock_t *) (lock)) = 0; \ +} while (0) +#else #define S_UNLOCK(lock) \ do \ { \ __asm__ __volatile__ (" sync \n"); \ *((volatile slock_t *) (lock)) = 0; \ } while (0) +#endif /* USE_PPC_LWSYNC */ #endif /* powerpc */