8350285: Shenandoah: Regression caused by ShenandoahLock under extreme contention

Reviewed-by: shade, kdnilsen
This commit is contained in:
Xiaolong Peng 2025-02-21 16:39:17 +00:00 committed by Aleksey Shipilev
parent 24b557361a
commit bd8ad309b5
2 changed files with 18 additions and 3 deletions

View File

@ -45,6 +45,7 @@ void ShenandoahLock::contended_lock_internal(JavaThread* java_thread) {
assert(!ALLOW_BLOCK || java_thread != nullptr, "Must have a Java thread when allowing block.");
// Spin this much, but only on multi-processor systems.
int ctr = os::is_MP() ? 0xFF : 0;
int yields = 0;
// Apply TTAS to avoid more expensive CAS calls if the lock is still held by other thread.
while (Atomic::load(&_state) == locked ||
Atomic::cmpxchg(&_state, unlocked, locked) != unlocked) {
@ -67,17 +68,29 @@ void ShenandoahLock::contended_lock_internal(JavaThread* java_thread) {
// VM thread to arm the poll sooner.
while (SafepointSynchronize::is_synchronizing() &&
!SafepointMechanism::local_poll_armed(java_thread)) {
os::naked_yield();
yield_or_sleep(yields);
}
} else {
os::naked_yield();
yield_or_sleep(yields);
}
} else {
os::naked_yield();
yield_or_sleep(yields);
}
}
}
void ShenandoahLock::yield_or_sleep(int &yields) {
// Simple yield-sleep policy: do one 100us sleep after every N yields.
// Tested with different values of N, and chose 3 for best performance.
if (yields < 3) {
os::naked_yield();
yields++;
} else {
os::naked_short_nanosleep(100000);
yields = 0;
}
}
ShenandoahSimpleLock::ShenandoahSimpleLock() {
assert(os::mutex_init_done(), "Too early!");
}

View File

@ -42,6 +42,8 @@ private:
template<bool ALLOW_BLOCK>
void contended_lock_internal(JavaThread* java_thread);
static void yield_or_sleep(int &yields);
public:
ShenandoahLock() : _state(unlocked), _owner(nullptr) {};