Workaround R10K ll/sc errata.

This commit is contained in:
Matt Turner 2011-08-02 15:18:06 +00:00 committed by Joseph Myers
parent 9dc88b5c93
commit e349dfdb68
2 changed files with 36 additions and 6 deletions

View File

@ -1,3 +1,7 @@
2011-08-02 Matt Turner <mattst88@gmail.com>
* sysdeps/mips/bits/atomic.h: Workaround R10K ll/sc errata.
2011-07-25 Joseph Myers <joseph@codesourcery.com>
* sysdeps/unix/sysv/linux/mips/bits/socket.h (PF_NFC, AF_NFC):

View File

@ -49,6 +49,32 @@ typedef uintmax_t uatomic_max_t;
# define MIPS_SYNC sync
#endif
/* Certain revisions of the R10000 Processor need an LL/SC Workaround
enabled. Revisions before 3.0 misbehave on atomic operations, and
Revs 2.6 and lower deadlock after several seconds due to other errata.
To quote the R10K Errata:
Workaround: The basic idea is to inhibit the four instructions
from simultaneously becoming active in R10000. Padding all
ll/sc sequences with nops or changing the looping branch in the
routines to a branch likely (which is always predicted taken
by R10000) will work. The nops should go after the loop, and the
number of them should be 28. This number could be decremented for
each additional instruction in the ll/sc loop such as the lock
modifier(s) between the ll and sc, the looping branch and its
delay slot. For typical short routines with one ll/sc loop, any
instructions after the loop could also count as a decrement. The
nop workaround pollutes the cache more but would be a few cycles
faster if all the code is in the cache and the looping branch
is predicted not taken. */
#ifdef _MIPS_ARCH_R10000
#define R10K_BEQZ_INSN "beqzl"
#else
#define R10K_BEQZ_INSN "beqz"
#endif
#define MIPS_SYNC_STR_2(X) #X
#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X)
#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC)
@ -74,7 +100,7 @@ typedef uintmax_t uatomic_max_t;
"bne %0,%3,2f\n\t" \
"move %1,%4\n\t" \
"sc %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \
@ -98,7 +124,7 @@ typedef uintmax_t uatomic_max_t;
"bne %0,%3,2f\n\t" \
"move %1,%4\n\t" \
"scd %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \
@ -192,7 +218,7 @@ typedef uintmax_t uatomic_max_t;
"ll %0,%4\n\t" \
"move %1,%3\n\t" \
"sc %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \
@ -216,7 +242,7 @@ typedef uintmax_t uatomic_max_t;
"lld %0,%4\n\t" \
"move %1,%3\n\t" \
"scd %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \
@ -251,7 +277,7 @@ typedef uintmax_t uatomic_max_t;
"ll %0,%4\n\t" \
"addu %1,%0,%3\n\t" \
"sc %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \
@ -275,7 +301,7 @@ typedef uintmax_t uatomic_max_t;
"lld %0,%4\n\t" \
"daddu %1,%0,%3\n\t" \
"scd %1,%2\n\t" \
"beqz %1,1b\n" \
R10K_BEQZ_INSN" %1,1b\n" \
acq "\n\t" \
".set pop\n" \
"2:\n\t" \