< prev index next >

src/hotspot/share/runtime/vmThread.cpp

Print this page

  1 /*
  2  * Copyright (c) 1998, 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 "compiler/compileBroker.hpp"
 27 #include "gc/shared/collectedHeap.hpp"
 28 #include "jfr/jfrEvents.hpp"
 29 #include "jfr/support/jfrThreadId.hpp"
 30 #include "logging/log.hpp"
 31 #include "logging/logStream.hpp"
 32 #include "logging/logConfiguration.hpp"
 33 #include "memory/resourceArea.hpp"
 34 #include "memory/universe.hpp"
 35 #include "oops/oop.inline.hpp"
 36 #include "oops/verifyOopClosure.hpp"
 37 #include "runtime/atomic.hpp"
 38 #include "runtime/cpuTimeCounters.hpp"
 39 #include "runtime/handles.inline.hpp"
 40 #include "runtime/interfaceSupport.inline.hpp"

 41 #include "runtime/javaThread.inline.hpp"
 42 #include "runtime/jniHandles.hpp"
 43 #include "runtime/mutexLocker.hpp"
 44 #include "runtime/os.hpp"
 45 #include "runtime/perfData.hpp"
 46 #include "runtime/safepoint.hpp"
 47 #include "runtime/synchronizer.hpp"
 48 #include "runtime/timerTrace.hpp"
 49 #include "runtime/vmThread.hpp"

 50 #include "runtime/vmOperations.hpp"

 51 #include "utilities/dtrace.hpp"
 52 #include "utilities/events.hpp"
 53 #include "utilities/vmError.hpp"
 54 
 55 
 56 //------------------------------------------------------------------------------------------------------------------
 57 // Timeout machinery
 58 
 59 void VMOperationTimeoutTask::task() {
 60   assert(AbortVMOnVMOperationTimeout, "only if enabled");
 61   if (is_armed()) {
 62     jlong delay = nanos_to_millis(os::javaTimeNanos() - _arm_time);
 63     if (delay > AbortVMOnVMOperationTimeoutDelay) {
 64       fatal("%s VM operation took too long: " JLONG_FORMAT " ms elapsed since VM-op start (timeout: " INTX_FORMAT " ms)",
 65             _vm_op_name, delay, AbortVMOnVMOperationTimeoutDelay);
 66     }
 67   }
 68 }
 69 
 70 bool VMOperationTimeoutTask::is_armed() {

257     }
258   }
259 }
260 
261 static void post_vm_operation_event(EventExecuteVMOperation* event, VM_Operation* op) {
262   assert(event != nullptr, "invariant");
263   assert(op != nullptr, "invariant");
264   const bool evaluate_at_safepoint = op->evaluate_at_safepoint();
265   event->set_operation(op->type());
266   event->set_safepoint(evaluate_at_safepoint);
267   event->set_blocking(true);
268   event->set_caller(JFR_THREAD_ID(op->calling_thread()));
269   event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_id() : 0);
270   event->commit();
271 }
272 
273 void VMThread::evaluate_operation(VM_Operation* op) {
274   ResourceMark rm;
275 
276   {
277     PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
278     HOTSPOT_VMOPS_BEGIN(
279                      (char *) op->name(), strlen(op->name()),
280                      op->evaluate_at_safepoint() ? 0 : 1);
281 
282     EventExecuteVMOperation event;
283     op->evaluate();
284     if (event.should_commit()) {
285       post_vm_operation_event(&event, op);
286     }
287 
288     HOTSPOT_VMOPS_END(
289                      (char *) op->name(), strlen(op->name()),
290                      op->evaluate_at_safepoint() ? 0 : 1);
291   }
292 
293   if (UsePerfData && os::is_thread_cpu_time_supported()) {
294     assert(Thread::current() == this, "Must be called from VM thread");
295     // Update vm_thread_cpu_time after each VM operation.
296     ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::vm);
297     tttc.do_thread(this);

522   public:
523 #ifdef ASSERT
524     SkipGCALot(Thread* t) : _t(t) {
525       _saved = _t->skip_gcalot();
526       _t->set_skip_gcalot(true);
527     }
528 
529     ~SkipGCALot() {
530       assert(_t->skip_gcalot(), "Save-restore protocol invariant");
531       _t->set_skip_gcalot(_saved);
532     }
533 #else
534     SkipGCALot(Thread* t) { }
535     ~SkipGCALot() { }
536 #endif
537 };
538 
539 void VMThread::execute(VM_Operation* op) {
540   Thread* t = Thread::current();
541 



542   if (t->is_VM_thread()) {
543     op->set_calling_thread(t);
544     ((VMThread*)t)->inner_execute(op);
545     return;
546   }
547 
548   // Avoid re-entrant attempts to gc-a-lot
549   SkipGCALot sgcalot(t);
550 
551   // JavaThread or WatcherThread
552   if (t->is_Java_thread()) {
553     JavaThread::cast(t)->check_for_valid_safepoint_state();
554   }
555 
556   // New request from Java thread, evaluate prologue
557   if (!op->doit_prologue()) {
558     return;   // op was cancelled
559   }
560 
561   op->set_calling_thread(t);
562 
563   wait_until_executed(op);
564 
565   op->doit_epilogue();
566 }
567 
568 void VMThread::verify() {
569   oops_do(&VerifyOopClosure::verify_oop, nullptr);
570 }





















































































  1 /*
  2  * Copyright (c) 1998, 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 "compiler/compileBroker.hpp"
 27 #include "gc/shared/collectedHeap.hpp"
 28 #include "jfr/jfrEvents.hpp"
 29 #include "jfr/support/jfrThreadId.hpp"
 30 #include "logging/log.hpp"
 31 #include "logging/logStream.hpp"
 32 #include "logging/logConfiguration.hpp"
 33 #include "memory/resourceArea.hpp"
 34 #include "memory/universe.hpp"
 35 #include "oops/oop.inline.hpp"
 36 #include "oops/verifyOopClosure.hpp"
 37 #include "runtime/atomic.hpp"
 38 #include "runtime/cpuTimeCounters.hpp"
 39 #include "runtime/handles.inline.hpp"
 40 #include "runtime/interfaceSupport.inline.hpp"
 41 #include "runtime/java.hpp"
 42 #include "runtime/javaThread.inline.hpp"
 43 #include "runtime/jniHandles.hpp"
 44 #include "runtime/mutexLocker.hpp"
 45 #include "runtime/os.hpp"
 46 #include "runtime/perfData.inline.hpp"
 47 #include "runtime/safepoint.hpp"
 48 #include "runtime/synchronizer.hpp"
 49 #include "runtime/timerTrace.hpp"
 50 #include "runtime/vmThread.hpp"
 51 #include "runtime/vmOperation.hpp"
 52 #include "runtime/vmOperations.hpp"
 53 #include "services/management.hpp"
 54 #include "utilities/dtrace.hpp"
 55 #include "utilities/events.hpp"
 56 #include "utilities/vmError.hpp"
 57 
 58 
 59 //------------------------------------------------------------------------------------------------------------------
 60 // Timeout machinery
 61 
 62 void VMOperationTimeoutTask::task() {
 63   assert(AbortVMOnVMOperationTimeout, "only if enabled");
 64   if (is_armed()) {
 65     jlong delay = nanos_to_millis(os::javaTimeNanos() - _arm_time);
 66     if (delay > AbortVMOnVMOperationTimeoutDelay) {
 67       fatal("%s VM operation took too long: " JLONG_FORMAT " ms elapsed since VM-op start (timeout: " INTX_FORMAT " ms)",
 68             _vm_op_name, delay, AbortVMOnVMOperationTimeoutDelay);
 69     }
 70   }
 71 }
 72 
 73 bool VMOperationTimeoutTask::is_armed() {

260     }
261   }
262 }
263 
264 static void post_vm_operation_event(EventExecuteVMOperation* event, VM_Operation* op) {
265   assert(event != nullptr, "invariant");
266   assert(op != nullptr, "invariant");
267   const bool evaluate_at_safepoint = op->evaluate_at_safepoint();
268   event->set_operation(op->type());
269   event->set_safepoint(evaluate_at_safepoint);
270   event->set_blocking(true);
271   event->set_caller(JFR_THREAD_ID(op->calling_thread()));
272   event->set_safepointId(evaluate_at_safepoint ? SafepointSynchronize::safepoint_id() : 0);
273   event->commit();
274 }
275 
276 void VMThread::evaluate_operation(VM_Operation* op) {
277   ResourceMark rm;
278 
279   {
280     PerfTraceElapsedTime vm_op_timer(perf_accumulated_vm_operation_time());
281     HOTSPOT_VMOPS_BEGIN(
282                      (char *) op->name(), strlen(op->name()),
283                      op->evaluate_at_safepoint() ? 0 : 1);
284 
285     EventExecuteVMOperation event;
286     op->evaluate();
287     if (event.should_commit()) {
288       post_vm_operation_event(&event, op);
289     }
290 
291     HOTSPOT_VMOPS_END(
292                      (char *) op->name(), strlen(op->name()),
293                      op->evaluate_at_safepoint() ? 0 : 1);
294   }
295 
296   if (UsePerfData && os::is_thread_cpu_time_supported()) {
297     assert(Thread::current() == this, "Must be called from VM thread");
298     // Update vm_thread_cpu_time after each VM operation.
299     ThreadTotalCPUTimeClosure tttc(CPUTimeGroups::CPUTimeType::vm);
300     tttc.do_thread(this);

525   public:
526 #ifdef ASSERT
527     SkipGCALot(Thread* t) : _t(t) {
528       _saved = _t->skip_gcalot();
529       _t->set_skip_gcalot(true);
530     }
531 
532     ~SkipGCALot() {
533       assert(_t->skip_gcalot(), "Save-restore protocol invariant");
534       _t->set_skip_gcalot(_saved);
535     }
536 #else
537     SkipGCALot(Thread* t) { }
538     ~SkipGCALot() { }
539 #endif
540 };
541 
542 void VMThread::execute(VM_Operation* op) {
543   Thread* t = Thread::current();
544 
545   PerfTraceTimedEvent p(VMThread::get_perf_timer_for(op), VMThread::get_perf_counter_for(op), \
546                         Thread::current()->profile_vm_ops()); \
547 
548   if (t->is_VM_thread()) {
549     op->set_calling_thread(t);
550     ((VMThread*)t)->inner_execute(op);
551     return;
552   }
553 
554   // Avoid re-entrant attempts to gc-a-lot
555   SkipGCALot sgcalot(t);
556 
557   // JavaThread or WatcherThread
558   if (t->is_Java_thread()) {
559     JavaThread::cast(t)->check_for_valid_safepoint_state();
560   }
561 
562   // New request from Java thread, evaluate prologue
563   if (!op->doit_prologue()) {
564     return;   // op was cancelled
565   }
566 
567   op->set_calling_thread(t);
568 
569   wait_until_executed(op);
570 
571   op->doit_epilogue();
572 }
573 
574 void VMThread::verify() {
575   oops_do(&VerifyOopClosure::verify_oop, nullptr);
576 }
577 
578 #define DECLARE_COUNTER(name) \
579 PerfTickCounters* _perf_##name##_timer = nullptr; \
580 PerfCounter*      _perf_##name##_count = nullptr;
581 
582 VM_OPS_DO(DECLARE_COUNTER)
583 
584 #undef DECLARE_COUNTER
585 
586 #define SWITCH_TIMER(name) \
587 case VM_Operation::VMOp_##name: return _perf_##name##_timer;
588 
589 PerfTickCounters* VMThread::get_perf_timer_for(VM_Operation *op) {
590   switch(op->type()) {
591     VM_OPS_DO(SWITCH_TIMER)
592     default: ShouldNotReachHere();
593   }
594 }
595 
596 #undef SWITCH_TIMER
597 
598 #define SWITCH_COUNT(name) \
599 case VM_Operation::VMOp_##name: return _perf_##name##_count;
600 
601 PerfCounter* VMThread::get_perf_counter_for(VM_Operation *op) {
602   switch(op->type()) {
603     VM_OPS_DO(SWITCH_COUNT)
604     default: ShouldNotReachHere();
605   }
606 }
607 
608 #undef SWITCH_COUNT
609 
610 #define INIT_COUNTER(name) \
611     NEWPERFTICKCOUNTERS(_perf_##name##_timer, SUN_RT, #name "_time"); \
612     NEWPERFEVENTCOUNTER(_perf_##name##_count, SUN_RT, #name "_count"); \
613 
614 void VMThread::init_counters() {
615   if (ProfileVMOps && UsePerfData) {
616     EXCEPTION_MARK;
617 
618     VM_OPS_DO(INIT_COUNTER)
619 
620     if (HAS_PENDING_EXCEPTION) {
621       vm_exit_during_initialization("jvm_perf_init failed unexpectedly");
622     }
623   }
624 }
625 
626 #undef INIT_COUNTER
627 
628 static jlong total_count() {
629   jlong total = 0;
630 #define ACC_COUNT(name) total += _perf_##name##_count->get_value();
631   VM_OPS_DO(ACC_COUNT)
632 #undef ACC_COUNT
633   return total;
634 }
635 
636 static jlong total_elapsed_time_in_ms() {
637   jlong total_elapsed_ticks = 0;
638 #define ACC_COUNT(name) total_elapsed_ticks += _perf_##name##_timer->elapsed_counter_value();
639   VM_OPS_DO(ACC_COUNT)
640 #undef ACC_COUNT
641   return Management::ticks_to_ms(total_elapsed_ticks);
642 }
643 
644 #define PRINT_COUNTER(name) {\
645   jlong count = _perf_##name##_count->get_value(); \
646   if (count > 0) { \
647     st->print_cr("  %-40s = %4ldms (%5ld events)", #name, _perf_##name##_timer->elapsed_counter_value_ms(), count); \
648   }}
649 
650 void VMThread::print_counters_on(outputStream* st) {
651   if (ProfileVMOps && UsePerfData) {
652     st->print_cr("VMOperation: Total: %ld events (elapsed %ldms) for thread \"main\":",
653                  total_count(), total_elapsed_time_in_ms());
654     VM_OPS_DO(PRINT_COUNTER)
655   } else {
656     st->print_cr("  VMOperations:  no info (%s is disabled)", (UsePerfData ? "ProfileVMCalls" : "UsePerfData"));
657   }
658 }
659 
660 #undef PRINT_COUNTER
< prev index next >