6935224: Adding new DTrace probes to work with Palantir

Adding probes related to thread scheduling and class initialization

Reviewed-by: kamg, never
This commit is contained in:
Frederic Parain 2010-03-17 11:01:05 +01:00
parent d713517a21
commit 2450ae35a1
9 changed files with 134 additions and 7 deletions

View File

@ -25,9 +25,20 @@
provider hotspot { provider hotspot {
probe class__loaded(char*, uintptr_t, void*, uintptr_t); probe class__loaded(char*, uintptr_t, void*, uintptr_t);
probe class__unloaded(char*, uintptr_t, void*, uintptr_t); probe class__unloaded(char*, uintptr_t, void*, uintptr_t);
probe class__initialization__required(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__recursive(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__concurrent(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__erroneous(char*, uintptr_t, void*, intptr_t, int);
probe class__initialization__super__failed(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__clinit(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__error(char*, uintptr_t, void*, intptr_t,int);
probe class__initialization__end(char*, uintptr_t, void*, intptr_t,int);
probe vm__init__begin(); probe vm__init__begin();
probe vm__init__end(); probe vm__init__end();
probe vm__shutdown(); probe vm__shutdown();
probe vmops__request(char*, uintptr_t, int);
probe vmops__begin(char*, uintptr_t, int);
probe vmops__end(char*, uintptr_t, int);
probe gc__begin(uintptr_t); probe gc__begin(uintptr_t);
probe gc__end(); probe gc__end();
probe mem__pool__gc__begin( probe mem__pool__gc__begin(
@ -38,6 +49,12 @@ provider hotspot {
uintptr_t, uintptr_t, uintptr_t, uintptr_t); uintptr_t, uintptr_t, uintptr_t, uintptr_t);
probe thread__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); probe thread__start(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
probe thread__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t); probe thread__stop(char*, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
probe thread__sleep__begin(long long);
probe thread__sleep__end(int);
probe thread__yield();
probe thread__park__begin(uintptr_t, int, long long);
probe thread__park__end(uintptr_t);
probe thread__unpark(uintptr_t);
probe method__compile__begin( probe method__compile__begin(
char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, char*, uintptr_t); char*, uintptr_t, char*, uintptr_t, char*, uintptr_t, char*, uintptr_t);
probe method__compile__end( probe method__compile__end(

View File

@ -668,13 +668,18 @@ jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
} }
} }
if (strcmp(name, "ExtendedDTraceProbes") != 0) { if (strcmp(name, "ExtendedDTraceProbes") == 0) {
out->print_cr("flag '%s' cannot be changed", name); DTrace::set_extended_dprobes(flag);
return JNI_ERR; return JNI_OK;
} }
DTrace::set_extended_dprobes(flag); if (strcmp(name, "DTraceMonitorProbes") == 0) {
return JNI_OK; DTrace::set_monitor_dprobes(flag);
return JNI_OK;
}
out->print_cr("flag '%s' cannot be changed", name);
return JNI_ERR;
} }
void AttachListener::pd_detachall() { void AttachListener::pd_detachall() {

View File

@ -2024,6 +2024,7 @@ init.hpp top.hpp
instanceKlass.cpp collectedHeap.inline.hpp instanceKlass.cpp collectedHeap.inline.hpp
instanceKlass.cpp compileBroker.hpp instanceKlass.cpp compileBroker.hpp
instanceKlass.cpp dtrace.hpp
instanceKlass.cpp fieldDescriptor.hpp instanceKlass.cpp fieldDescriptor.hpp
instanceKlass.cpp genOopClosures.inline.hpp instanceKlass.cpp genOopClosures.inline.hpp
instanceKlass.cpp handles.inline.hpp instanceKlass.cpp handles.inline.hpp
@ -2483,6 +2484,7 @@ jvm.cpp classLoader.hpp
jvm.cpp collectedHeap.inline.hpp jvm.cpp collectedHeap.inline.hpp
jvm.cpp copy.hpp jvm.cpp copy.hpp
jvm.cpp defaultStream.hpp jvm.cpp defaultStream.hpp
jvm.cpp dtrace.hpp
jvm.cpp dtraceJSDT.hpp jvm.cpp dtraceJSDT.hpp
jvm.cpp events.hpp jvm.cpp events.hpp
jvm.cpp handles.inline.hpp jvm.cpp handles.inline.hpp
@ -4449,6 +4451,7 @@ universe.inline.hpp universe.hpp
unsafe.cpp allocation.inline.hpp unsafe.cpp allocation.inline.hpp
unsafe.cpp copy.hpp unsafe.cpp copy.hpp
unsafe.cpp dtrace.hpp
unsafe.cpp globals.hpp unsafe.cpp globals.hpp
unsafe.cpp interfaceSupport.hpp unsafe.cpp interfaceSupport.hpp
unsafe.cpp jni.h unsafe.cpp jni.h
@ -4620,6 +4623,7 @@ vmSymbols.hpp symbolOop.hpp
vmThread.cpp collectedHeap.hpp vmThread.cpp collectedHeap.hpp
vmThread.cpp compileBroker.hpp vmThread.cpp compileBroker.hpp
vmThread.cpp dtrace.hpp
vmThread.cpp events.hpp vmThread.cpp events.hpp
vmThread.cpp interfaceSupport.hpp vmThread.cpp interfaceSupport.hpp
vmThread.cpp methodOop.hpp vmThread.cpp methodOop.hpp

View File

@ -25,6 +25,58 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_instanceKlass.cpp.incl" # include "incls/_instanceKlass.cpp.incl"
#ifdef DTRACE_ENABLED
HS_DTRACE_PROBE_DECL4(hotspot, class__initialization__required,
char*, intptr_t, oop, intptr_t);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__recursive,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__concurrent,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__erroneous,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__super__failed,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__clinit,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__error,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
char*, intptr_t, oop, intptr_t, int);
#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \
{ \
char* data = NULL; \
int len = 0; \
symbolOop name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HS_DTRACE_PROBE4(hotspot, class__initialization__##type, \
data, len, (clss)->class_loader(), thread_type); \
}
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
{ \
char* data = NULL; \
int len = 0; \
symbolOop name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \
data, len, (clss)->class_loader(), thread_type, wait); \
}
#else // ndef DTRACE_ENABLED
#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type)
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait)
#endif // ndef DTRACE_ENABLED
bool instanceKlass::should_be_initialized() const { bool instanceKlass::should_be_initialized() const {
return !is_initialized(); return !is_initialized();
} }
@ -292,6 +344,10 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
// A class could already be verified, since it has been reflected upon. // A class could already be verified, since it has been reflected upon.
this_oop->link_class(CHECK); this_oop->link_class(CHECK);
DTRACE_CLASSINIT_PROBE(required, instanceKlass::cast(this_oop()), -1);
bool wait = false;
// refer to the JVM book page 47 for description of steps // refer to the JVM book page 47 for description of steps
// Step 1 // Step 1
{ ObjectLocker ol(this_oop, THREAD); { ObjectLocker ol(this_oop, THREAD);
@ -303,19 +359,25 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
// we might end up throwing IE from link/symbol resolution sites // we might end up throwing IE from link/symbol resolution sites
// that aren't expected to throw. This would wreak havoc. See 6320309. // that aren't expected to throw. This would wreak havoc. See 6320309.
while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) { while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK); ol.waitUninterruptibly(CHECK);
} }
// Step 3 // Step 3
if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
DTRACE_CLASSINIT_PROBE_WAIT(recursive, instanceKlass::cast(this_oop()), -1,wait);
return; return;
}
// Step 4 // Step 4
if (this_oop->is_initialized()) if (this_oop->is_initialized()) {
DTRACE_CLASSINIT_PROBE_WAIT(concurrent, instanceKlass::cast(this_oop()), -1,wait);
return; return;
}
// Step 5 // Step 5
if (this_oop->is_in_error_state()) { if (this_oop->is_in_error_state()) {
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, instanceKlass::cast(this_oop()), -1,wait);
ResourceMark rm(THREAD); ResourceMark rm(THREAD);
const char* desc = "Could not initialize class "; const char* desc = "Could not initialize class ";
const char* className = this_oop->external_name(); const char* className = this_oop->external_name();
@ -348,6 +410,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads this_oop->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below
} }
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, instanceKlass::cast(this_oop()), -1,wait);
THROW_OOP(e()); THROW_OOP(e());
} }
} }
@ -356,6 +419,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
{ {
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl"); assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD; JavaThread* jt = (JavaThread*)THREAD;
DTRACE_CLASSINIT_PROBE_WAIT(clinit, instanceKlass::cast(this_oop()), -1,wait);
// Timer includes any side effects of class initialization (resolution, // Timer includes any side effects of class initialization (resolution,
// etc), but not recursive entry into call_class_initializer(). // etc), but not recursive entry into call_class_initializer().
PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
@ -383,6 +447,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
this_oop->set_initialization_state_and_notify(initialization_error, THREAD); this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
} }
DTRACE_CLASSINIT_PROBE_WAIT(error, instanceKlass::cast(this_oop()), -1,wait);
if (e->is_a(SystemDictionary::Error_klass())) { if (e->is_a(SystemDictionary::Error_klass())) {
THROW_OOP(e()); THROW_OOP(e());
} else { } else {
@ -392,6 +457,7 @@ void instanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
&args); &args);
} }
} }
DTRACE_CLASSINIT_PROBE_WAIT(end, instanceKlass::cast(this_oop()), -1,wait);
} }

