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