postgres.git / summary / log / commit / refs

commit    40dde829070ddebd3f8bbf06d8e1cc4bff2e0c06
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Sun Jun 23 00:31:50 2019 +0000
First released in: 12.0, 9.4.24, 9.5.19, 9.6.15, 10.10, 11.5

    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 3cbe6b247), 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


src/include/storage/s_lock.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/include/storage/s_lock.h b/src/include/storage/s_lock.h index 04175dbaaa4..7ec32c1e6fb 100644 --- a/src/include/storage/s_lock.h +++ b/src/include/storage/s_lock.h @@ -598,14 +598,31 @@ tas(volatile slock_t *lock) #if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */ -/* Note: on SGI we use the OS' mutex ABI, see below */ -/* 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) { @@ -615,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" @@ -637,7 +654,7 @@ do \ { \ __asm__ __volatile__( \ " .set push \n" \ - " .set mips2 \n" \ + MIPS_SET_MIPS2 \ " .set noreorder \n" \ " .set nomacro \n" \ " sync \n" \ [parent: a40dca815dd1]