aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_RUNTIME_SAFEPOINT_HPP aoqi@0: #define SHARE_VM_RUNTIME_SAFEPOINT_HPP aoqi@0: aoqi@0: #include "asm/assembler.hpp" aoqi@0: #include "code/nmethod.hpp" aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "runtime/extendedPC.hpp" aoqi@0: #include "runtime/mutexLocker.hpp" aoqi@0: #include "runtime/os.hpp" aoqi@0: #include "utilities/ostream.hpp" aoqi@0: aoqi@0: // aoqi@0: // Safepoint synchronization aoqi@0: //// aoqi@0: // The VMThread or CMS_thread uses the SafepointSynchronize::begin/end aoqi@0: // methods to enter/exit a safepoint region. The begin method will roll aoqi@0: // all JavaThreads forward to a safepoint. aoqi@0: // aoqi@0: // JavaThreads must use the ThreadSafepointState abstraction (defined in aoqi@0: // thread.hpp) to indicate that that they are at a safepoint. aoqi@0: // aoqi@0: // The Mutex/Condition variable and ObjectLocker classes calls the enter/ aoqi@0: // exit safepoint methods, when a thread is blocked/restarted. Hence, all mutex exter/ aoqi@0: // exit points *must* be at a safepoint. aoqi@0: aoqi@0: aoqi@0: class ThreadSafepointState; aoqi@0: class SnippetCache; aoqi@0: class nmethod; aoqi@0: aoqi@0: // aoqi@0: // Implements roll-forward to safepoint (safepoint synchronization) aoqi@0: // aoqi@0: class SafepointSynchronize : AllStatic { aoqi@0: public: aoqi@0: enum SynchronizeState { aoqi@0: _not_synchronized = 0, // Threads not synchronized at a safepoint aoqi@0: // Keep this value 0. See the coment in do_call_back() aoqi@0: _synchronizing = 1, // Synchronizing in progress aoqi@0: _synchronized = 2 // All Java threads are stopped at a safepoint. Only VM thread is running aoqi@0: }; aoqi@0: aoqi@0: enum SafepointingThread { aoqi@0: _null_thread = 0, aoqi@0: _vm_thread = 1, aoqi@0: _other_thread = 2 aoqi@0: }; aoqi@0: aoqi@0: enum SafepointTimeoutReason { aoqi@0: _spinning_timeout = 0, aoqi@0: _blocking_timeout = 1 aoqi@0: }; aoqi@0: aoqi@0: typedef struct { aoqi@0: float _time_stamp; // record when the current safepoint occurs in seconds aoqi@0: int _vmop_type; // type of VM operation triggers the safepoint aoqi@0: int _nof_total_threads; // total number of Java threads aoqi@0: int _nof_initial_running_threads; // total number of initially seen running threads aoqi@0: int _nof_threads_wait_to_block; // total number of threads waiting for to block aoqi@0: bool _page_armed; // true if polling page is armed, false otherwise aoqi@0: int _nof_threads_hit_page_trap; // total number of threads hitting the page trap aoqi@0: jlong _time_to_spin; // total time in millis spent in spinning aoqi@0: jlong _time_to_wait_to_block; // total time in millis spent in waiting for to block aoqi@0: jlong _time_to_do_cleanups; // total time in millis spent in performing cleanups aoqi@0: jlong _time_to_sync; // total time in millis spent in getting to _synchronized aoqi@0: jlong _time_to_exec_vmop; // total time in millis spent in vm operation itself aoqi@0: } SafepointStats; aoqi@0: aoqi@0: private: aoqi@0: static volatile SynchronizeState _state; // Threads might read this flag directly, without acquireing the Threads_lock aoqi@0: static volatile int _waiting_to_block; // number of threads we are waiting for to block aoqi@0: static int _current_jni_active_count; // Counts the number of active critical natives during the safepoint aoqi@0: aoqi@0: // This counter is used for fast versions of jni_GetField. aoqi@0: // An even value means there is no ongoing safepoint operations. aoqi@0: // The counter is incremented ONLY at the beginning and end of each aoqi@0: // safepoint. The fact that Threads_lock is held throughout each pair of aoqi@0: // increments (at the beginning and end of each safepoint) guarantees aoqi@0: // race freedom. aoqi@0: public: aoqi@0: static volatile int _safepoint_counter; aoqi@0: private: aoqi@0: static long _end_of_last_safepoint; // Time of last safepoint in milliseconds aoqi@0: aoqi@0: // statistics aoqi@0: static jlong _safepoint_begin_time; // time when safepoint begins aoqi@0: static SafepointStats* _safepoint_stats; // array of SafepointStats struct aoqi@0: static int _cur_stat_index; // current index to the above array aoqi@0: static julong _safepoint_reasons[]; // safepoint count for each VM op aoqi@0: static julong _coalesced_vmop_count; // coalesced vmop count aoqi@0: static jlong _max_sync_time; // maximum sync time in nanos aoqi@0: static jlong _max_vmop_time; // maximum vm operation time in nanos aoqi@0: static float _ts_of_current_safepoint; // time stamp of current safepoint in seconds aoqi@0: aoqi@0: static void begin_statistics(int nof_threads, int nof_running); aoqi@0: static void update_statistics_on_spin_end(); aoqi@0: static void update_statistics_on_sync_end(jlong end_time); aoqi@0: static void update_statistics_on_cleanup_end(jlong end_time); aoqi@0: static void end_statistics(jlong end_time); aoqi@0: static void print_statistics(); aoqi@0: inline static void inc_page_trap_count() { aoqi@0: Atomic::inc(&_safepoint_stats[_cur_stat_index]._nof_threads_hit_page_trap); aoqi@0: } aoqi@0: aoqi@0: // For debug long safepoint aoqi@0: static void print_safepoint_timeout(SafepointTimeoutReason timeout_reason); aoqi@0: aoqi@0: public: aoqi@0: aoqi@0: // Main entry points aoqi@0: aoqi@0: // Roll all threads forward to safepoint. Must be called by the aoqi@0: // VMThread or CMS_thread. aoqi@0: static void begin(); aoqi@0: static void end(); // Start all suspended threads again... aoqi@0: aoqi@0: static bool safepoint_safe(JavaThread *thread, JavaThreadState state); aoqi@0: aoqi@0: static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state); aoqi@0: aoqi@0: // Query aoqi@0: inline static bool is_at_safepoint() { return _state == _synchronized; } aoqi@0: inline static bool is_synchronizing() { return _state == _synchronizing; } aoqi@0: aoqi@0: inline static bool do_call_back() { aoqi@0: return (_state != _not_synchronized); aoqi@0: } aoqi@0: aoqi@0: inline static void increment_jni_active_count() { aoqi@0: assert_locked_or_safepoint(Safepoint_lock); aoqi@0: _current_jni_active_count++; aoqi@0: } aoqi@0: aoqi@0: // Called when a thread volantary blocks aoqi@0: static void block(JavaThread *thread); aoqi@0: static void signal_thread_at_safepoint() { _waiting_to_block--; } aoqi@0: aoqi@0: // Exception handling for page polling aoqi@0: static void handle_polling_page_exception(JavaThread *thread); aoqi@0: aoqi@0: // VM Thread interface for determining safepoint rate aoqi@0: static long last_non_safepoint_interval() { aoqi@0: return os::javaTimeMillis() - _end_of_last_safepoint; aoqi@0: } aoqi@0: static long end_of_last_safepoint() { aoqi@0: return _end_of_last_safepoint; aoqi@0: } aoqi@0: static bool is_cleanup_needed(); aoqi@0: static void do_cleanup_tasks(); aoqi@0: aoqi@0: // debugging aoqi@0: static void print_state() PRODUCT_RETURN; aoqi@0: static void safepoint_msg(const char* format, ...) ATTRIBUTE_PRINTF(1, 2) PRODUCT_RETURN; aoqi@0: aoqi@0: static void deferred_initialize_stat(); aoqi@0: static void print_stat_on_exit(); aoqi@0: inline static void inc_vmop_coalesced_count() { _coalesced_vmop_count++; } aoqi@0: aoqi@0: static void set_is_at_safepoint() { _state = _synchronized; } aoqi@0: static void set_is_not_at_safepoint() { _state = _not_synchronized; } aoqi@0: aoqi@0: // assembly support aoqi@0: static address address_of_state() { return (address)&_state; } aoqi@0: aoqi@0: static address safepoint_counter_addr() { return (address)&_safepoint_counter; } aoqi@0: }; aoqi@0: aoqi@0: // State class for a thread suspended at a safepoint aoqi@0: class ThreadSafepointState: public CHeapObj { aoqi@0: public: aoqi@0: // These states are maintained by VM thread while threads are being brought aoqi@0: // to a safepoint. After SafepointSynchronize::end(), they are reset to aoqi@0: // _running. aoqi@0: enum suspend_type { aoqi@0: _running = 0, // Thread state not yet determined (i.e., not at a safepoint yet) aoqi@0: _at_safepoint = 1, // Thread at a safepoint (f.ex., when blocked on a lock) aoqi@0: _call_back = 2 // Keep executing and wait for callback (if thread is in interpreted or vm) aoqi@0: }; aoqi@0: private: aoqi@0: volatile bool _at_poll_safepoint; // At polling page safepoint (NOT a poll return safepoint) aoqi@0: // Thread has called back the safepoint code (for debugging) aoqi@0: bool _has_called_back; aoqi@0: aoqi@0: JavaThread * _thread; aoqi@0: volatile suspend_type _type; aoqi@0: JavaThreadState _orig_thread_state; aoqi@0: aoqi@0: aoqi@0: public: aoqi@0: ThreadSafepointState(JavaThread *thread); aoqi@0: aoqi@0: // examine/roll-forward/restart aoqi@0: void examine_state_of_thread(); aoqi@0: void roll_forward(suspend_type type); aoqi@0: void restart(); aoqi@0: aoqi@0: // Query aoqi@0: JavaThread* thread() const { return _thread; } aoqi@0: suspend_type type() const { return _type; } aoqi@0: bool is_running() const { return (_type==_running); } aoqi@0: JavaThreadState orig_thread_state() const { return _orig_thread_state; } aoqi@0: aoqi@0: // Support for safepoint timeout (debugging) aoqi@0: bool has_called_back() const { return _has_called_back; } aoqi@0: void set_has_called_back(bool val) { _has_called_back = val; } aoqi@0: bool is_at_poll_safepoint() { return _at_poll_safepoint; } aoqi@0: void set_at_poll_safepoint(bool val) { _at_poll_safepoint = val; } aoqi@0: aoqi@0: void handle_polling_page_exception(); aoqi@0: aoqi@0: // debugging aoqi@0: void print_on(outputStream* st) const; aoqi@0: void print() const { print_on(tty); } aoqi@0: aoqi@0: // Initialize aoqi@0: static void create(JavaThread *thread); aoqi@0: static void destroy(JavaThread *thread); aoqi@0: aoqi@0: void safepoint_msg(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) { aoqi@0: if (ShowSafepointMsgs) { aoqi@0: va_list ap; aoqi@0: va_start(ap, format); aoqi@0: tty->vprint_cr(format, ap); aoqi@0: va_end(ap); aoqi@0: } aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: aoqi@0: #endif // SHARE_VM_RUNTIME_SAFEPOINT_HPP