diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 941309ca2acc9..fdce6d21531e9 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 @@ -1264,36 +1264,49 @@ 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 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: size_t monitor_usage = (monitors_used * 100LL) / ceiling; if (int(monitor_usage) > MonitorUsedDeflationThreshold) { + // 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. + if (NoAsyncDeflationProgressMax != 0 && + _no_progress_cnt >= NoAsyncDeflationProgressMax) { + double remainder = (100.0 - MonitorUsedDeflationThreshold) / 100.0; + 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; + + 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; + 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 true; + return is_above_threshold; } return false;