< prev index next >

src/share/vm/runtime/safepoint.cpp

Print this page

        

*** 30,39 **** --- 30,40 ---- #include "code/nmethod.hpp" #include "code/pcDesc.hpp" #include "code/scopeDesc.hpp" #include "gc_interface/collectedHeap.hpp" #include "interpreter/interpreter.hpp" + #include "jfr/jfrEvents.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/compilationPolicy.hpp"
*** 81,90 **** --- 82,158 ---- #include "c1/c1_globals.hpp" #endif PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC + template <typename E> + static void set_current_safepoint_id(E* event, int adjustment = 0) { + assert(event != NULL, "invariant"); + event->set_safepointId(SafepointSynchronize::safepoint_counter() + adjustment); + } + + static void post_safepoint_begin_event(EventSafepointBegin* event, + int thread_count, + int critical_thread_count) { + assert(event != NULL, "invariant"); + assert(event->should_commit(), "invariant"); + set_current_safepoint_id(event); + event->set_totalThreadCount(thread_count); + event->set_jniCriticalThreadCount(critical_thread_count); + event->commit(); + } + + static void post_safepoint_cleanup_event(EventSafepointCleanup* event) { + assert(event != NULL, "invariant"); + assert(event->should_commit(), "invariant"); + set_current_safepoint_id(event); + event->commit(); + } + + static void post_safepoint_synchronize_event(EventSafepointStateSynchronization* event, + int initial_number_of_threads, + int threads_waiting_to_block, + unsigned int iterations) { + assert(event != NULL, "invariant"); + if (event->should_commit()) { + // Group this event together with the ones committed after the counter is increased + set_current_safepoint_id(event, 1); + event->set_initialThreadCount(initial_number_of_threads); + event->set_runningThreadCount(threads_waiting_to_block); + event->set_iterations(iterations); + event->commit(); + } + } + + static void post_safepoint_wait_blocked_event(EventSafepointWaitBlocked* event, + int initial_threads_waiting_to_block) { + assert(event != NULL, "invariant"); + assert(event->should_commit(), "invariant"); + set_current_safepoint_id(event); + event->set_runningThreadCount(initial_threads_waiting_to_block); + event->commit(); + } + + static void post_safepoint_cleanup_task_event(EventSafepointCleanupTask* event, + const char* name) { + assert(event != NULL, "invariant"); + if (event->should_commit()) { + set_current_safepoint_id(event); + event->set_name(name); + event->commit(); + } + } + + static void post_safepoint_end_event(EventSafepointEnd* event) { + assert(event != NULL, "invariant"); + if (event->should_commit()) { + // Group this event together with the ones committed before the counter increased + set_current_safepoint_id(event, -1); + event->commit(); + } + } + // -------------------------------------------------------------------------------------------------- // Implementation of Safepoint begin/end SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized; volatile int SafepointSynchronize::_waiting_to_block = 0;
*** 95,105 **** static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only static bool timeout_error_printed = false; // Roll all threads forward to a safepoint and suspend them all void SafepointSynchronize::begin() { ! Thread* myThread = Thread::current(); assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint"); if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) { _safepoint_begin_time = os::javaTimeNanos(); --- 163,173 ---- static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only static bool timeout_error_printed = false; // Roll all threads forward to a safepoint and suspend them all void SafepointSynchronize::begin() { ! EventSafepointBegin begin_event; Thread* myThread = Thread::current(); assert(myThread->is_VM_thread(), "Only VM thread may execute a safepoint"); if (PrintSafepointStatistics || PrintSafepointStatisticsTimeout > 0) { _safepoint_begin_time = os::javaTimeNanos();
*** 187,196 **** --- 255,267 ---- // 5. In VM or Transitioning between states // If a Java thread is currently running in the VM or transitioning // between states, the safepointing code will wait for the thread to // block itself when it attempts transitions to a new state. // + EventSafepointStateSynchronization sync_event; + int initial_running = 0; + _state = _synchronizing; OrderAccess::fence(); // Flush all thread states to memory if (!UseMembar) {
*** 241,252 **** } if (TraceSafepoint && Verbose) cur_state->print(); } } ! if (PrintSafepointStatistics && iterations == 0) { ! begin_statistics(nof_threads, still_running); } if (still_running > 0) { // Check for if it takes to long if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) { --- 312,326 ---- } if (TraceSafepoint && Verbose) cur_state->print(); } } ! if (iterations == 0) { ! initial_running = still_running; ! if (PrintSafepointStatistics) { ! begin_statistics(nof_threads, still_running); ! } } if (still_running > 0) { // Check for if it takes to long if (SafepointTimeout && safepoint_limit_time < os::javaTimeNanos()) {
*** 334,380 **** if (PrintSafepointStatistics) { update_statistics_on_spin_end(); } // wait until all threads are stopped ! while (_waiting_to_block > 0) { ! if (TraceSafepoint) tty->print_cr("Waiting for %d thread(s) to block", _waiting_to_block); ! if (!SafepointTimeout || timeout_error_printed) { ! Safepoint_lock->wait(true); // true, means with no safepoint checks ! } else { ! // Compute remaining time ! jlong remaining_time = safepoint_limit_time - os::javaTimeNanos(); ! ! // If there is no remaining time, then there is an error ! if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) { ! print_safepoint_timeout(_blocking_timeout); } } ! } ! assert(_waiting_to_block == 0, "sanity check"); #ifndef PRODUCT ! if (SafepointTimeout) { ! jlong current_time = os::javaTimeNanos(); ! if (safepoint_limit_time < current_time) { ! tty->print_cr("# SafepointSynchronize: Finished after " ! INT64_FORMAT_W(6) " ms", ! ((current_time - safepoint_limit_time) / MICROUNITS + ! SafepointTimeoutDelay)); } - } #endif ! assert((_safepoint_counter & 0x1) == 0, "must be even"); ! assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); ! _safepoint_counter ++; ! // Record state ! _state = _synchronized; ! OrderAccess::fence(); #ifdef ASSERT for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { // make sure all the threads were visited assert(cur->was_visited_for_critical_count(), "missed a thread"); --- 408,467 ---- if (PrintSafepointStatistics) { update_statistics_on_spin_end(); } + if (sync_event.should_commit()) { + post_safepoint_synchronize_event(&sync_event, initial_running, _waiting_to_block, iterations); + } + // wait until all threads are stopped ! { ! EventSafepointWaitBlocked wait_blocked_event; ! int initial_waiting_to_block = _waiting_to_block; ! ! while (_waiting_to_block > 0) { ! if (TraceSafepoint) tty->print_cr("Waiting for %d thread(s) to block", _waiting_to_block); ! if (!SafepointTimeout || timeout_error_printed) { ! Safepoint_lock->wait(true); // true, means with no safepoint checks ! } else { ! // Compute remaining time ! jlong remaining_time = safepoint_limit_time - os::javaTimeNanos(); ! ! // If there is no remaining time, then there is an error ! if (remaining_time < 0 || Safepoint_lock->wait(true, remaining_time / MICROUNITS)) { ! print_safepoint_timeout(_blocking_timeout); ! } } } ! assert(_waiting_to_block == 0, "sanity check"); #ifndef PRODUCT ! if (SafepointTimeout) { ! jlong current_time = os::javaTimeNanos(); ! if (safepoint_limit_time < current_time) { ! tty->print_cr("# SafepointSynchronize: Finished after " ! INT64_FORMAT_W(6) " ms", ! ((current_time - safepoint_limit_time) / MICROUNITS + ! SafepointTimeoutDelay)); ! } } #endif ! assert((_safepoint_counter & 0x1) == 0, "must be even"); ! assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); ! _safepoint_counter ++; ! // Record state ! _state = _synchronized; ! OrderAccess::fence(); ! ! if (wait_blocked_event.should_commit()) { ! post_safepoint_wait_blocked_event(&wait_blocked_event, initial_waiting_to_block); ! } ! } #ifdef ASSERT for (JavaThread *cur = Threads::first(); cur != NULL; cur = cur->next()) { // make sure all the threads were visited assert(cur->was_visited_for_critical_count(), "missed a thread");
*** 393,416 **** if (PrintSafepointStatistics) { update_statistics_on_sync_end(os::javaTimeNanos()); } // Call stuff that needs to be run when a safepoint is just about to be completed ! do_cleanup_tasks(); if (PrintSafepointStatistics) { // Record how much time spend on the above cleanup tasks update_statistics_on_cleanup_end(os::javaTimeNanos()); } } // Wake up all threads, so they are ready to resume execution after the safepoint // operation has been carried out void SafepointSynchronize::end() { assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); assert((_safepoint_counter & 0x1) == 1, "must be odd"); _safepoint_counter ++; // memory fence isn't required here since an odd _safepoint_counter // value can do no harm and a fence is issued below anyway. DEBUG_ONLY(Thread* myThread = Thread::current();) --- 480,514 ---- if (PrintSafepointStatistics) { update_statistics_on_sync_end(os::javaTimeNanos()); } // Call stuff that needs to be run when a safepoint is just about to be completed ! { ! EventSafepointCleanup cleanup_event; ! do_cleanup_tasks(); ! if (cleanup_event.should_commit()) { ! post_safepoint_cleanup_event(&cleanup_event); ! } ! } if (PrintSafepointStatistics) { // Record how much time spend on the above cleanup tasks update_statistics_on_cleanup_end(os::javaTimeNanos()); } + + if (begin_event.should_commit()) { + post_safepoint_begin_event(&begin_event, nof_threads, _current_jni_active_count); + } } // Wake up all threads, so they are ready to resume execution after the safepoint // operation has been carried out void SafepointSynchronize::end() { assert(Threads_lock->owned_by_self(), "must hold Threads_lock"); assert((_safepoint_counter & 0x1) == 1, "must be odd"); + EventSafepointEnd event; _safepoint_counter ++; // memory fence isn't required here since an odd _safepoint_counter // value can do no harm and a fence is issued below anyway. DEBUG_ONLY(Thread* myThread = Thread::current();)
*** 492,501 **** --- 590,602 ---- } #endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elasped // since last safepoint. _end_of_last_safepoint = os::javaTimeMillis(); + if (event.should_commit()) { + post_safepoint_end_event(&event); + } } bool SafepointSynchronize::is_cleanup_needed() { // Need a safepoint if some inline cache buffers is non-empty if (!InlineCacheBuffer::is_empty()) return true;
*** 505,540 **** // Various cleaning tasks that should be done periodically at safepoints void SafepointSynchronize::do_cleanup_tasks() { { ! TraceTime t1("deflating idle monitors", TraceSafepointCleanupTime); ObjectSynchronizer::deflate_idle_monitors(); } { ! TraceTime t2("updating inline caches", TraceSafepointCleanupTime); InlineCacheBuffer::update_inline_caches(); } { ! TraceTime t3("compilation policy safepoint handler", TraceSafepointCleanupTime); CompilationPolicy::policy()->do_safepoint_work(); } { ! TraceTime t4("mark nmethods", TraceSafepointCleanupTime); NMethodSweeper::mark_active_nmethods(); } if (SymbolTable::needs_rehashing()) { ! TraceTime t5("rehashing symbol table", TraceSafepointCleanupTime); SymbolTable::rehash_table(); } if (StringTable::needs_rehashing()) { ! TraceTime t6("rehashing string table", TraceSafepointCleanupTime); StringTable::rehash_table(); } // rotate log files? if (UseGCLogFileRotation) { gclog_or_tty->rotate_log(false); --- 606,671 ---- // Various cleaning tasks that should be done periodically at safepoints void SafepointSynchronize::do_cleanup_tasks() { { ! const char* name = "deflating idle monitors"; ! EventSafepointCleanupTask event; ! TraceTime t1(name, TraceSafepointCleanupTime); ObjectSynchronizer::deflate_idle_monitors(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } { ! const char* name = "updating inline caches"; ! EventSafepointCleanupTask event; ! TraceTime t2(name, TraceSafepointCleanupTime); InlineCacheBuffer::update_inline_caches(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } { ! const char* name = "compilation policy safepoint handler"; ! EventSafepointCleanupTask event; ! TraceTime t3(name, TraceSafepointCleanupTime); CompilationPolicy::policy()->do_safepoint_work(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } { ! const char* name = "mark nmethods"; ! EventSafepointCleanupTask event; ! TraceTime t4(name, TraceSafepointCleanupTime); NMethodSweeper::mark_active_nmethods(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } if (SymbolTable::needs_rehashing()) { ! const char* name = "rehashing symbol table"; ! EventSafepointCleanupTask event; ! TraceTime t5(name, TraceSafepointCleanupTime); SymbolTable::rehash_table(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } if (StringTable::needs_rehashing()) { ! const char* name = "rehashing string table"; ! EventSafepointCleanupTask event; ! TraceTime t6(name, TraceSafepointCleanupTime); StringTable::rehash_table(); + if (event.should_commit()) { + post_safepoint_cleanup_task_event(&event, name); + } } // rotate log files? if (UseGCLogFileRotation) { gclog_or_tty->rotate_log(false);
< prev index next >