8344010: RISC-V: Zacas do not work with LW locking

Reviewed-by: fyang, mli
This commit is contained in:
Robbin Ehn 2024-11-20 12:05:53 +00:00
parent e2f8f1aded
commit ea7e722ca0
2 changed files with 25 additions and 87 deletions

View File

@ -3466,6 +3466,17 @@ void MacroAssembler::cmpxchg(Register addr, Register expected,
assert_different_registers(expected, t0);
assert_different_registers(new_val, t0);
// NOTE:
// Register _result_ may be the same register as _new_val_ or _expected_.
// Hence do NOT use _result_ until after 'cas'.
//
// Register _expected_ may be the same register as _new_val_ and is assumed to be preserved.
// Hence do NOT change _expected_ or _new_val_.
//
// Having _expected_ and _new_val_ being the same register is a very puzzling cas.
//
// TODO: Address these issues.
if (UseZacas) {
if (result_as_bool) {
mv(t0, expected);
@ -3473,8 +3484,9 @@ void MacroAssembler::cmpxchg(Register addr, Register expected,
xorr(t0, t0, expected);
seqz(result, t0);
} else {
mv(result, expected);
atomic_cas(result, new_val, addr, size, acquire, release);
mv(t0, expected);
atomic_cas(t0, new_val, addr, size, acquire, release);
mv(result, t0);
}
return;
}
@ -3510,15 +3522,16 @@ void MacroAssembler::cmpxchg_weak(Register addr, Register expected,
enum operand_size size,
Assembler::Aqrl acquire, Assembler::Aqrl release,
Register result) {
if (UseZacas) {
cmpxchg(addr, expected, new_val, size, acquire, release, result, true);
return;
}
assert_different_registers(addr, t0);
assert_different_registers(expected, t0);
assert_different_registers(new_val, t0);
if (UseZacas) {
cmpxchg(addr, expected, new_val, size, acquire, release, result, true);
return;
}
Label fail, done;
load_reserved(t0, addr, size, acquire);
bne(t0, expected, fail);
@ -3581,83 +3594,18 @@ ATOMIC_XCHGU(xchgalwu, xchgalw)
#undef ATOMIC_XCHGU
#define ATOMIC_CAS(OP, AOP, ACQUIRE, RELEASE) \
void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { \
assert(UseZacas, "invariant"); \
prev = prev->is_valid() ? prev : zr; \
AOP(prev, addr, newv, (Assembler::Aqrl)(ACQUIRE | RELEASE)); \
return; \
}
ATOMIC_CAS(cas, amocas_d, Assembler::relaxed, Assembler::relaxed)
ATOMIC_CAS(casw, amocas_w, Assembler::relaxed, Assembler::relaxed)
ATOMIC_CAS(casl, amocas_d, Assembler::relaxed, Assembler::rl)
ATOMIC_CAS(caslw, amocas_w, Assembler::relaxed, Assembler::rl)
ATOMIC_CAS(casal, amocas_d, Assembler::aq, Assembler::rl)
ATOMIC_CAS(casalw, amocas_w, Assembler::aq, Assembler::rl)
#undef ATOMIC_CAS
#define ATOMIC_CASU(OP1, OP2) \
void MacroAssembler::atomic_##OP1(Register prev, Register newv, Register addr) { \
atomic_##OP2(prev, newv, addr); \
zero_extend(prev, prev, 32); \
return; \
}
ATOMIC_CASU(caswu, casw)
ATOMIC_CASU(caslwu, caslw)
ATOMIC_CASU(casalwu, casalw)
#undef ATOMIC_CASU
void MacroAssembler::atomic_cas(
Register prev, Register newv, Register addr, enum operand_size size, Assembler::Aqrl acquire, Assembler::Aqrl release) {
void MacroAssembler::atomic_cas(Register prev, Register newv, Register addr,
enum operand_size size, Assembler::Aqrl acquire, Assembler::Aqrl release) {
switch (size) {
case int64:
switch ((Assembler::Aqrl)(acquire | release)) {
case Assembler::relaxed:
atomic_cas(prev, newv, addr);
break;
case Assembler::rl:
atomic_casl(prev, newv, addr);
break;
case Assembler::aqrl:
atomic_casal(prev, newv, addr);
break;
default:
ShouldNotReachHere();
}
amocas_d(prev, addr, newv, (Assembler::Aqrl)(acquire | release));
break;
case int32:
switch ((Assembler::Aqrl)(acquire | release)) {
case Assembler::relaxed:
atomic_casw(prev, newv, addr);
break;
case Assembler::rl:
atomic_caslw(prev, newv, addr);
break;
case Assembler::aqrl:
atomic_casalw(prev, newv, addr);
break;
default:
ShouldNotReachHere();
}
amocas_w(prev, addr, newv, (Assembler::Aqrl)(acquire | release));
break;
case uint32:
switch ((Assembler::Aqrl)(acquire | release)) {
case Assembler::relaxed:
atomic_caswu(prev, newv, addr);
break;
case Assembler::rl:
atomic_caslwu(prev, newv, addr);
break;
case Assembler::aqrl:
atomic_casalwu(prev, newv, addr);
break;
default:
ShouldNotReachHere();
}
amocas_w(prev, addr, newv, (Assembler::Aqrl)(acquire | release));
zero_extend(prev, prev, 32);
break;
default:
ShouldNotReachHere();

View File

@ -1175,16 +1175,6 @@ public:
void atomic_xchgwu(Register prev, Register newv, Register addr);
void atomic_xchgalwu(Register prev, Register newv, Register addr);
void atomic_cas(Register prev, Register newv, Register addr);
void atomic_casw(Register prev, Register newv, Register addr);
void atomic_casl(Register prev, Register newv, Register addr);
void atomic_caslw(Register prev, Register newv, Register addr);
void atomic_casal(Register prev, Register newv, Register addr);
void atomic_casalw(Register prev, Register newv, Register addr);
void atomic_caswu(Register prev, Register newv, Register addr);
void atomic_caslwu(Register prev, Register newv, Register addr);
void atomic_casalwu(Register prev, Register newv, Register addr);
void atomic_cas(Register prev, Register newv, Register addr, enum operand_size size,
Assembler::Aqrl acquire = Assembler::relaxed, Assembler::Aqrl release = Assembler::relaxed);