Skip to content

Commit 2854e2a

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/15844-8f62fe7e163939b3@postgresql.org
1 parent a01e72f commit 2854e2a

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/include/storage/s_lock.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,14 +671,31 @@ do \
671671

672672

673673
#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
674-
/* Note: on SGI we use the OS' mutex ABI, see below */
675-
/* Note: R10000 processors require a separate SYNC */
676674
#define HAS_TEST_AND_SET
677675

678676
typedef unsigned int slock_t;
679677

680678
#define TAS(lock) tas(lock)
681679

680+
/*
681+
* Original MIPS-I processors lacked the LL/SC instructions, but if we are
682+
* so unfortunate as to be running on one of those, we expect that the kernel
683+
* will handle the illegal-instruction traps and emulate them for us. On
684+
* anything newer (and really, MIPS-I is extinct) LL/SC is the only sane
685+
* choice because any other synchronization method must involve a kernel
686+
* call. Unfortunately, many toolchains still default to MIPS-I as the
687+
* codegen target; if the symbol __mips shows that that's the case, we
688+
* have to force the assembler to accept LL/SC.
689+
*
690+
* R10000 and up processors require a separate SYNC, which has the same
691+
* issues as LL/SC.
692+
*/
693+
#if __mips < 2
694+
#define MIPS_SET_MIPS2 " .set mips2 \n"
695+
#else
696+
#define MIPS_SET_MIPS2
697+
#endif
698+
682699
static __inline__ int
683700
tas(volatile slock_t *lock)
684701
{
@@ -688,7 +705,7 @@ tas(volatile slock_t *lock)
688705

689706
__asm__ __volatile__(
690707
" .set push \n"
691-
" .set mips2 \n"
708+
MIPS_SET_MIPS2
692709
" .set noreorder \n"
693710
" .set nomacro \n"
694711
" ll %0, %2 \n"
@@ -710,7 +727,7 @@ do \
710727
{ \
711728
__asm__ __volatile__( \
712729
" .set push \n" \
713-
" .set mips2 \n" \
730+
MIPS_SET_MIPS2 \
714731
" .set noreorder \n" \
715732
" .set nomacro \n" \
716733
" sync \n" \

0 commit comments

Comments
 (0)