提交 0219cd98 编写于 作者: J joeylee.lz 提交者: joeyleeeeeee97

[Wisp] Support threadMxbean in AllThreadAsWisp

Summary: Now we can use ThreadMxBean to inspect coroutine infomation.

Test Plan: Support ThreadMxBean to inspect coroutine infomation,
including getThreadInfo, dumpAllThreads,getThreadCount, getAllThreadIds.

Reviewed-by: zhengxiaolinX, yuleil, sanhongli

Issue: https://github.com/alibaba/dragonwell8/issues/132
上级 92cfe745
......@@ -1503,17 +1503,6 @@ JVM_ENTRY(jboolean, CoroutineSupport_stealCoroutine(JNIEnv* env, jclass klass, j
return true;
JVM_END
JVM_ENTRY (jobjectArray, CoroutineSupport_getCoroutineStack(JNIEnv* env, jclass klass, jlong coroPtr))
assert(EnableCoroutine, "pre-condition");
JvmtiVMObjectAllocEventCollector oam;
Coroutine* coro = (Coroutine*)coroPtr;
Handle stacktraces = ThreadService::dump_coroutine_stack_trace(coro, CHECK_NULL);
return (jobjectArray)JNIHandles::make_local(env, stacktraces());
JVM_END
JVM_ENTRY (void, CoroutineSupport_checkAndThrowException0(JNIEnv* env, jclass klass, jlong coroPtr))
assert(EnableCoroutine, "pre-condition");
Coroutine* coro = (Coroutine*)coroPtr;
......@@ -1880,7 +1869,6 @@ JNINativeMethod coroutine_support_methods[] = {
{CC"getNextCoroutine", CC"(J)"COR, FN_PTR(CoroutineSupport_getNextCoroutine)},
{CC"moveCoroutine", CC"(JJ)V", FN_PTR(CoroutineSupport_moveCoroutine)},
{CC"markThreadCoroutine", CC"(J"COBA")V", FN_PTR(CoroutineSupport_markThreadCoroutine)},
{CC"getCoroutineStack", CC"(J)["STE, FN_PTR(CoroutineSupport_getCoroutineStack)},
{CC"checkAndThrowException0", CC"(J)V", FN_PTR(CoroutineSupport_checkAndThrowException0)},
};
......
......@@ -4299,6 +4299,20 @@ JavaThread* Threads::find_java_thread_from_java_tid(jlong java_tid) {
java_thread = thread;
break;
}
if (EnableCoroutine) {
for (Coroutine* co = thread->coroutine_list()->next();
co != thread->coroutine_list(); co = co->next()) {
oop wtObj = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// wtObj == 0 means coroutine is cached
if (!thread->is_exiting() &&
wtObj != NULL &&
java_tid == java_lang_Thread::thread_id(wtObj)) {
co->wisp_thread()->set_threadObj(wtObj);
return co->wisp_thread();
}
}
}
}
return java_thread;
}
......
......@@ -323,6 +323,25 @@ void VM_ThreadDump::doit() {
}
ThreadSnapshot* ts = snapshot_thread(jt, tcl);
_result->add_thread_snapshot(ts);
if (EnableCoroutine) {
for (Coroutine* co = jt->coroutine_list()->next();
co != jt->coroutine_list(); co = co->next()) {
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw == NULL) {
continue;
}
co->wisp_thread()->set_threadObj(tw);
ThreadConcurrentLocks* wtcl = NULL;
if (_with_locked_synchronizers) {
wtcl = concurrent_locks.thread_concurrent_locks(co->wisp_thread());
}
ThreadSnapshot* wts = snapshot_coroutine(co, wtcl);
_result->add_thread_snapshot(wts);
}
}
}
} else {
// Snapshot threads in the given _threads array
......@@ -336,6 +355,29 @@ void VM_ThreadDump::doit() {
continue;
}
if (EnableCoroutine) {
jlong id = java_lang_Thread::thread_id(th());
// this would traverse thread's coroutine list
JavaThread* jt = Threads::find_java_thread_from_java_tid(id);
if (jt->is_Wisp_thread()) {
Coroutine* co = ((WispThread*)jt)->coroutine();
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw == NULL) {
continue;
}
co->wisp_thread()->set_threadObj(tw);
ThreadConcurrentLocks* wtcl = NULL;
if (_with_locked_synchronizers) {
wtcl = concurrent_locks.thread_concurrent_locks(co->wisp_thread());
}
ThreadSnapshot* wts = snapshot_coroutine(co, wtcl);
_result->add_thread_snapshot(wts);
return;
}
}
// Dump thread stack only if the thread is alive and not exiting
// and not VM internal thread.
JavaThread* jt = java_lang_Thread::thread(th());
......@@ -363,33 +405,13 @@ ThreadSnapshot* VM_ThreadDump::snapshot_thread(JavaThread* java_thread, ThreadCo
return snapshot;
}
ThreadSnapshot* VM_CoroutineDump::snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl) {
ThreadSnapshot* snapshot = new ThreadSnapshot(java_thread);
snapshot->dump_stack_at_safepoint_for_coroutine(_target);
ThreadSnapshot* VM_ThreadDump::snapshot_coroutine(Coroutine* coro, ThreadConcurrentLocks* tcl) {
ThreadSnapshot* snapshot = new ThreadSnapshot(coro->wisp_thread());
snapshot->dump_stack_at_safepoint_for_coroutine(coro, _max_depth, _with_locked_monitors);
snapshot->set_concurrent_locks(tcl);
return snapshot;
}
VM_CoroutineDump::VM_CoroutineDump(ThreadDumpResult* result, Coroutine *target) {
assert(EnableCoroutine, "coroutine enabled");
_result = result;
_target = target;
}
bool VM_CoroutineDump::doit_prologue() {
assert(EnableCoroutine && Thread::current()->is_Java_thread(), "just checking");
return true;
}
void VM_CoroutineDump::doit_epilogue() {}
void VM_CoroutineDump::doit() {
ResourceMark rm;
ThreadSnapshot* ts = snapshot_thread(_target->thread(), NULL);
_result->add_thread_snapshot(ts);
}
volatile bool VM_Exit::_vm_exited = false;
Thread * VM_Exit::_shutdown_thread = NULL;
......
......@@ -42,7 +42,6 @@
template(Dummy) \
template(ThreadStop) \
template(ThreadDump) \
template(CoroutineDump) \
template(PrintThreads) \
template(FindDeadlocks) \
template(ForceSafepoint) \
......@@ -361,6 +360,7 @@ class VM_ThreadDump : public VM_Operation {
bool _with_locked_synchronizers;
ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
ThreadSnapshot* snapshot_coroutine(Coroutine* coro, ThreadConcurrentLocks* tcl);
public:
VM_ThreadDump(ThreadDumpResult* result,
......@@ -381,23 +381,6 @@ class VM_ThreadDump : public VM_Operation {
void doit_epilogue();
};
class VM_CoroutineDump : public VM_Operation {
private:
ThreadDumpResult* _result;
Coroutine * _target;
ThreadSnapshot* snapshot_thread(JavaThread* java_thread, ThreadConcurrentLocks* tcl);
public:
VM_CoroutineDump(ThreadDumpResult* result, Coroutine *target);
VMOp_Type type() const { return VMOp_CoroutineDump; }
void doit();
bool doit_prologue();
void doit_epilogue();
};
class VM_Exit: public VM_Operation {
private:
int _exit_code;
......
......@@ -37,6 +37,7 @@
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
#include "services/threadService.hpp"
#include "runtime/coroutine.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
......@@ -281,31 +282,6 @@ Handle ThreadService::dump_stack_traces(GrowableArray<instanceHandle>* threads,
return result_obj;
}
// Dump stack trace of Coroutine and return StackTraceElement[].
Handle ThreadService::dump_coroutine_stack_trace(Coroutine *coro, TRAPS) {
assert(EnableCoroutine, "coroutine enabled");
ThreadDumpResult dump_result;
VM_CoroutineDump op(&dump_result, coro);
VMThread::execute(&op);
// Allocate the resulting StackTraceElement[] object
ResourceMark rm(THREAD);
assert(dump_result.num_snapshots() == 1, "must only one stacktrace");
ThreadStackTrace* stacktrace = dump_result.snapshots()->get_stack_trace();
Handle stacktrace_h;
if (stacktrace == NULL) {
// No stack trace
stacktrace_h = Handle();
} else {
// Construct an array of java/lang/StackTraceElement object
stacktrace_h = stacktrace->allocate_fill_stack_trace_element_array(CHECK_NH);
}
return stacktrace_h;
}
void ThreadService::reset_contention_count_stat(JavaThread* thread) {
ThreadStatistics* stat = thread->get_thread_stat();
......@@ -655,7 +631,7 @@ void ThreadStackTrace::add_stack_frame(javaVFrame* jvf) {
_depth++;
}
void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target) {
void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth) {
assert(SafepointSynchronize::is_at_safepoint(), "all threads are stopped");
Coroutine::CoroutineState state = target->state();
......@@ -681,12 +657,18 @@ void ThreadStackTrace::dump_stack_at_safepoint_for_coroutine(Coroutine *target)
}
}
int count = 0;
while (vf) {
if (vf->is_java_frame()) {
javaVFrame* jvf = javaVFrame::cast(vf);
add_stack_frame(jvf);
count++;
}
vf = vf->sender();
if (max_depth > 0 && count == max_depth) {
// Skip frames if more than maxDepth
break;
}
}
}
......@@ -900,9 +882,9 @@ void ThreadSnapshot::dump_stack_at_safepoint(int max_depth, bool with_locked_mon
_stack_trace->dump_stack_at_safepoint(max_depth);
}
void ThreadSnapshot::dump_stack_at_safepoint_for_coroutine(Coroutine *target) {
_stack_trace = new ThreadStackTrace(_thread, false);
_stack_trace->dump_stack_at_safepoint_for_coroutine(target);
void ThreadSnapshot::dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth, bool with_locked_monitors) {
_stack_trace = new ThreadStackTrace(_thread, with_locked_monitors);
_stack_trace->dump_stack_at_safepoint_for_coroutine(target, max_depth);
}
......@@ -1016,6 +998,27 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,
MutexLockerEx ml(Threads_lock);
for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
if (!ThreadsListEnumerator::skipThread(jt, include_jvmti_agent_threads, include_jni_attaching_threads)) {
instanceHandle h(cur_thread, (instanceOop) jt->threadObj());
_threads_array->append(h);
}
if (EnableCoroutine) {
for (Coroutine* co = jt->coroutine_list()->next(); co != jt->coroutine_list(); co = co->next()) {
if (!ThreadsListEnumerator::skipThread(co->thread(), include_jvmti_agent_threads, include_jni_attaching_threads)) {
oop tw = com_alibaba_wisp_engine_WispTask::get_threadWrapper(co->wisp_task());
// skip exited wisp threads
if (tw != NULL) {
instanceHandle hc(cur_thread, (instanceOop) tw);
_threads_array->append(hc);
}
}
}
}
}
}
bool ThreadsListEnumerator::skipThread(JavaThread* jt, bool include_jvmti_agent_threads, bool include_jni_attaching_threads) {
// skips JavaThreads in the process of exiting
// and also skips VM internal JavaThreads
// Threads in _thread_new or _thread_new_trans state are included.
......@@ -1024,20 +1027,18 @@ ThreadsListEnumerator::ThreadsListEnumerator(Thread* cur_thread,
jt->is_exiting() ||
!java_lang_Thread::is_alive(jt->threadObj()) ||
jt->is_hidden_from_external_view()) {
continue;
return true;
}
// skip agent threads
if (!include_jvmti_agent_threads && jt->is_jvmti_agent_thread()) {
continue;
return true;
}
// skip jni threads in the process of attaching
if (!include_jni_attaching_threads && jt->is_attaching_via_jni()) {
continue;
return true;
}
instanceHandle h(cur_thread, (instanceOop) jt->threadObj());
_threads_array->append(h);
}
return false;
}
......@@ -105,8 +105,6 @@ public:
static Handle dump_stack_traces(GrowableArray<instanceHandle>* threads,
int num_threads, TRAPS);
static Handle dump_coroutine_stack_trace(Coroutine *coro, TRAPS);
static void reset_peak_thread_count();
static void reset_contention_count_stat(JavaThread* thread);
static void reset_contention_time_stat(JavaThread* thread);
......@@ -243,7 +241,7 @@ public:
ThreadConcurrentLocks* get_concurrent_locks() { return _concurrent_locks; }
void dump_stack_at_safepoint(int max_depth, bool with_locked_monitors);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth, bool with_locked_monitors);
void set_concurrent_locks(ThreadConcurrentLocks* l) { _concurrent_locks = l; }
void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*));
......@@ -268,7 +266,7 @@ class ThreadStackTrace : public CHeapObj<mtInternal> {
void add_stack_frame(javaVFrame* jvf);
void dump_stack_at_safepoint(int max_depth);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target);
void dump_stack_at_safepoint_for_coroutine(Coroutine *target, int max_depth);
Handle allocate_fill_stack_trace_element_array(TRAPS);
void oops_do(OopClosure* f);
void metadata_do(void f(Metadata*));
......@@ -392,6 +390,7 @@ class DeadlockCycle : public CHeapObj<mtInternal> {
class ThreadsListEnumerator : public StackObj {
private:
GrowableArray<instanceHandle>* _threads_array;
static bool skipThread(JavaThread* jt, bool include_jvmti_agent_threads, bool include_jni_attaching_threads);
public:
ThreadsListEnumerator(Thread* cur_thread,
bool include_jvmti_agent_threads = false,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册