From 16c3fecd0702b444e4ebe81da7adba9676bb3195 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Wed, 18 Dec 2024 12:20:06 +0100 Subject: [PATCH 1/4] 8332506: SIGFPE In ObjectSynchronizer::is_async_deflation_needed() causing JVM Crash --- src/hotspot/share/runtime/synchronizer.cpp | 47 +++++++++++++--------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 941309ca2acc9..32e1d4471e3c0 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1264,36 +1264,45 @@ static bool monitors_used_above_threshold(MonitorList* list) { if (MonitorUsedDeflationThreshold == 0) { // disabled case is easy return false; } - // Start with ceiling based on a per-thread estimate: - size_t ceiling = ObjectSynchronizer::in_use_list_ceiling(); - size_t old_ceiling = ceiling; - if (ceiling < list->max()) { - // The max used by the system has exceeded the ceiling so use that: - ceiling = list->max(); - } size_t monitors_used = list->count(); if (monitors_used == 0) { // empty list is easy return false; } - if (NoAsyncDeflationProgressMax != 0 && - _no_progress_cnt >= NoAsyncDeflationProgressMax) { - double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; - size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1; - ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); - log_info(monitorinflation)("Too many deflations without progress; " - "bumping in_use_list_ceiling from " SIZE_FORMAT - " to " SIZE_FORMAT, old_ceiling, new_ceiling); - _no_progress_cnt = 0; - ceiling = new_ceiling; - } + size_t old_ceiling = ObjectSynchronizer::in_use_list_ceiling(); + // Make sure the we use a ceiling value that is not lower than the + // max used by the system, and not zero. + size_t ceiling = MAX3(old_ceiling, list->max(), monitors_used); // Check if our monitor usage is above the threshold: size_t monitor_usage = (monitors_used * 100LL) / ceiling; if (int(monitor_usage) > MonitorUsedDeflationThreshold) { + bool status = true; + + // Check if we it's time to adjust the in_use_list_ceiling up, due + // to too many async deflation attempts without any progress. + if (NoAsyncDeflationProgressMax != 0 && + _no_progress_cnt >= NoAsyncDeflationProgressMax) { + double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; + size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1; + + if (new_ceiling < old_ceiling) { + new_ceiling = SIZE_MAX; // Wrap around, let's clamp new_ceiling. + } + ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); + log_info(monitorinflation)("Too many deflations without progress; " + "bumping in_use_list_ceiling from " SIZE_FORMAT + " to " SIZE_FORMAT, old_ceiling, new_ceiling); + _no_progress_cnt = 0; + ceiling = new_ceiling; + + // Check if our monitor usage is still above the threshold: + monitor_usage = (monitors_used * 100LL) / ceiling; + status = int(monitor_usage) > MonitorUsedDeflationThreshold; + } log_info(monitorinflation)("monitors_used=" SIZE_FORMAT ", ceiling=" SIZE_FORMAT ", monitor_usage=" SIZE_FORMAT ", threshold=%d", monitors_used, ceiling, monitor_usage, MonitorUsedDeflationThreshold); - return true; + return status; } return false; From 452fb584a7702bf3adc661724d6cad12e2d58064 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Thu, 2 Jan 2025 11:55:08 +0100 Subject: [PATCH 2/4] Update after review --- src/hotspot/share/runtime/synchronizer.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 32e1d4471e3c0..ce4d89159a747 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1278,16 +1278,16 @@ static bool monitors_used_above_threshold(MonitorList* list) { if (int(monitor_usage) > MonitorUsedDeflationThreshold) { bool status = true; - // Check if we it's time to adjust the in_use_list_ceiling up, due + // Check if it's time to adjust the in_use_list_ceiling up, due // to too many async deflation attempts without any progress. if (NoAsyncDeflationProgressMax != 0 && _no_progress_cnt >= NoAsyncDeflationProgressMax) { double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; - size_t new_ceiling = ceiling + (size_t)((double)ceiling * remainder) + 1; + size_t delta = (size_t)((double)ceiling * remainder) + 1; + size_t new_ceiling = (ceiling > SIZE_MAX - delta) + ? SIZE_MAX // Overflow, let's clamp new_ceiling. + : ceiling + delta; - if (new_ceiling < old_ceiling) { - new_ceiling = SIZE_MAX; // Wrap around, let's clamp new_ceiling. - } ObjectSynchronizer::set_in_use_list_ceiling(new_ceiling); log_info(monitorinflation)("Too many deflations without progress; " "bumping in_use_list_ceiling from " SIZE_FORMAT From 502766b759d13edd1ce3f4ebd46fcc8f13ed5d53 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Sun, 5 Jan 2025 15:59:37 +0100 Subject: [PATCH 3/4] Update two after review --- src/hotspot/share/runtime/synchronizer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index ce4d89159a747..6c91f9d34c601 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1276,7 +1276,9 @@ static bool monitors_used_above_threshold(MonitorList* list) { // Check if our monitor usage is above the threshold: size_t monitor_usage = (monitors_used * 100LL) / ceiling; if (int(monitor_usage) > MonitorUsedDeflationThreshold) { - bool status = true; + // Deflate monitors if over the threshold percentage, unless no + // progress on previous deflations. + bool is_above_threshold = true; // Check if it's time to adjust the in_use_list_ceiling up, due // to too many async deflation attempts without any progress. @@ -1297,12 +1299,12 @@ static bool monitors_used_above_threshold(MonitorList* list) { // Check if our monitor usage is still above the threshold: monitor_usage = (monitors_used * 100LL) / ceiling; - status = int(monitor_usage) > MonitorUsedDeflationThreshold; + is_above_threshold = int(monitor_usage) > MonitorUsedDeflationThreshold; } log_info(monitorinflation)("monitors_used=" SIZE_FORMAT ", ceiling=" SIZE_FORMAT ", monitor_usage=" SIZE_FORMAT ", threshold=%d", monitors_used, ceiling, monitor_usage, MonitorUsedDeflationThreshold); - return status; + return is_above_threshold; } return false; From 99a31a2f05374ad808f4a7df397cb170692c95ac Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Tue, 7 Jan 2025 10:58:02 +0100 Subject: [PATCH 4/4] Update three after review --- src/hotspot/share/runtime/synchronizer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 6c91f9d34c601..fdce6d21531e9 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1269,8 +1269,10 @@ static bool monitors_used_above_threshold(MonitorList* list) { return false; } size_t old_ceiling = ObjectSynchronizer::in_use_list_ceiling(); - // Make sure the we use a ceiling value that is not lower than the - // max used by the system, and not zero. + // Make sure that we use a ceiling value that is not lower than + // previous, not lower than the recorded max used by the system, and + // not lower than the current number of monitors in use (which can + // race ahead of max). The result is guaranteed > 0. size_t ceiling = MAX3(old_ceiling, list->max(), monitors_used); // Check if our monitor usage is above the threshold: @@ -1285,7 +1287,7 @@ static bool monitors_used_above_threshold(MonitorList* list) { if (NoAsyncDeflationProgressMax != 0 && _no_progress_cnt >= NoAsyncDeflationProgressMax) { double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; - size_t delta = (size_t)((double)ceiling * remainder) + 1; + size_t delta = (size_t)(ceiling * remainder) + 1; size_t new_ceiling = (ceiling > SIZE_MAX - delta) ? SIZE_MAX // Overflow, let's clamp new_ceiling. : ceiling + delta;