mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
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
This commit is contained in:
parent
6121ba9d18
commit
05399b1488
@ -598,14 +598,31 @@ tas(volatile slock_t *lock)
|
|||||||
|
|
||||||
|
|
||||||
#if defined(__mips__) && !defined(__sgi) /* non-SGI MIPS */
|
#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
|
#define HAS_TEST_AND_SET
|
||||||
|
|
||||||
typedef unsigned int slock_t;
|
typedef unsigned int slock_t;
|
||||||
|
|
||||||
#define TAS(lock) tas(lock)
|
#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
|
static __inline__ int
|
||||||
tas(volatile slock_t *lock)
|
tas(volatile slock_t *lock)
|
||||||
{
|
{
|
||||||
@ -615,7 +632,7 @@ tas(volatile slock_t *lock)
|
|||||||
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
" .set push \n"
|
" .set push \n"
|
||||||
" .set mips2 \n"
|
MIPS_SET_MIPS2
|
||||||
" .set noreorder \n"
|
" .set noreorder \n"
|
||||||
" .set nomacro \n"
|
" .set nomacro \n"
|
||||||
" ll %0, %2 \n"
|
" ll %0, %2 \n"
|
||||||
@ -637,7 +654,7 @@ do \
|
|||||||
{ \
|
{ \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
" .set push \n" \
|
" .set push \n" \
|
||||||
" .set mips2 \n" \
|
MIPS_SET_MIPS2 \
|
||||||
" .set noreorder \n" \
|
" .set noreorder \n" \
|
||||||
" .set nomacro \n" \
|
" .set nomacro \n" \
|
||||||
" sync \n" \
|
" sync \n" \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user