--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp Mon Jun 04 07:12:26 2018 +0200
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp Mon Jun 04 12:51:24 2018 +0200
@@ -44,46 +44,48 @@
NATIVE_SAMPLE = 2
};
-static bool in_java_sample(JavaThread* thread) {
- switch (thread->thread_state()) {
- case _thread_new:
- case _thread_uninitialized:
- case _thread_new_trans:
- case _thread_in_vm_trans:
- case _thread_blocked_trans:
- case _thread_in_native_trans:
- case _thread_blocked:
- case _thread_in_vm:
- case _thread_in_native:
- case _thread_in_Java_trans:
- break;
- case _thread_in_Java:
- return true;
- default:
- ShouldNotReachHere();
- break;
+static bool thread_state_in_java(JavaThread* thread) {
+ assert(thread != NULL, "invariant");
+ switch(thread->thread_state()) {
+ case _thread_new:
+ case _thread_uninitialized:
+ case _thread_new_trans:
+ case _thread_in_vm_trans:
+ case _thread_blocked_trans:
+ case _thread_in_native_trans:
+ case _thread_blocked:
+ case _thread_in_vm:
+ case _thread_in_native:
+ case _thread_in_Java_trans:
+ break;
+ case _thread_in_Java:
+ return true;
+ default:
+ ShouldNotReachHere();
+ break;
}
return false;
}
-static bool in_native_sample(JavaThread* thread) {
- switch (thread->thread_state()) {
- case _thread_new:
- case _thread_uninitialized:
- case _thread_new_trans:
- case _thread_blocked_trans:
- case _thread_blocked:
- case _thread_in_vm:
- case _thread_in_vm_trans:
- case _thread_in_Java_trans:
- case _thread_in_Java:
- case _thread_in_native_trans:
- break;
- case _thread_in_native:
- return true;
- default:
- ShouldNotReachHere();
- break;
+static bool thread_state_in_native(JavaThread* thread) {
+ assert(thread != NULL, "invariant");
+ switch(thread->thread_state()) {
+ case _thread_new:
+ case _thread_uninitialized:
+ case _thread_new_trans:
+ case _thread_blocked_trans:
+ case _thread_blocked:
+ case _thread_in_vm:
+ case _thread_in_vm_trans:
+ case _thread_in_Java_trans:
+ case _thread_in_Java:
+ case _thread_in_native_trans:
+ break;
+ case _thread_in_native:
+ return true;
+ default:
+ ShouldNotReachHere();
+ break;
}
return false;
}
@@ -94,11 +96,10 @@
~JfrThreadSampleClosure() {}
EventExecutionSample* next_event() { return &_events[_added_java++]; }
EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; }
- void commit_events();
- int added() const { return _added_java; }
- JfrSampleType do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, bool java_sample, bool native_sample);
- int java_entries() { return _added_java; }
- int native_entries() { return _added_native; }
+ void commit_events(JfrSampleType type);
+ bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type);
+ uint java_entries() { return _added_java; }
+ uint native_entries() { return _added_native; }
private:
bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
@@ -106,8 +107,8 @@
EventExecutionSample* _events;
EventNativeMethodSample* _events_native;
Thread* _self;
- int _added_java;
- int _added_native;
+ uint _added_java;
+ uint _added_native;
};
class OSThreadSampler : public os::SuspendedThreadTask {
@@ -172,7 +173,7 @@
void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
JavaThread* jth = (JavaThread*)context.thread();
// Skip sample if we signaled a thread that moved to other state
- if (!in_java_sample(jth)) {
+ if (!thread_state_in_java(jth)) {
return;
}
JfrGetCallTrace trace(true, jth);
@@ -281,12 +282,21 @@
return true;
}
-void JfrThreadSampleClosure::commit_events() {
- for (int i = 0; i < _added_java; ++i) {
- _events[i].commit();
- }
- for (int i = 0; i < _added_native; ++i) {
- _events_native[i].commit();
+static const uint MAX_NR_OF_JAVA_SAMPLES = 5;
+static const uint MAX_NR_OF_NATIVE_SAMPLES = 1;
+
+void JfrThreadSampleClosure::commit_events(JfrSampleType type) {
+ if (JAVA_SAMPLE == type) {
+ assert(_added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant");
+ for (uint i = 0; i < _added_java; ++i) {
+ _events[i].commit();
+ }
+ } else {
+ assert(NATIVE_SAMPLE == type, "invariant");
+ assert(_added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant");
+ for (uint i = 0; i < _added_native; ++i) {
+ _events_native[i].commit();
+ }
}
}
@@ -344,23 +354,26 @@
}
}
-JfrSampleType JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, bool java_sample, bool native_sample) {
+bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
- if (thread->is_hidden_from_external_view()) {
- return NO_SAMPLE;
+ if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
+ return false;
}
- if (thread->in_deopt_handler()) {
- return NO_SAMPLE;
- }
- JfrSampleType ret = NO_SAMPLE;
+
+ bool ret = false;
thread->set_trace_flag();
if (!UseMembar) {
os::serialize_thread_states();
}
- if (in_java_sample(thread) && java_sample) {
- ret = sample_thread_in_java(thread, frames, max_frames) ? JAVA_SAMPLE : NO_SAMPLE;
- } else if (in_native_sample(thread) && native_sample) {
- ret = sample_thread_in_native(thread, frames, max_frames) ? NATIVE_SAMPLE : NO_SAMPLE;
+ if (JAVA_SAMPLE == type) {
+ if (thread_state_in_java(thread)) {
+ ret = sample_thread_in_java(thread, frames, max_frames);
+ }
+ } else {
+ assert(NATIVE_SAMPLE == type, "invariant");
+ if (thread_state_in_native(thread)) {
+ ret = sample_thread_in_native(thread, frames, max_frames);
+ }
}
clear_transition_block(thread);
return ret;
@@ -396,31 +409,19 @@
}
JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
+ assert(t_list != NULL, "invariant");
assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
- if (current == NULL) {
+ assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
+ assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
+ if ((uint)_cur_index + 1 == t_list->length()) {
+ // wrap
_cur_index = 0;
- return t_list->thread_at(_cur_index);
- }
-
- if (_cur_index == -1 || t_list->thread_at(_cur_index) != current) {
- // 'current' is not at '_cur_index' so find it:
- _cur_index = t_list->find_index_of_JavaThread(current);
- assert(_cur_index != -1, "current JavaThread should be findable.");
+ } else {
+ _cur_index++;
}
- _cur_index++;
-
- JavaThread* next = NULL;
- // wrap
- if ((uint)_cur_index >= t_list->length()) {
- _cur_index = 0;
- }
- next = t_list->thread_at(_cur_index);
-
- // sample wrap
- if (next == first_sampled) {
- return NULL;
- }
- return next;
+ assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
+ JavaThread* const next = t_list->thread_at(_cur_index);
+ return next != first_sampled ? next : NULL;
}
void JfrThreadSampler::start_thread() {
@@ -494,54 +495,50 @@
delete this;
}
-static const int MAX_NR_OF_SAMPLES = 5;
void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
ResourceMark rm;
- EventExecutionSample samples[MAX_NR_OF_SAMPLES];
- EventNativeMethodSample samples_native[MAX_NR_OF_SAMPLES];
+ EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
+ EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
JfrThreadSampleClosure sample_task(samples, samples_native);
- int num_samples = 0;
+ const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
+ uint num_sample_attempts = 0;
+ JavaThread* start = NULL;
+
{
elapsedTimer sample_time;
sample_time.start();
-
{
MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
ThreadsListHandle tlh;
- JavaThread* current = tlh.includes(*last_thread) ? *last_thread : NULL;
- JavaThread* start = NULL;
+ // Resolve a sample session relative start position index into the thread list array.
+ // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
+ _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
+ JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
- while (num_samples < MAX_NR_OF_SAMPLES) {
+ while (num_sample_attempts < sample_limit) {
current = next_thread(tlh.list(), start, current);
if (current == NULL) {
break;
}
if (start == NULL) {
- start = current; // remember thread where we started sampling
+ start = current; // remember the thread where we started to attempt sampling
}
if (current->is_Compiler_thread()) {
continue;
}
- *last_thread = current; // remember thread we last sampled
- JfrSampleType ret = sample_task.do_sample_thread(current, _frames, _max_frames, type == JAVA_SAMPLE, type == NATIVE_SAMPLE);
- switch (type) {
- case JAVA_SAMPLE:
- case NATIVE_SAMPLE:
- ++num_samples;
- break;
- default:
- break;
- }
+ sample_task.do_sample_thread(current, _frames, _max_frames, type);
+ num_sample_attempts++;
}
+ *last_thread = current; // remember the thread we last attempted to sample
}
sample_time.stop();
log_trace(jfr)("JFR thread sampling done in %3.7f secs with %d java %d native samples",
- sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
+ sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
}
- if (num_samples > 0) {
- sample_task.commit_events();
+ if (num_sample_attempts > 0) {
+ sample_task.commit_events(type);
}
}
@@ -573,7 +570,7 @@
}
static void log(size_t interval_java, size_t interval_native) {
- log_info(jfr)("Updated thread sampler for java: " SIZE_FORMAT" ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
+ log_info(jfr)("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
}
void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
@@ -591,13 +588,11 @@
interval_java = _sampler->get_java_interval();
interval_native = _sampler->get_native_interval();
}
-
if (java_interval) {
interval_java = period;
} else {
interval_native = period;
}
-
if (interval_java > 0 || interval_native > 0) {
if (_sampler == NULL) {
log_info(jfr)("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);