1 /* 2 * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.hpp" 27 #include "classfile/vmClasses.hpp" 28 #include "classfile/vmSymbols.hpp" 29 #include "logging/log.hpp" 30 #include "logging/logStream.hpp" 31 #include "memory/universe.hpp" 32 #include "runtime/interfaceSupport.inline.hpp" 33 #include "runtime/java.hpp" 34 #include "runtime/javaCalls.hpp" 35 #include "runtime/lightweightSynchronizer.hpp" 36 #include "runtime/monitorDeflationThread.hpp" 37 #include "runtime/mutexLocker.hpp" 38 #include "runtime/synchronizer.hpp" 39 #include "utilities/checkedCast.hpp" 40 41 void MonitorDeflationThread::initialize() { 42 EXCEPTION_MARK; 43 44 const char* name = "Monitor Deflation Thread"; 45 Handle thread_oop = JavaThread::create_system_thread_object(name, CHECK); 46 47 MonitorDeflationThread* thread = new MonitorDeflationThread(&monitor_deflation_thread_entry); 48 JavaThread::vm_exit_on_osthread_failure(thread); 49 50 JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority); 51 } 52 53 void MonitorDeflationThread::monitor_deflation_thread_entry(JavaThread* jt, TRAPS) { 54 55 // We wait for the lowest of these three intervals: 56 // - GuaranteedSafepointInterval 57 // While deflation is not related to safepoint anymore, this keeps compatibility with 58 // the old behavior when deflation also happened at safepoints. Users who set this 59 // option to get more/less frequent deflations would be served with this option. 60 // - AsyncDeflationInterval 61 // Normal threshold-based deflation heuristic checks the conditions at this interval. 62 // See is_async_deflation_needed(). 63 // - GuaranteedAsyncDeflationInterval 64 // Backup deflation heuristic checks the conditions at this interval. 65 // See is_async_deflation_needed(). 66 // 67 intx deflation_interval = max_intx; 68 if (GuaranteedSafepointInterval > 0) { 69 deflation_interval = MIN2(deflation_interval, GuaranteedSafepointInterval); 70 } 71 if (AsyncDeflationInterval > 0) { 72 deflation_interval = MIN2(deflation_interval, AsyncDeflationInterval); 73 } 74 if (GuaranteedAsyncDeflationInterval > 0) { 75 deflation_interval = MIN2(deflation_interval, GuaranteedAsyncDeflationInterval); 76 } 77 78 // If all options are disabled, then wait time is not defined, and the deflation 79 // is effectively disabled. In that case, exit the thread immediately after printing 80 // a warning message. 81 if (deflation_interval == max_intx) { 82 warning("Async deflation is disabled"); 83 LightweightSynchronizer::set_table_max(jt); 84 return; 85 } 86 87 intx time_to_wait = deflation_interval; 88 while (true) { 89 bool resize = false; 90 { 91 // TODO[OMWorld]: This is all being rewritten. 92 // Need state transition ThreadBlockInVM so that this thread 93 // will be handled by safepoint correctly when this thread is 94 // notified at a safepoint. 95 96 ThreadBlockInVM tbivm(jt); 97 98 MonitorLocker ml(MonitorDeflation_lock, Mutex::_no_safepoint_check_flag); 99 while (!ObjectSynchronizer::is_async_deflation_needed()) { 100 // Wait until notified that there is some work to do. 101 ml.wait(time_to_wait); 102 103 // Handle LightweightSynchronizer Hash Table Resizing 104 if (LightweightSynchronizer::needs_resize(jt)) { 105 resize = true; 106 break; 107 } 108 } 109 } 110 111 if (resize) { 112 // TODO[OMWorld]: Recheck this logic, especially !resize_successful and LightweightSynchronizer::needs_resize when is_max_size_reached == true 113 const intx time_since_last_deflation = checked_cast<intx>(ObjectSynchronizer::time_since_last_async_deflation_ms()); 114 const bool resize_successful = LightweightSynchronizer::resize_table(jt); 115 const bool deflation_interval_passed = time_since_last_deflation >= deflation_interval; 116 const bool deflation_needed = deflation_interval_passed && ObjectSynchronizer::is_async_deflation_needed(); 117 118 if (!resize_successful) { 119 // Resize failed, try again in 250 ms 120 time_to_wait = 250; 121 } else if (deflation_interval_passed) { 122 time_to_wait = deflation_interval; 123 } else { 124 time_to_wait = deflation_interval - time_since_last_deflation; 125 } 126 127 if (!deflation_needed) { 128 continue; 129 } 130 } else { 131 time_to_wait = deflation_interval; 132 } 133 134 135 (void)ObjectSynchronizer::deflate_idle_monitors(); 136 137 if (log_is_enabled(Debug, monitorinflation)) { 138 // The VMThread calls do_final_audit_and_print_stats() which calls 139 // audit_and_print_stats() at the Info level at VM exit time. 140 LogStreamHandle(Debug, monitorinflation) ls; 141 ObjectSynchronizer::audit_and_print_stats(&ls, false /* on_exit */); 142 } 143 } 144 }