]> granicus.if.org Git - postgresql/commitdiff
Use LWSYNC in place of SYNC/ISYNC in PPC spinlocks, where possible.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 2 Jan 2012 05:01:33 +0000 (00:01 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 2 Jan 2012 05:02:02 +0000 (00:02 -0500)
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
src/include/storage/s_lock.h

index 810be27e813f4790bf26410d0400f1110264d753..ac45ee6426eb32e3dd893f7e3e82d2b98dc9fc03 100644 (file)
 #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
index 2e5163eabf071fbb451a9c62bf6147bc25023e8a..ff7eb1418e63b19b3396485b4725e1fc06ca8441 100644 (file)
@@ -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 */