Commit 1323bfce authored by Tom Lane's avatar Tom Lane

Fix spinlock assembly code for MIPS so it works on MIPS r6.

Original MIPS-I processors didn't have the LL/SC instructions (nor any
other userland synchronization primitive).  If the build toolchain
targets that ISA variant by default, as an astonishingly large fraction
of MIPS platforms still do, the assembler won't take LL/SC without
coercion in the form of a ".set mips2" instruction.  But we issued that
unconditionally, making it an ISA downgrade for chips later than MIPS2.
That breaks things for the latest MIPS r6 ISA, which encodes these
instructions differently.  Adjust the code so we don't change ISA level
if it's >= 2.

Note that this patch doesn't change what happens on an actual MIPS-I
processor: either the kernel will emulate these instructions
transparently, or you'll get a SIGILL failure.  That tradeoff seemed
fine in 2002 when this code was added (cf 3cbe6b24), and it's even
more so today when MIPS-I is basically extinct.  But let's add a
comment about that.

YunQiang Su (with cosmetic adjustments by me).  Back-patch to all
supported branches.

Discussion: https://postgr.es/m/15844-8f62fe7e163939b3@postgresql.org
parent 660a2b19
......@@ -598,13 +598,31 @@ tas(volatile slock_t *lock)
#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
/* Note: R10000 processors require a separate SYNC */
#define HAS_TEST_AND_SET
typedef unsigned int slock_t;
#define TAS(lock) tas(lock)
/*
* Original MIPS-I processors lacked the LL/SC instructions, but if we are
* so unfortunate as to be running on one of those, we expect that the kernel
* will handle the illegal-instruction traps and emulate them for us. On
* anything newer (and really, MIPS-I is extinct) LL/SC is the only sane
* choice because any other synchronization method must involve a kernel
* call. Unfortunately, many toolchains still default to MIPS-I as the
* codegen target; if the symbol __mips shows that that's the case, we
* have to force the assembler to accept LL/SC.
*
* R10000 and up processors require a separate SYNC, which has the same
* issues as LL/SC.
*/
#if __mips < 2
#define MIPS_SET_MIPS2 " .set mips2 \n"
#else
#define MIPS_SET_MIPS2
#endif
static __inline__ int
tas(volatile slock_t *lock)
{
......@@ -614,7 +632,7 @@ tas(volatile slock_t *lock)
__asm__ __volatile__(
" .set push \n"
" .set mips2 \n"
MIPS_SET_MIPS2
" .set noreorder \n"
" .set nomacro \n"
" ll %0, %2 \n"
......@@ -636,7 +654,7 @@ do \
{ \
__asm__ __volatile__( \
" .set push \n" \
" .set mips2 \n" \
MIPS_SET_MIPS2 \
" .set noreorder \n" \
" .set nomacro \n" \
" sync \n" \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment