Skip to content

Commit 1323bfc

Browse files
committed
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 3cbe6b2), 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/[email protected]
1 parent 660a2b1 commit 1323bfc

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/include/storage/s_lock.h

+21-3
Original file line numberDiff line numberDiff line change
@@ -598,13 +598,31 @@ tas(volatile slock_t *lock)
598598

599599

600600
#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
601-
/* Note: R10000 processors require a separate SYNC */
602601
#define HAS_TEST_AND_SET
603602

604603
typedef unsigned int slock_t;
605604

606605
#define TAS(lock) tas(lock)
607606

607+
/*
608+
* Original MIPS-I processors lacked the LL/SC instructions, but if we are
609+
* so unfortunate as to be running on one of those, we expect that the kernel
610+
* will handle the illegal-instruction traps and emulate them for us. On
611+
* anything newer (and really, MIPS-I is extinct) LL/SC is the only sane
612+
* choice because any other synchronization method must involve a kernel
613+
* call. Unfortunately, many toolchains still default to MIPS-I as the
614+
* codegen target; if the symbol __mips shows that that's the case, we
615+
* have to force the assembler to accept LL/SC.
616+
*
617+
* R10000 and up processors require a separate SYNC, which has the same
618+
* issues as LL/SC.
619+
*/
620+
#if __mips < 2
621+
#define MIPS_SET_MIPS2 " .set mips2 \n"
622+
#else
623+
#define MIPS_SET_MIPS2
624+
#endif
625+
608626
static __inline__ int
609627
tas(volatile slock_t *lock)
610628
{
@@ -614,7 +632,7 @@ tas(volatile slock_t *lock)
614632

615633
__asm__ __volatile__(
616634
" .set push \n"
617-
" .set mips2 \n"
635+
MIPS_SET_MIPS2
618636
" .set noreorder \n"
619637
" .set nomacro \n"
620638
" ll %0, %2 \n"
@@ -636,7 +654,7 @@ do \
636654
{ \
637655
__asm__ __volatile__( \
638656
" .set push \n" \
639-
" .set mips2 \n" \
657+
MIPS_SET_MIPS2 \
640658
" .set noreorder \n" \
641659
" .set nomacro \n" \
642660
" sync \n" \

0 commit comments

Comments
 (0)