View File

@ -26,6 +26,10 @@
#include "incls/_jvm.cpp.incl" #include "incls/_jvm.cpp.incl"
#include <errno.h> #include <errno.h>
HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__begin, long long);
HS_DTRACE_PROBE_DECL1(hotspot, thread__sleep__end, int);
HS_DTRACE_PROBE_DECL0(hotspot, thread__yield);
/* /*
NOTE about use of any ctor or function call that can trigger a safepoint/GC: NOTE about use of any ctor or function call that can trigger a safepoint/GC:
such ctors and calls MUST NOT come between an oop declaration/init and its such ctors and calls MUST NOT come between an oop declaration/init and its
@ -2762,6 +2766,7 @@ JVM_END
JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass)) JVM_ENTRY(void, JVM_Yield(JNIEnv *env, jclass threadClass))
JVMWrapper("JVM_Yield"); JVMWrapper("JVM_Yield");
if (os::dont_yield()) return; if (os::dont_yield()) return;
HS_DTRACE_PROBE0(hotspot, thread__yield);
// When ConvertYieldToSleep is off (default), this matches the classic VM use of yield. // When ConvertYieldToSleep is off (default), this matches the classic VM use of yield.
// Critical for similar threading behaviour // Critical for similar threading behaviour
if (ConvertYieldToSleep) { if (ConvertYieldToSleep) {
@ -2787,6 +2792,8 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
// And set new thread state to SLEEPING. // And set new thread state to SLEEPING.
JavaThreadSleepState jtss(thread); JavaThreadSleepState jtss(thread);
HS_DTRACE_PROBE1(hotspot, thread__sleep__begin, millis);
if (millis == 0) { if (millis == 0) {
// When ConvertSleepToYield is on, this matches the classic VM implementation of // When ConvertSleepToYield is on, this matches the classic VM implementation of
// JVM_Sleep. Critical for similar threading behaviour (Win32) // JVM_Sleep. Critical for similar threading behaviour (Win32)
@ -2807,6 +2814,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
// An asynchronous exception (e.g., ThreadDeathException) could have been thrown on // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
// us while we were sleeping. We do not overwrite those. // us while we were sleeping. We do not overwrite those.
if (!HAS_PENDING_EXCEPTION) { if (!HAS_PENDING_EXCEPTION) {
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,1);
// TODO-FIXME: THROW_MSG returns which means we will not call set_state() // TODO-FIXME: THROW_MSG returns which means we will not call set_state()
// to properly restore the thread state. That's likely wrong. // to properly restore the thread state. That's likely wrong.
THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted"); THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
@ -2814,6 +2822,7 @@ JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
} }
thread->osthread()->set_state(old_state); thread->osthread()->set_state(old_state);
} }
HS_DTRACE_PROBE1(hotspot, thread__sleep__end,0);
JVM_END JVM_END
JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass)) JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))

View File

@ -29,6 +29,10 @@
#include "incls/_precompiled.incl" #include "incls/_precompiled.incl"
#include "incls/_unsafe.cpp.incl" #include "incls/_unsafe.cpp.incl"
HS_DTRACE_PROBE_DECL3(hotspot, thread__park__begin, uintptr_t, int, long long);
HS_DTRACE_PROBE_DECL1(hotspot, thread__park__end, uintptr_t);
HS_DTRACE_PROBE_DECL1(hotspot, thread__unpark, uintptr_t);
#define MAX_OBJECT_SIZE \ #define MAX_OBJECT_SIZE \
( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \ ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \
+ ((julong)max_jint * sizeof(double)) ) + ((julong)max_jint * sizeof(double)) )
@ -1083,8 +1087,10 @@ UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
UnsafeWrapper("Unsafe_Park"); UnsafeWrapper("Unsafe_Park");
HS_DTRACE_PROBE3(hotspot, thread__park__begin, thread->parker(), (int) isAbsolute, time);
JavaThreadParkedState jtps(thread, time != 0); JavaThreadParkedState jtps(thread, time != 0);
thread->parker()->park(isAbsolute != 0, time); thread->parker()->park(isAbsolute != 0, time);
HS_DTRACE_PROBE1(hotspot, thread__park__end, thread->parker());
UNSAFE_END UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
@ -1116,6 +1122,7 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
} }
} }
if (p != NULL) { if (p != NULL) {
HS_DTRACE_PROBE1(hotspot, thread__unpark, p);
p->unpark(); p->unpark();
} }
UNSAFE_END UNSAFE_END

View File

@ -25,6 +25,10 @@
# include "incls/_precompiled.incl" # include "incls/_precompiled.incl"
# include "incls/_vmThread.cpp.incl" # include "incls/_vmThread.cpp.incl"
HS_DTRACE_PROBE_DECL3(hotspot, vmops__request, char *, uintptr_t, int);
HS_DTRACE_PROBE_DECL3(hotspot, vmops__begin, char *, uintptr_t, int);
HS_DTRACE_PROBE_DECL3(hotspot, vmops__end, char *, uintptr_t, int);
// Dummy VM operation to act as first element in our circular double-linked list // Dummy VM operation to act as first element in our circular double-linked list
class VM_Dummy: public VM_Operation { class VM_Dummy: public VM_Operation {
VMOp_Type type() const { return VMOp_Dummy; } VMOp_Type type() const { return VMOp_Dummy; }
@ -132,6 +136,10 @@ void VMOperationQueue::drain_list_oops_do(OopClosure* f) {
//----------------------------------------------------------------- //-----------------------------------------------------------------
// High-level interface // High-level interface
bool VMOperationQueue::add(VM_Operation *op) { bool VMOperationQueue::add(VM_Operation *op) {
HS_DTRACE_PROBE3(hotspot, vmops__request, op->name(), strlen(op->name()),
op->evaluation_mode());
// Encapsulates VM queue policy. Currently, that // Encapsulates VM queue policy. Currently, that
// only involves putting them on the right list // only involves putting them on the right list
if (op->evaluate_at_safepoint()) { if (op->evaluate_at_safepoint()) {
@ -325,7 +333,11 @@ void VMThread::evaluate_operation(VM_Operation* op) {
{ {
PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time()); PerfTraceTime vm_op_timer(perf_accumulated_vm_operation_time());
HS_DTRACE_PROBE3(hotspot, vmops__begin, op->name(), strlen(op->name()),
op->evaluation_mode());
op->evaluate(); op->evaluate();
HS_DTRACE_PROBE3(hotspot, vmops__end, op->name(), strlen(op->name()),
op->evaluation_mode());
} }
// Last access of info in _cur_vm_operation! // Last access of info in _cur_vm_operation!

View File

@ -135,4 +135,9 @@ void DTrace::set_extended_dprobes(bool flag) {
} }
} }
void DTrace::set_monitor_dprobes(bool flag) {
// explicit setting of DTraceMonitorProbes flag
set_bool_flag("DTraceMonitorProbes", flag);
}
#endif /* SOLARIS */ #endif /* SOLARIS */

View File

@ -41,4 +41,6 @@ class DTrace : public AllStatic {
static void detach_all_clients(); static void detach_all_clients();
// set ExtendedDTraceProbes flag // set ExtendedDTraceProbes flag
static void set_extended_dprobes(bool value); static void set_extended_dprobes(bool value);
// set DTraceMonitorProbes flag
static void set_monitor_dprobes(bool value);
}; };