Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp
38922 views
/*1* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "jfr/jfrEvents.hpp"26#include "jfr/recorder/jfrRecorder.hpp"27#include "jfr/periodic/sampling/jfrCallTrace.hpp"28#include "jfr/periodic/sampling/jfrThreadSampler.hpp"29#include "jfr/recorder/service/jfrOptionSet.hpp"30#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"31#include "jfr/support/jfrThreadId.hpp"32#include "jfr/utilities/jfrTime.hpp"33#include "runtime/frame.inline.hpp"34#include "runtime/os.hpp"35#include "runtime/semaphore.hpp"36#include "runtime/thread.inline.hpp"3738enum JfrSampleType {39NO_SAMPLE = 0,40JAVA_SAMPLE = 1,41NATIVE_SAMPLE = 242};4344static bool thread_state_in_java(JavaThread* thread) {45assert(thread != NULL, "invariant");46switch(thread->thread_state()) {47case _thread_new:48case _thread_uninitialized:49case _thread_new_trans:50case _thread_in_vm_trans:51case _thread_blocked_trans:52case _thread_in_native_trans:53case _thread_blocked:54case _thread_in_vm:55case _thread_in_native:56case _thread_in_Java_trans:57break;58case _thread_in_Java:59return true;60default:61ShouldNotReachHere();62break;63}64return false;65}6667static bool thread_state_in_native(JavaThread* thread) {68assert(thread != NULL, "invariant");69switch(thread->thread_state()) {70case _thread_new:71case _thread_uninitialized:72case _thread_new_trans:73case _thread_blocked_trans:74case _thread_blocked:75case _thread_in_vm:76case _thread_in_vm_trans:77case _thread_in_Java_trans:78case _thread_in_Java:79case _thread_in_native_trans:80break;81case _thread_in_native:82return true;83default:84ShouldNotReachHere();85break;86}87return false;88}8990class JfrThreadSampleClosure {91public:92JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native);93~JfrThreadSampleClosure() {}94EventExecutionSample* next_event() { return &_events[_added_java++]; }95EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; }96void commit_events(JfrSampleType type);97bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type);98uint java_entries() { return _added_java; }99uint native_entries() { return _added_native; }100101private:102bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);103bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);104EventExecutionSample* _events;105EventNativeMethodSample* _events_native;106Thread* _self;107uint _added_java;108uint _added_native;109};110111class OSThreadSampler : public os::SuspendedThreadTask {112public:113OSThreadSampler(JavaThread* thread,114JfrThreadSampleClosure& closure,115JfrStackFrame *frames,116u4 max_frames) : os::SuspendedThreadTask((Thread*)thread),117_success(false),118_stacktrace(frames, max_frames),119_closure(closure),120_suspend_time() {}121122void take_sample();123void do_task(const os::SuspendedThreadTaskContext& context);124void protected_task(const os::SuspendedThreadTaskContext& context);125bool success() const { return _success; }126const JfrStackTrace& stacktrace() const { return _stacktrace; }127128private:129bool _success;130JfrStackTrace _stacktrace;131JfrThreadSampleClosure& _closure;132JfrTicks _suspend_time;133};134135class OSThreadSamplerCallback : public os::CrashProtectionCallback {136public:137OSThreadSamplerCallback(OSThreadSampler& sampler, const os::SuspendedThreadTaskContext &context) :138_sampler(sampler), _context(context) {139}140virtual void call() {141_sampler.protected_task(_context);142}143private:144OSThreadSampler& _sampler;145const os::SuspendedThreadTaskContext& _context;146};147148void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) {149#ifndef ASSERT150guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds");151#endif152assert(_suspend_time.value() == 0, "already timestamped!");153_suspend_time = JfrTicks::now();154155if (JfrOptionSet::sample_protection()) {156OSThreadSamplerCallback cb(*this, context);157os::ThreadCrashProtection crash_protection;158if (!crash_protection.call(cb)) {159if (true) tty->print_cr("Thread method sampler crashed");160}161} else {162protected_task(context);163}164}165166/*167* From this method and down the call tree we attempt to protect against crashes168* using a signal handler / __try block. Don't take locks, rely on destructors or169* leave memory (in case of signal / exception) in an inconsistent state. */170void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {171JavaThread* jth = (JavaThread*)context.thread();172// Skip sample if we signaled a thread that moved to other state173if (!thread_state_in_java(jth)) {174return;175}176JfrGetCallTrace trace(true, jth);177frame topframe;178if (trace.get_topframe(context.ucontext(), topframe)) {179if (_stacktrace.record_thread(*jth, topframe)) {180/* If we managed to get a topframe and a stacktrace, create an event181* and put it into our array. We can't call Jfr::_stacktraces.add()182* here since it would allocate memory using malloc. Doing so while183* the stopped thread is inside malloc would deadlock. */184_success = true;185EventExecutionSample *ev = _closure.next_event();186ev->set_starttime(_suspend_time);187ev->set_endtime(_suspend_time); // fake to not take an end time188ev->set_sampledThread(JFR_THREAD_ID(jth));189ev->set_state(java_lang_Thread::get_thread_status(jth->threadObj()));190}191}192}193194void OSThreadSampler::take_sample() {195run();196}197198class JfrNativeSamplerCallback : public os::CrashProtectionCallback {199public:200JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) :201_closure(closure), _jt(jt), _stacktrace(frames, max_frames), _success(false) {202}203virtual void call();204bool success() { return _success; }205JfrStackTrace& stacktrace() { return _stacktrace; }206207private:208JfrThreadSampleClosure& _closure;209JavaThread* _jt;210JfrStackTrace _stacktrace;211bool _success;212};213214static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt) {215EventNativeMethodSample *ev = closure.next_event_native();216ev->set_starttime(JfrTicks::now());217ev->set_sampledThread(JFR_THREAD_ID(jt));218ev->set_state(java_lang_Thread::get_thread_status(jt->threadObj()));219}220221void JfrNativeSamplerCallback::call() {222// When a thread is only attach it will be native without a last java frame223if (!_jt->has_last_Java_frame()) {224return;225}226227frame topframe = _jt->last_frame();228frame first_java_frame;229Method* method = NULL;230JfrGetCallTrace gct(false, _jt);231if (!gct.find_top_frame(topframe, &method, first_java_frame)) {232return;233}234if (method == NULL) {235return;236}237topframe = first_java_frame;238_success = _stacktrace.record_thread(*_jt, topframe);239if (_success) {240write_native_event(_closure, _jt);241}242}243244bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {245OSThreadSampler sampler(thread, *this, frames, max_frames);246sampler.take_sample();247/* We don't want to allocate any memory using malloc/etc while the thread248* is stopped, so everything is stored in stack allocated memory until this249* point where the thread has been resumed again, if the sampling was a success250* we need to store the stacktrace in the stacktrace repository and update251* the event with the id that was returned. */252if (!sampler.success()) {253return false;254}255EventExecutionSample *event = &_events[_added_java - 1];256traceid id = JfrStackTraceRepository::add(sampler.stacktrace());257assert(id != 0, "Stacktrace id should not be 0");258event->set_stackTrace(id);259return true;260}261262bool JfrThreadSampleClosure::sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {263JfrNativeSamplerCallback cb(*this, thread, frames, max_frames);264if (JfrOptionSet::sample_protection()) {265os::ThreadCrashProtection crash_protection;266if (!crash_protection.call(cb)) {267if (true) tty->print_cr("Thread method sampler crashed for native");268}269} else {270cb.call();271}272if (!cb.success()) {273return false;274}275EventNativeMethodSample *event = &_events_native[_added_native - 1];276traceid id = JfrStackTraceRepository::add(cb.stacktrace());277assert(id != 0, "Stacktrace id should not be 0");278event->set_stackTrace(id);279return true;280}281282static const uint MAX_NR_OF_JAVA_SAMPLES = 5;283static const uint MAX_NR_OF_NATIVE_SAMPLES = 1;284285void JfrThreadSampleClosure::commit_events(JfrSampleType type) {286if (JAVA_SAMPLE == type) {287assert(_added_java > 0 && _added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant");288for (uint i = 0; i < _added_java; ++i) {289_events[i].commit();290}291} else {292assert(NATIVE_SAMPLE == type, "invariant");293assert(_added_native > 0 && _added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant");294for (uint i = 0; i < _added_native; ++i) {295_events_native[i].commit();296}297}298}299300JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) :301_events(events),302_events_native(events_native),303_self(Thread::current()),304_added_java(0),305_added_native(0) {306}307308class JfrThreadSampler : public Thread {309friend class JfrThreadSampling;310private:311Semaphore _sample;312Thread* _sampler_thread;313JfrStackFrame* const _frames;314JavaThread* _last_thread_java;315JavaThread* _last_thread_native;316size_t _interval_java;317size_t _interval_native;318int _cur_index;319const u4 _max_frames;320volatile bool _disenrolled;321static Monitor* _transition_block_lock;322323int find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target);324JavaThread* next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current);325void task_stacktrace(JfrSampleType type, JavaThread** last_thread);326JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames);327~JfrThreadSampler();328329void start_thread();330331void enroll();332void disenroll();333void set_java_interval(size_t interval) { _interval_java = interval; };334void set_native_interval(size_t interval) { _interval_native = interval; };335size_t get_java_interval() { return _interval_java; };336size_t get_native_interval() { return _interval_native; };337338public:339void run();340static Monitor* transition_block() { return _transition_block_lock; }341static void on_javathread_suspend(JavaThread* thread);342};343344Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);345346static void clear_transition_block(JavaThread* jt) {347jt->clear_trace_flag();348JfrThreadLocal* const tl = jt->jfr_thread_local();349if (tl->is_trace_block()) {350MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);351JfrThreadSampler::transition_block()->notify_all();352}353}354355bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {356assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");357if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {358return false;359}360361bool ret = false;362thread->set_trace_flag();363if (!UseMembar) {364os::serialize_thread_states();365}366if (JAVA_SAMPLE == type) {367if (thread_state_in_java(thread)) {368ret = sample_thread_in_java(thread, frames, max_frames);369}370} else {371assert(NATIVE_SAMPLE == type, "invariant");372if (thread_state_in_native(thread)) {373ret = sample_thread_in_native(thread, frames, max_frames);374}375}376clear_transition_block(thread);377return ret;378}379380JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :381_sample(),382_sampler_thread(NULL),383_frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),384_last_thread_java(NULL),385_last_thread_native(NULL),386_interval_java(interval_java),387_interval_native(interval_native),388_cur_index(-1),389_max_frames(max_frames),390_disenrolled(true) {391}392393JfrThreadSampler::~JfrThreadSampler() {394JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);395}396397void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {398JfrThreadLocal* const tl = thread->jfr_thread_local();399tl->set_trace_block();400{401MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);402while (thread->is_trace_suspend()) {403transition_block()->wait(true);404}405tl->clear_trace_block();406}407}408409int JfrThreadSampler::find_index_of_JavaThread(JavaThread** t_list, uint length, JavaThread *target) {410assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");411if (target == NULL) {412return -1;413}414for (uint i = 0; i < length; i++) {415if (target == t_list[i]) {416return (int)i;417}418}419return -1;420}421422JavaThread* JfrThreadSampler::next_thread(JavaThread** t_list, uint length, JavaThread* first_sampled, JavaThread* current) {423assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");424if (current == NULL) {425_cur_index = 0;426return t_list[_cur_index];427}428429if (_cur_index == -1 || t_list[_cur_index] != current) {430// 'current' is not at '_cur_index' so find it:431_cur_index = find_index_of_JavaThread(t_list, length, current);432assert(_cur_index != -1, "current JavaThread should be findable.");433}434_cur_index++;435436JavaThread* next = NULL;437// wrap438if ((uint)_cur_index >= length) {439_cur_index = 0;440}441next = t_list[_cur_index];442443// sample wrap444if (next == first_sampled) {445return NULL;446}447return next;448}449450void JfrThreadSampler::start_thread() {451if (os::create_thread(this, os::os_thread)) {452os::start_thread(this);453} else {454tty->print_cr("Failed to create thread for thread sampling");455}456}457458void JfrThreadSampler::enroll() {459if (_disenrolled) {460if (LogJFR) tty->print_cr("Enrolling thread sampler");461_sample.signal();462_disenrolled = false;463}464}465466void JfrThreadSampler::disenroll() {467if (!_disenrolled) {468_sample.wait();469_disenrolled = true;470if (LogJFR) tty->print_cr("Disenrolling thread sampler");471}472}473474static jlong get_monotonic_ms() {475return os::javaTimeNanos() / 1000000;476}477478void JfrThreadSampler::run() {479assert(_sampler_thread == NULL, "invariant");480481initialize_thread_local_storage();482record_stack_base_and_size();483484_sampler_thread = this;485486jlong last_java_ms = get_monotonic_ms();487jlong last_native_ms = last_java_ms;488while (true) {489if (!_sample.trywait()) {490// disenrolled491_sample.wait();492last_java_ms = get_monotonic_ms();493last_native_ms = last_java_ms;494}495_sample.signal();496jlong java_interval = _interval_java == 0 ? max_jlong : MAX2<jlong>(_interval_java, 1);497jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 1);498499jlong now_ms = get_monotonic_ms();500501/*502* Let I be java_interval or native_interval.503* Let L be last_java_ms or last_native_ms.504* Let N be now_ms.505*506* Interval, I, might be max_jlong so the addition507* could potentially overflow without parenthesis (UB). Also note that508* L - N < 0. Avoid UB, by adding parenthesis.509*/510jlong next_j = java_interval + (last_java_ms - now_ms);511jlong next_n = native_interval + (last_native_ms - now_ms);512513jlong sleep_to_next = MIN2<jlong>(next_j, next_n);514515if (sleep_to_next > 0) {516os::naked_short_sleep(sleep_to_next);517}518519if ((next_j - sleep_to_next) <= 0) {520task_stacktrace(JAVA_SAMPLE, &_last_thread_java);521last_java_ms = get_monotonic_ms();522}523if ((next_n - sleep_to_next) <= 0) {524task_stacktrace(NATIVE_SAMPLE, &_last_thread_native);525last_native_ms = get_monotonic_ms();526}527}528delete this;529}530531532void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {533ResourceMark rm;534EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];535EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];536JfrThreadSampleClosure sample_task(samples, samples_native);537538const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;539uint num_samples = 0;540JavaThread* start = NULL;541542{543elapsedTimer sample_time;544sample_time.start();545{546MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);547int max_threads = Threads::number_of_threads();548assert(max_threads >= 0, "Threads list is empty");549uint index = 0;550JavaThread** threads_list = NEW_C_HEAP_ARRAY(JavaThread *, max_threads, mtInternal);551for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {552threads_list[index++] = tp;553}554JavaThread* current = Threads::includes(*last_thread) ? *last_thread : NULL;555JavaThread* start = NULL;556557while (num_samples < sample_limit) {558current = next_thread(threads_list, index, start, current);559if (current == NULL) {560break;561}562if (start == NULL) {563start = current; // remember the thread where we started to attempt sampling564}565if (current->is_Compiler_thread()) {566continue;567}568if (sample_task.do_sample_thread(current, _frames, _max_frames, type)) {569num_samples++;570}571}572*last_thread = current; // remember the thread we last attempted to sample573FREE_C_HEAP_ARRAY(JavaThread *, threads_list, mtInternal);574}575sample_time.stop();576if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",577sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());578}579if (num_samples > 0) {580sample_task.commit_events(type);581}582}583584static JfrThreadSampling* _instance = NULL;585586JfrThreadSampling& JfrThreadSampling::instance() {587return *_instance;588}589590JfrThreadSampling* JfrThreadSampling::create() {591assert(_instance == NULL, "invariant");592_instance = new JfrThreadSampling();593return _instance;594}595596void JfrThreadSampling::destroy() {597if (_instance != NULL) {598delete _instance;599_instance = NULL;600}601}602603JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {}604605JfrThreadSampling::~JfrThreadSampling() {606if (_sampler != NULL) {607_sampler->disenroll();608}609}610611static void log(size_t interval_java, size_t interval_native) {612if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native);613}614615void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {616assert(_sampler == NULL, "invariant");617if (LogJFR) tty->print_cr("Enrolling thread sampler");618_sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth());619_sampler->start_thread();620_sampler->enroll();621}622623void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) {624size_t interval_java = 0;625size_t interval_native = 0;626if (_sampler != NULL) {627interval_java = _sampler->get_java_interval();628interval_native = _sampler->get_native_interval();629}630if (java_interval) {631interval_java = period;632} else {633interval_native = period;634}635if (interval_java > 0 || interval_native > 0) {636if (_sampler == NULL) {637if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);638start_sampler(interval_java, interval_native);639} else {640_sampler->set_java_interval(interval_java);641_sampler->set_native_interval(interval_native);642_sampler->enroll();643}644assert(_sampler != NULL, "invariant");645log(interval_java, interval_native);646} else if (_sampler != NULL) {647_sampler->disenroll();648}649}650651void JfrThreadSampling::set_java_sample_interval(size_t period) {652if (_instance == NULL && 0 == period) {653return;654}655instance().set_sampling_interval(true, period);656}657658void JfrThreadSampling::set_native_sample_interval(size_t period) {659if (_instance == NULL && 0 == period) {660return;661}662instance().set_sampling_interval(false, period);663}664665void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) {666JfrThreadSampler::on_javathread_suspend(thread);667}668669Thread* JfrThreadSampling::sampler_thread() {670if (_instance == NULL) {671return NULL;672}673return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL;674}675676677