40 #include "oops/objArrayOop.inline.hpp" |
39 #include "oops/objArrayOop.inline.hpp" |
41 #include "runtime/handles.inline.hpp" |
40 #include "runtime/handles.inline.hpp" |
42 #include "runtime/fieldDescriptor.inline.hpp" |
41 #include "runtime/fieldDescriptor.inline.hpp" |
43 #include "runtime/java.hpp" |
42 #include "runtime/java.hpp" |
44 #include "runtime/jniHandles.inline.hpp" |
43 #include "runtime/jniHandles.inline.hpp" |
|
44 #include "runtime/semaphore.inline.hpp" |
45 #include "runtime/synchronizer.hpp" |
45 #include "runtime/synchronizer.hpp" |
46 #include "runtime/thread.inline.hpp" |
46 #include "runtime/thread.inline.hpp" |
47 #include "runtime/threadSMR.hpp" |
47 #include "runtime/threadSMR.hpp" |
|
48 #include "utilities/growableArray.hpp" |
48 |
49 |
49 #ifdef ASSERT |
50 #ifdef ASSERT |
50 void JfrJavaSupport::check_java_thread_in_vm(Thread* t) { |
51 void JfrJavaSupport::check_java_thread_in_vm(Thread* t) { |
51 assert(t != NULL, "invariant"); |
52 assert(t != NULL, "invariant"); |
52 assert(t->is_Java_thread(), "invariant"); |
53 assert(t->is_Java_thread(), "invariant"); |
89 return obj == NULL ? NULL : global_jni_handle(obj, t); |
96 return obj == NULL ? NULL : global_jni_handle(obj, t); |
90 } |
97 } |
91 |
98 |
92 void JfrJavaSupport::destroy_global_jni_handle(jobject handle) { |
99 void JfrJavaSupport::destroy_global_jni_handle(jobject handle) { |
93 JNIHandles::destroy_global(handle); |
100 JNIHandles::destroy_global(handle); |
|
101 } |
|
102 |
|
103 jweak JfrJavaSupport::global_weak_jni_handle(const oop obj, Thread* t) { |
|
104 DEBUG_ONLY(check_java_thread_in_vm(t)); |
|
105 HandleMark hm(t); |
|
106 return JNIHandles::make_weak_global(Handle(t, obj)); |
|
107 } |
|
108 |
|
109 jweak JfrJavaSupport::global_weak_jni_handle(const jobject handle, Thread* t) { |
|
110 const oop obj = JNIHandles::resolve(handle); |
|
111 return obj == NULL ? NULL : global_weak_jni_handle(obj, t); |
|
112 } |
|
113 |
|
114 void JfrJavaSupport::destroy_global_weak_jni_handle(jweak handle) { |
|
115 JNIHandles::destroy_weak_global(handle); |
94 } |
116 } |
95 |
117 |
96 oop JfrJavaSupport::resolve_non_null(jobject obj) { |
118 oop JfrJavaSupport::resolve_non_null(jobject obj) { |
97 return JNIHandles::resolve_non_null(obj); |
119 return JNIHandles::resolve_non_null(obj); |
98 } |
120 } |
601 return false; |
623 return false; |
602 } |
624 } |
603 return true; |
625 return true; |
604 } |
626 } |
605 |
627 |
606 jlong JfrJavaSupport::jfr_thread_id(jobject target_thread) { |
628 class ThreadExclusionListAccess : public StackObj { |
|
629 private: |
|
630 static Semaphore _mutex_semaphore; |
|
631 public: |
|
632 ThreadExclusionListAccess() { _mutex_semaphore.wait(); } |
|
633 ~ThreadExclusionListAccess() { _mutex_semaphore.signal(); } |
|
634 }; |
|
635 |
|
636 Semaphore ThreadExclusionListAccess::_mutex_semaphore(1); |
|
637 static GrowableArray<jweak>* exclusion_list = NULL; |
|
638 |
|
639 static bool equals(const jweak excluded_thread, Handle target_thread) { |
|
640 return JfrJavaSupport::resolve_non_null(excluded_thread) == target_thread(); |
|
641 } |
|
642 |
|
643 static int find_exclusion_thread_idx(Handle thread) { |
|
644 if (exclusion_list != NULL) { |
|
645 for (int i = 0; i < exclusion_list->length(); ++i) { |
|
646 if (equals(exclusion_list->at(i), thread)) { |
|
647 return i; |
|
648 } |
|
649 } |
|
650 } |
|
651 return -1; |
|
652 } |
|
653 |
|
654 static Handle as_handle(jobject thread) { |
|
655 return Handle(Thread::current(), JfrJavaSupport::resolve_non_null(thread)); |
|
656 } |
|
657 |
|
658 static bool thread_is_not_excluded(Handle thread) { |
|
659 return -1 == find_exclusion_thread_idx(thread); |
|
660 } |
|
661 |
|
662 static bool thread_is_not_excluded(jobject thread) { |
|
663 return thread_is_not_excluded(as_handle(thread)); |
|
664 } |
|
665 |
|
666 static bool is_thread_excluded(jobject thread) { |
|
667 return !thread_is_not_excluded(thread); |
|
668 } |
|
669 |
|
670 #ifdef ASSERT |
|
671 static bool is_thread_excluded(Handle thread) { |
|
672 return !thread_is_not_excluded(thread); |
|
673 } |
|
674 #endif // ASSERT |
|
675 |
|
676 static int add_thread_to_exclusion_list(jobject thread) { |
|
677 ThreadExclusionListAccess lock; |
|
678 if (exclusion_list == NULL) { |
|
679 exclusion_list = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<jweak>(10, true, mtTracing); |
|
680 } |
|
681 assert(exclusion_list != NULL, "invariant"); |
|
682 assert(thread_is_not_excluded(thread), "invariant"); |
|
683 jweak ref = JfrJavaSupport::global_weak_jni_handle(thread, Thread::current()); |
|
684 const int idx = exclusion_list->append(ref); |
|
685 assert(is_thread_excluded(thread), "invariant"); |
|
686 return idx; |
|
687 } |
|
688 |
|
689 static void remove_thread_from_exclusion_list(Handle thread) { |
|
690 assert(exclusion_list != NULL, "invariant"); |
|
691 assert(is_thread_excluded(thread), "invariant"); |
|
692 assert(exclusion_list != NULL, "invariant"); |
|
693 const int idx = find_exclusion_thread_idx(thread); |
|
694 assert(idx >= 0, "invariant"); |
|
695 assert(idx < exclusion_list->length(), "invariant"); |
|
696 JfrJavaSupport::destroy_global_weak_jni_handle(exclusion_list->at(idx)); |
|
697 exclusion_list->delete_at(idx); |
|
698 assert(thread_is_not_excluded(thread), "invariant"); |
|
699 if (0 == exclusion_list->length()) { |
|
700 delete exclusion_list; |
|
701 exclusion_list = NULL; |
|
702 } |
|
703 } |
|
704 |
|
705 static void remove_thread_from_exclusion_list(jobject thread) { |
|
706 ThreadExclusionListAccess lock; |
|
707 remove_thread_from_exclusion_list(as_handle(thread)); |
|
708 } |
|
709 |
|
710 // includes removal |
|
711 static bool check_exclusion_state_on_thread_start(JavaThread* jt) { |
|
712 Handle h_obj(jt, jt->threadObj()); |
|
713 ThreadExclusionListAccess lock; |
|
714 if (thread_is_not_excluded(h_obj)) { |
|
715 return false; |
|
716 } |
|
717 remove_thread_from_exclusion_list(h_obj); |
|
718 return true; |
|
719 } |
|
720 |
|
721 jlong JfrJavaSupport::jfr_thread_id(jobject thread) { |
607 ThreadsListHandle tlh; |
722 ThreadsListHandle tlh; |
608 JavaThread* native_thread = NULL; |
723 JavaThread* native_thread = NULL; |
609 (void)tlh.cv_internal_thread_to_JavaThread(target_thread, &native_thread, NULL); |
724 (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL); |
610 return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0; |
725 return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0; |
611 } |
726 } |
|
727 |
|
728 void JfrJavaSupport::exclude(jobject thread) { |
|
729 HandleMark hm; |
|
730 ThreadsListHandle tlh; |
|
731 JavaThread* native_thread = NULL; |
|
732 (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL); |
|
733 if (native_thread != NULL) { |
|
734 JfrThreadLocal::exclude(native_thread); |
|
735 } else { |
|
736 // not started yet, track the thread oop |
|
737 add_thread_to_exclusion_list(thread); |
|
738 } |
|
739 } |
|
740 |
|
741 void JfrJavaSupport::include(jobject thread) { |
|
742 HandleMark hm; |
|
743 ThreadsListHandle tlh; |
|
744 JavaThread* native_thread = NULL; |
|
745 (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL); |
|
746 if (native_thread != NULL) { |
|
747 JfrThreadLocal::include(native_thread); |
|
748 } else { |
|
749 // not started yet, untrack the thread oop |
|
750 remove_thread_from_exclusion_list(thread); |
|
751 } |
|
752 } |
|
753 |
|
754 bool JfrJavaSupport::is_excluded(jobject thread) { |
|
755 HandleMark hm; |
|
756 ThreadsListHandle tlh; |
|
757 JavaThread* native_thread = NULL; |
|
758 (void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL); |
|
759 return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread); |
|
760 } |
|
761 |
|
762 void JfrJavaSupport::on_thread_start(Thread* t) { |
|
763 assert(t != NULL, "invariant"); |
|
764 assert(Thread::current() == t, "invariant"); |
|
765 if (!t->is_Java_thread()) { |
|
766 return; |
|
767 } |
|
768 DEBUG_ONLY(check_new_unstarted_java_thread(t);) |
|
769 HandleMark hm; |
|
770 if (check_exclusion_state_on_thread_start((JavaThread*)t)) { |
|
771 JfrThreadLocal::exclude(t); |
|
772 } |
|
773 } |