Skip to content

8350285: Shenandoah: Regression caused by ShenandoahLock under extreme contention #3614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/hotspot/share/gc/shenandoah/shenandoahLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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) {
Expand All @@ -68,17 +69,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!");
}
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/gc/shenandoah/shenandoahLock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class ShenandoahLock {

template<bool ALLOW_BLOCK>
void contended_lock_internal(JavaThread* java_thread);
static void yield_or_sleep(int &yields);

public:
ShenandoahLock() : _state(unlocked), _owner(NULL) {};

Expand Down