1 /*
 2  * Copyright (c) 2020, 2023, 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 "memory/universe.hpp"
30 #include "runtime/interfaceSupport.inline.hpp"
31 #include "runtime/java.hpp"
32 #include "runtime/javaCalls.hpp"
33 #include "runtime/monitorDeflationThread.hpp"
34 #include "runtime/mutexLocker.hpp"
35 #include "runtime/synchronizer.hpp"
36 
37 void MonitorDeflationThread::initialize() {
38   EXCEPTION_MARK;
39 
40   const char* name = "Monitor Deflation Thread";
41   Handle thread_oop = JavaThread::create_system_thread_object(name, CHECK);
42 
43   MonitorDeflationThread* thread = new MonitorDeflationThread(&monitor_deflation_thread_entry);
44   JavaThread::vm_exit_on_osthread_failure(thread);
45 
46   JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority);
47 }
48 
49 void MonitorDeflationThread::monitor_deflation_thread_entry(JavaThread* jt, TRAPS) {
50 
51   // We wait for the lowest of these three intervals:
52   //  - GuaranteedSafepointInterval
53   //      While deflation is not related to safepoint anymore, this keeps compatibility with
54   //      the old behavior when deflation also happened at safepoints. Users who set this
55   //      option to get more/less frequent deflations would be served with this option.
56   //  - AsyncDeflationInterval
57   //      Normal threshold-based deflation heuristic checks the conditions at this interval.
58   //      See is_async_deflation_needed().
59   //  - GuaranteedAsyncDeflationInterval
60   //      Backup deflation heuristic checks the conditions at this interval.
61   //      See is_async_deflation_needed().
62   //
63   intx wait_time = max_intx;
64   if (GuaranteedSafepointInterval > 0) {
65     wait_time = MIN2(wait_time, GuaranteedSafepointInterval);
66   }
67   if (AsyncDeflationInterval > 0) {
68     wait_time = MIN2(wait_time, AsyncDeflationInterval);
69   }
70   if (GuaranteedAsyncDeflationInterval > 0) {
71     wait_time = MIN2(wait_time, GuaranteedAsyncDeflationInterval);
72   }
73 
74   // If all options are disabled, then wait time is not defined, and the deflation
75   // is effectively disabled. In that case, exit the thread immediately after printing
76   // a warning message.
77   if (wait_time == max_intx) {
78     warning("Async deflation is disabled");
79     return;
80   }
81 
82   while (true) {
83     {
84       // Need state transition ThreadBlockInVM so that this thread
85       // will be handled by safepoint correctly when this thread is
86       // notified at a safepoint.
87 
88       ThreadBlockInVM tbivm(jt);
89 
90       MonitorLocker ml(MonitorDeflation_lock, Mutex::_no_safepoint_check_flag);
91       while (!ObjectSynchronizer::is_async_deflation_needed()) {
92         // Wait until notified that there is some work to do.
93         ml.wait(wait_time);
94       }
95     }
96 
97     (void)ObjectSynchronizer::deflate_idle_monitors(/* ObjectMonitorsHashtable is not needed here */ nullptr);
98   }
99 }