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.
This commit is contained in:
Tom Lane 2012-01-02 00:01:33 -05:00
parent 8496c6cd77
commit 631beeac35
2 changed files with 29 additions and 1 deletions

View File

@ -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

View 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 */