8220795: Rework naked_short_nanosleep on Windows to improve time-to-safepoint
Reviewed-by: dholmes, rehn
This commit is contained in:
parent
2998236d83
commit
37281369f0
src/hotspot
@ -3558,41 +3558,19 @@ void os::naked_short_sleep(jlong ms) {
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
// Windows does not provide sleep functionality with nanosecond resolution, so we
|
||||
// try to approximate this with spinning combined with yielding if another thread
|
||||
// is ready to run on the current processor.
|
||||
void os::naked_short_nanosleep(jlong ns) {
|
||||
assert(ns > -1 && ns < NANOUNITS, "Un-interruptable sleep, short time use only");
|
||||
LARGE_INTEGER hundreds_nanos = { 0 };
|
||||
HANDLE wait_timer = ::CreateWaitableTimer(NULL /* attributes*/,
|
||||
true /* manual reset */,
|
||||
NULL /* name */ );
|
||||
if (wait_timer == NULL) {
|
||||
log_warning(os)("Failed to CreateWaitableTimer: %u", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// We need a minimum of one hundred nanos.
|
||||
ns = ns > 100 ? ns : 100;
|
||||
|
||||
// Round ns to the nearst hundred of nanos.
|
||||
// Negative values indicate relative time.
|
||||
hundreds_nanos.QuadPart = -((ns + 50) / 100);
|
||||
|
||||
if (::SetWaitableTimer(wait_timer /* handle */,
|
||||
&hundreds_nanos /* due time */,
|
||||
0 /* period */,
|
||||
NULL /* comp func */,
|
||||
NULL /* comp func args */,
|
||||
FALSE /* resume */)) {
|
||||
DWORD res = ::WaitForSingleObject(wait_timer /* handle */, INFINITE /* timeout */);
|
||||
if (res != WAIT_OBJECT_0) {
|
||||
if (res == WAIT_FAILED) {
|
||||
log_warning(os)("Failed to WaitForSingleObject: %u", GetLastError());
|
||||
} else {
|
||||
log_warning(os)("Unexpected return from WaitForSingleObject: %s",
|
||||
res == WAIT_ABANDONED ? "WAIT_ABANDONED" : "WAIT_TIMEOUT");
|
||||
}
|
||||
int64_t start = os::javaTimeNanos();
|
||||
do {
|
||||
if (SwitchToThread() == 0) {
|
||||
// Nothing else is ready to run on this cpu, spin a little
|
||||
SpinPause();
|
||||
}
|
||||
}
|
||||
::CloseHandle(wait_timer /* handle */);
|
||||
} while (os::javaTimeNanos() - start < ns);
|
||||
}
|
||||
|
||||
// Sleep forever; naked call to OS-specific sleep; use with CAUTION
|
||||
|
@ -186,16 +186,14 @@ static void assert_list_is_valid(const ThreadSafepointState* tss_head, int still
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
static void back_off(int iteration) {
|
||||
// iteration will be 1 the first time we enter this spin back-off.
|
||||
// naked_short_nanosleep takes tenths of micros which means that
|
||||
// number of nanoseconds is irrelevant if it's below that. We do
|
||||
// 20 1 ns sleeps with a total cost of ~1 ms, then we do 1 ms sleeps.
|
||||
jlong sleep_ns = 1;
|
||||
if (iteration > 20) {
|
||||
sleep_ns = NANOUNITS / MILLIUNITS; // 1 ms
|
||||
static void back_off(int64_t start_time) {
|
||||
// We start with fine-grained nanosleeping until a millisecond has
|
||||
// passed, at which point we resort to plain naked_short_sleep.
|
||||
if (os::javaTimeNanos() - start_time < NANOSECS_PER_MILLISEC) {
|
||||
os::naked_short_nanosleep(10 * (NANOUNITS / MICROUNITS));
|
||||
} else {
|
||||
os::naked_short_sleep(1);
|
||||
}
|
||||
os::naked_short_nanosleep(sleep_ns);
|
||||
}
|
||||
|
||||
int SafepointSynchronize::synchronize_threads(jlong safepoint_limit_time, int nof_threads, int* initial_running)
|
||||
@ -229,9 +227,16 @@ int SafepointSynchronize::synchronize_threads(jlong safepoint_limit_time, int no
|
||||
|
||||
*initial_running = still_running;
|
||||
|
||||
int iterations = 1; // The first iteration is above.
|
||||
// If there is no thread still running, we are already done.
|
||||
if (still_running <= 0) {
|
||||
assert(tss_head == NULL, "Must be empty");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (still_running > 0) {
|
||||
int iterations = 1; // The first iteration is above.
|
||||
int64_t start_time = os::javaTimeNanos();
|
||||
|
||||
do {
|
||||
// Check if this has taken too long:
|
||||
if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
|
||||
print_safepoint_timeout();
|
||||
@ -264,11 +269,11 @@ int SafepointSynchronize::synchronize_threads(jlong safepoint_limit_time, int no
|
||||
DEBUG_ONLY(assert_list_is_valid(tss_head, still_running);)
|
||||
|
||||
if (still_running > 0) {
|
||||
back_off(iterations);
|
||||
back_off(start_time);
|
||||
}
|
||||
|
||||
iterations++;
|
||||
}
|
||||
} while (still_running > 0);
|
||||
|
||||
assert(tss_head == NULL, "Must be empty");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user