From 631beeac3598a73dee2c2afa38fa2e734148031b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
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 810be27e813..ac45ee6426e 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 2e5163eabf0..ff7eb1418e6 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 */
 
-- 
GitLab