| /* |
| * Copyright (c) 1998, 2024, 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 |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #ifndef SHARE_RUNTIME_SYNCHRONIZER_HPP |
| #define SHARE_RUNTIME_SYNCHRONIZER_HPP |
| |
| #include "memory/padded.hpp" |
| #include "oops/markWord.hpp" |
| #include "runtime/basicLock.hpp" |
| #include "runtime/handles.hpp" |
| #include "runtime/javaThread.hpp" |
| #include "utilities/resourceHash.hpp" |
| |
| template <typename T> class GrowableArray; |
| class LogStream; |
| class ObjectMonitor; |
| class ObjectMonitorDeflationSafepointer; |
| class ThreadsList; |
| |
| class MonitorList { |
| friend class VMStructs; |
| |
| private: |
| ObjectMonitor* volatile _head; |
| volatile size_t _count; |
| volatile size_t _max; |
| |
| public: |
| MonitorList() : _head(nullptr), _count(0), _max(0) {}; |
| void add(ObjectMonitor* monitor); |
| size_t unlink_deflated(size_t deflated_count, |
| GrowableArray<ObjectMonitor*>* unlinked_list, |
| ObjectMonitorDeflationSafepointer* safepointer); |
| size_t count() const; |
| size_t max() const; |
| |
| class Iterator; |
| Iterator iterator() const; |
| }; |
| |
| class MonitorList::Iterator { |
| ObjectMonitor* _current; |
| |
| public: |
| Iterator(ObjectMonitor* head) : _current(head) {} |
| bool has_next() const { return _current != nullptr; } |
| ObjectMonitor* next(); |
| }; |
| |
| class ObjectSynchronizer : AllStatic { |
| friend class VMStructs; |
| friend class ObjectMonitorDeflationLogging; |
| friend class WhiteBox; |
| |
| public: |
| typedef enum { |
| inflate_cause_vm_internal = 0, |
| inflate_cause_monitor_enter = 1, |
| inflate_cause_wait = 2, |
| inflate_cause_notify = 3, |
| inflate_cause_hash_code = 4, |
| inflate_cause_jni_enter = 5, |
| inflate_cause_jni_exit = 6, |
| inflate_cause_nof = 7 // Number of causes |
| } InflateCause; |
| |
| typedef enum { |
| NOT_ENABLED = 0, |
| FATAL_EXIT = 1, |
| LOG_WARNING = 2 |
| } SyncDiagnosticOption; |
| |
| // exit must be implemented non-blocking, since the compiler cannot easily handle |
| // deoptimization at monitor exit. Hence, it does not take a Handle argument. |
| |
| // This is the "slow path" version of monitor enter and exit. |
| static inline void enter(Handle obj, BasicLock* lock, JavaThread* current); |
| static inline void exit(oop obj, BasicLock* lock, JavaThread* current); |
| |
| // Used to enter a monitor for another thread. This requires that the |
| // locking_thread is suspended, and that entering on a potential |
| // inflated monitor may only contend with deflation. That is the obj being |
| // locked on is either already locked by the locking_thread or cannot |
| // escape the locking_thread. |
| static void enter_for(Handle obj, BasicLock* lock, JavaThread* locking_thread); |
| private: |
| // Shared implementation for enter and enter_for. Performs all but |
| // inflated monitor enter. |
| static bool enter_fast_impl(Handle obj, BasicLock* lock, JavaThread* locking_thread); |
| |
| static bool quick_enter_legacy(oop obj, BasicLock* Lock, JavaThread* current); |
| static void enter_legacy(Handle obj, BasicLock* Lock, JavaThread* current); |
| static void exit_legacy(oop obj, BasicLock* lock, JavaThread* current); |
| public: |
| // Used only to handle jni locks or other unmatched monitor enter/exit |
| // Internally they will use heavy weight monitor. |
| static void jni_enter(Handle obj, JavaThread* current); |
| static void jni_exit(oop obj, TRAPS); |
| |
| // Handle all interpreter, compiler and jni cases |
| static int wait(Handle obj, jlong millis, TRAPS); |
| static void notify(Handle obj, TRAPS); |
| static void notifyall(Handle obj, TRAPS); |
| |
| static bool quick_notify(oopDesc* obj, JavaThread* current, bool All); |
| static inline bool quick_enter(oop obj, BasicLock* Lock, JavaThread* current); |
| |
| // Special internal-use-only method for use by JVM infrastructure |
| // that needs to wait() on a java-level object but that can't risk |
| // throwing unexpected InterruptedExecutionExceptions. |
| static void waitUninterruptibly(Handle obj, jlong Millis, TRAPS); |
| |
| // Inflate light weight monitor to heavy weight monitor |
| static ObjectMonitor* inflate(Thread* current, oop obj, const InflateCause cause); |
| // Used to inflate a monitor as if it was done from the thread JavaThread. |
| static ObjectMonitor* inflate_for(JavaThread* thread, oop obj, const InflateCause cause); |
| |
| private: |
| // Shared implementation between the different LockingMode. |
| static ObjectMonitor* inflate_impl(JavaThread* locking_thread, oop obj, const InflateCause cause); |
| |
| public: |
| // This version is only for internal use |
| static void inflate_helper(oop obj); |
| static const char* inflate_cause_name(const InflateCause cause); |
| |
| inline static ObjectMonitor* read_monitor(markWord mark); |
| inline static ObjectMonitor* read_monitor(Thread* current, oop obj, markWord mark); |
| |
| // Returns the identity hash value for an oop |
| // NOTE: It may cause monitor inflation |
| static intptr_t FastHashCode(Thread* current, oop obj); |
| |
| // java.lang.Thread support |
| static bool current_thread_holds_lock(JavaThread* current, Handle h_obj); |
| |
| static JavaThread* get_lock_owner(ThreadsList * t_list, Handle h_obj); |
| |
| // JNI detach support |
| static void release_monitors_owned_by_thread(JavaThread* current); |
| |
| // Iterate over all ObjectMonitors. |
| template <typename Function> |
| static void monitors_iterate(Function function); |
| |
| // Iterate ObjectMonitors owned by any thread and where the owner `filter` |
| // returns true. |
| template <typename OwnerFilter> |
| static void owned_monitors_iterate_filtered(MonitorClosure* closure, OwnerFilter filter); |
| |
| // Iterate ObjectMonitors where the owner is thread; this does NOT include |
| // ObjectMonitors where the owner is anonymous. |
| static void owned_monitors_iterate(MonitorClosure* m, JavaThread* thread); |
| |
| // Iterate ObjectMonitors where the owner is vthread. |
| static void owned_monitors_iterate(MonitorClosure* m, oop vthread); |
| |
| // Iterate ObjectMonitors owned by any thread. |
| static void owned_monitors_iterate(MonitorClosure* closure); |
| |
| // Initialize the gInflationLocks |
| static void initialize(); |
| |
| // We currently use aggressive monitor deflation policy; |
| // basically we try to deflate all monitors that are not busy. |
| static size_t deflate_idle_monitors(); |
| |
| // Deflate idle monitors: |
| static size_t deflate_monitor_list(ObjectMonitorDeflationSafepointer* safepointer); |
| static size_t in_use_list_count(); |
| static size_t in_use_list_max(); |
| static size_t in_use_list_ceiling(); |
| static void dec_in_use_list_ceiling(); |
| static void inc_in_use_list_ceiling(); |
| static void set_in_use_list_ceiling(size_t new_value); |
| static bool is_async_deflation_needed(); |
| static bool is_async_deflation_requested() { return _is_async_deflation_requested; } |
| static bool is_final_audit() { return _is_final_audit; } |
| static void set_is_final_audit() { _is_final_audit = true; } |
| static jlong last_async_deflation_time_ns() { return _last_async_deflation_time_ns; } |
| static void request_deflate_idle_monitors(); |
| static bool request_deflate_idle_monitors_from_wb(); // for whitebox test support |
| static void set_is_async_deflation_requested(bool new_value) { _is_async_deflation_requested = new_value; } |
| static jlong time_since_last_async_deflation_ms(); |
| |
| // debugging |
| static void audit_and_print_stats(outputStream* out, bool on_exit); |
| static void chk_in_use_list(outputStream* out, int* error_cnt_p); |
| static void chk_in_use_entry(ObjectMonitor* n, outputStream* out, |
| int* error_cnt_p); |
| static void do_final_audit_and_print_stats(); |
| static void log_in_use_monitor_details(outputStream* out, bool log_all); |
| |
| private: |
| friend class SynchronizerTest; |
| friend class LightweightSynchronizer; |
| |
| static MonitorList _in_use_list; |
| static volatile bool _is_async_deflation_requested; |
| static volatile bool _is_final_audit; |
| static jlong _last_async_deflation_time_ns; |
| |
| // Support for SynchronizerTest access to GVars fields: |
| static u_char* get_gvars_addr(); |
| static u_char* get_gvars_hc_sequence_addr(); |
| static size_t get_gvars_size(); |
| static u_char* get_gvars_stw_random_addr(); |
| |
| static void handle_sync_on_value_based_class(Handle obj, JavaThread* locking_thread); |
| }; |
| |
| // ObjectLocker enforces balanced locking and can never throw an |
| // IllegalMonitorStateException. However, a pending exception may |
| // have to pass through, and we must also be able to deal with |
| // asynchronous exceptions. The caller is responsible for checking |
| // the thread's pending exception if needed. |
| // When using ObjectLocker the top native frames in the stack will |
| // not be seen in case we attempt preemption, since we start walking |
| // from the last Java anchor, so we disable it with NoPreemptMark. |
| class ObjectLocker : public StackObj { |
| private: |
| JavaThread* _thread; |
| Handle _obj; |
| BasicLock _lock; |
| NoPreemptMark _npm; |
| public: |
| ObjectLocker(Handle obj, JavaThread* current); |
| ~ObjectLocker(); |
| |
| // Monitor behavior |
| void wait(TRAPS) { ObjectSynchronizer::wait(_obj, 0, CHECK); } // wait forever |
| void wait_uninterruptibly(TRAPS) { ObjectSynchronizer::waitUninterruptibly(_obj, 0, CHECK); } // wait forever |
| void notify_all(TRAPS) { ObjectSynchronizer::notifyall(_obj, CHECK); } |
| }; |
| |
| // Interface to visit monitors |
| class ObjectMonitorsView { |
| public: |
| // Visit monitors that belong to the given thread |
| virtual void visit(MonitorClosure* closure, JavaThread* thread) = 0; |
| }; |
| |
| #endif // SHARE_RUNTIME_SYNCHRONIZER_HPP |