src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp

changeset 9858
b985cbb00e68
child 9861
a248d0be1309
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/jfr/periodic/sampling/jfrThreadSampler.cpp	Mon Aug 12 18:30:40 2019 +0300
     1.3 @@ -0,0 +1,635 @@
     1.4 +/*
     1.5 + * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "jfr/jfrEvents.hpp"
    1.30 +#include "jfr/recorder/jfrRecorder.hpp"
    1.31 +#include "jfr/periodic/sampling/jfrCallTrace.hpp"
    1.32 +#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
    1.33 +#include "jfr/recorder/service/jfrOptionSet.hpp"
    1.34 +#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
    1.35 +#include "jfr/support/jfrThreadId.hpp"
    1.36 +#include "jfr/utilities/jfrTime.hpp"
    1.37 +#include "runtime/frame.inline.hpp"
    1.38 +#include "runtime/os.hpp"
    1.39 +#include "runtime/semaphore.hpp"
    1.40 +#include "runtime/thread.inline.hpp"
    1.41 +
    1.42 +enum JfrSampleType {
    1.43 +  NO_SAMPLE = 0,
    1.44 +  JAVA_SAMPLE = 1,
    1.45 +  NATIVE_SAMPLE = 2
    1.46 +};
    1.47 +
    1.48 +static bool thread_state_in_java(JavaThread* thread) {
    1.49 +  assert(thread != NULL, "invariant");
    1.50 +  switch(thread->thread_state()) {
    1.51 +    case _thread_new:
    1.52 +    case _thread_uninitialized:
    1.53 +    case _thread_new_trans:
    1.54 +    case _thread_in_vm_trans:
    1.55 +    case _thread_blocked_trans:
    1.56 +    case _thread_in_native_trans:
    1.57 +    case _thread_blocked:
    1.58 +    case _thread_in_vm:
    1.59 +    case _thread_in_native:
    1.60 +    case _thread_in_Java_trans:
    1.61 +      break;
    1.62 +    case _thread_in_Java:
    1.63 +      return true;
    1.64 +    default:
    1.65 +      ShouldNotReachHere();
    1.66 +      break;
    1.67 +  }
    1.68 +  return false;
    1.69 +}
    1.70 +
    1.71 +static bool thread_state_in_native(JavaThread* thread) {
    1.72 +  assert(thread != NULL, "invariant");
    1.73 +  switch(thread->thread_state()) {
    1.74 +    case _thread_new:
    1.75 +    case _thread_uninitialized:
    1.76 +    case _thread_new_trans:
    1.77 +    case _thread_blocked_trans:
    1.78 +    case _thread_blocked:
    1.79 +    case _thread_in_vm:
    1.80 +    case _thread_in_vm_trans:
    1.81 +    case _thread_in_Java_trans:
    1.82 +    case _thread_in_Java:
    1.83 +    case _thread_in_native_trans:
    1.84 +      break;
    1.85 +    case _thread_in_native:
    1.86 +      return true;
    1.87 +    default:
    1.88 +      ShouldNotReachHere();
    1.89 +      break;
    1.90 +  }
    1.91 +  return false;
    1.92 +}
    1.93 +
    1.94 +class JfrThreadSampleClosure {
    1.95 + public:
    1.96 +  JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native);
    1.97 +  ~JfrThreadSampleClosure() {}
    1.98 +  EventExecutionSample* next_event() { return &_events[_added_java++]; }
    1.99 +  EventNativeMethodSample* next_event_native() { return &_events_native[_added_native++]; }
   1.100 +  void commit_events(JfrSampleType type);
   1.101 +  bool do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type);
   1.102 +  uint java_entries() { return _added_java; }
   1.103 +  uint native_entries() { return _added_native; }
   1.104 +
   1.105 + private:
   1.106 +  bool sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   1.107 +  bool sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames);
   1.108 +  EventExecutionSample* _events;
   1.109 +  EventNativeMethodSample* _events_native;
   1.110 +  Thread* _self;
   1.111 +  uint _added_java;
   1.112 +  uint _added_native;
   1.113 +};
   1.114 +
   1.115 +class OSThreadSampler : public os::SuspendedThreadTask {
   1.116 + public:
   1.117 +  OSThreadSampler(JavaThread* thread,
   1.118 +                  JfrThreadSampleClosure& closure,
   1.119 +                  JfrStackFrame *frames,
   1.120 +                  u4 max_frames) : os::SuspendedThreadTask((Thread*)thread),
   1.121 +    _success(false),
   1.122 +    _stacktrace(frames, max_frames),
   1.123 +    _closure(closure),
   1.124 +    _suspend_time() {}
   1.125 +
   1.126 +  void take_sample();
   1.127 +  void do_task(const os::SuspendedThreadTaskContext& context);
   1.128 +  void protected_task(const os::SuspendedThreadTaskContext& context);
   1.129 +  bool success() const { return _success; }
   1.130 +  const JfrStackTrace& stacktrace() const { return _stacktrace; }
   1.131 +
   1.132 + private:
   1.133 +  bool _success;
   1.134 +  JfrStackTrace _stacktrace;
   1.135 +  JfrThreadSampleClosure& _closure;
   1.136 +  JfrTicks _suspend_time;
   1.137 +};
   1.138 +
   1.139 +class OSThreadSamplerCallback : public os::CrashProtectionCallback {
   1.140 + public:
   1.141 +  OSThreadSamplerCallback(OSThreadSampler& sampler, const os::SuspendedThreadTaskContext &context) :
   1.142 +    _sampler(sampler), _context(context) {
   1.143 +  }
   1.144 +  virtual void call() {
   1.145 +    _sampler.protected_task(_context);
   1.146 +  }
   1.147 + private:
   1.148 +  OSThreadSampler& _sampler;
   1.149 +  const os::SuspendedThreadTaskContext& _context;
   1.150 +};
   1.151 +
   1.152 +void OSThreadSampler::do_task(const os::SuspendedThreadTaskContext& context) {
   1.153 +#ifndef ASSERT
   1.154 +  guarantee(JfrOptionSet::sample_protection(), "Sample Protection should be on in product builds");
   1.155 +#endif
   1.156 +  assert(_suspend_time.value() == 0, "already timestamped!");
   1.157 +  _suspend_time = JfrTicks::now();
   1.158 +
   1.159 +  if (JfrOptionSet::sample_protection()) {
   1.160 +    OSThreadSamplerCallback cb(*this, context);
   1.161 +    os::ThreadCrashProtection crash_protection;
   1.162 +    if (!crash_protection.call(cb)) {
   1.163 +      if (true) tty->print_cr("Thread method sampler crashed");
   1.164 +    }
   1.165 +  } else {
   1.166 +    protected_task(context);
   1.167 +  }
   1.168 +}
   1.169 +
   1.170 +/*
   1.171 +* From this method and down the call tree we attempt to protect against crashes
   1.172 +* using a signal handler / __try block. Don't take locks, rely on destructors or
   1.173 +* leave memory (in case of signal / exception) in an inconsistent state. */
   1.174 +void OSThreadSampler::protected_task(const os::SuspendedThreadTaskContext& context) {
   1.175 +  JavaThread* jth = (JavaThread*)context.thread();
   1.176 +  // Skip sample if we signaled a thread that moved to other state
   1.177 +  if (!thread_state_in_java(jth)) {
   1.178 +    return;
   1.179 +  }
   1.180 +  JfrGetCallTrace trace(true, jth);
   1.181 +  frame topframe;
   1.182 +  if (trace.get_topframe(context.ucontext(), topframe)) {
   1.183 +    if (_stacktrace.record_thread(*jth, topframe)) {
   1.184 +      /* If we managed to get a topframe and a stacktrace, create an event
   1.185 +      * and put it into our array. We can't call Jfr::_stacktraces.add()
   1.186 +      * here since it would allocate memory using malloc. Doing so while
   1.187 +      * the stopped thread is inside malloc would deadlock. */
   1.188 +      _success = true;
   1.189 +      EventExecutionSample *ev = _closure.next_event();
   1.190 +      ev->set_starttime(_suspend_time);
   1.191 +      ev->set_endtime(_suspend_time); // fake to not take an end time
   1.192 +      ev->set_sampledThread(JFR_THREAD_ID(jth));
   1.193 +      ev->set_state(java_lang_Thread::get_thread_status(jth->threadObj()));
   1.194 +    }
   1.195 +  }
   1.196 +}
   1.197 +
   1.198 +void OSThreadSampler::take_sample() {
   1.199 +  run();
   1.200 +}
   1.201 +
   1.202 +class JfrNativeSamplerCallback : public os::CrashProtectionCallback {
   1.203 + public:
   1.204 +  JfrNativeSamplerCallback(JfrThreadSampleClosure& closure, JavaThread* jt, JfrStackFrame* frames, u4 max_frames) :
   1.205 +    _closure(closure), _jt(jt), _stacktrace(frames, max_frames), _success(false) {
   1.206 +  }
   1.207 +  virtual void call();
   1.208 +  bool success() { return _success; }
   1.209 +  JfrStackTrace& stacktrace() { return _stacktrace; }
   1.210 +
   1.211 + private:
   1.212 +  JfrThreadSampleClosure& _closure;
   1.213 +  JavaThread* _jt;
   1.214 +  JfrStackTrace _stacktrace;
   1.215 +  bool _success;
   1.216 +};
   1.217 +
   1.218 +static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt) {
   1.219 +  EventNativeMethodSample *ev = closure.next_event_native();
   1.220 +  ev->set_starttime(JfrTicks::now());
   1.221 +  ev->set_sampledThread(JFR_THREAD_ID(jt));
   1.222 +  ev->set_state(java_lang_Thread::get_thread_status(jt->threadObj()));
   1.223 +}
   1.224 +
   1.225 +void JfrNativeSamplerCallback::call() {
   1.226 +  // When a thread is only attach it will be native without a last java frame
   1.227 +  if (!_jt->has_last_Java_frame()) {
   1.228 +    return;
   1.229 +  }
   1.230 +
   1.231 +  frame topframe = _jt->last_frame();
   1.232 +  frame first_java_frame;
   1.233 +  Method* method = NULL;
   1.234 +  JfrGetCallTrace gct(false, _jt);
   1.235 +  if (!gct.find_top_frame(topframe, &method, first_java_frame)) {
   1.236 +    return;
   1.237 +  }
   1.238 +  if (method == NULL) {
   1.239 +    return;
   1.240 +  }
   1.241 +  topframe = first_java_frame;
   1.242 +  _success = _stacktrace.record_thread(*_jt, topframe);
   1.243 +  if (_success) {
   1.244 +    write_native_event(_closure, _jt);
   1.245 +  }
   1.246 +}
   1.247 +
   1.248 +bool JfrThreadSampleClosure::sample_thread_in_java(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {
   1.249 +  OSThreadSampler sampler(thread, *this, frames, max_frames);
   1.250 +  sampler.take_sample();
   1.251 +  /* We don't want to allocate any memory using malloc/etc while the thread
   1.252 +  * is stopped, so everything is stored in stack allocated memory until this
   1.253 +  * point where the thread has been resumed again, if the sampling was a success
   1.254 +  * we need to store the stacktrace in the stacktrace repository and update
   1.255 +  * the event with the id that was returned. */
   1.256 +  if (!sampler.success()) {
   1.257 +    return false;
   1.258 +  }
   1.259 +  EventExecutionSample *event = &_events[_added_java - 1];
   1.260 +  traceid id = JfrStackTraceRepository::add(sampler.stacktrace());
   1.261 +  assert(id != 0, "Stacktrace id should not be 0");
   1.262 +  event->set_stackTrace(id);
   1.263 +  return true;
   1.264 +}
   1.265 +
   1.266 +bool JfrThreadSampleClosure::sample_thread_in_native(JavaThread* thread, JfrStackFrame* frames, u4 max_frames) {
   1.267 +  JfrNativeSamplerCallback cb(*this, thread, frames, max_frames);
   1.268 +  if (JfrOptionSet::sample_protection()) {
   1.269 +    os::ThreadCrashProtection crash_protection;
   1.270 +    if (!crash_protection.call(cb)) {
   1.271 +      if (true) tty->print_cr("Thread method sampler crashed for native");
   1.272 +    }
   1.273 +  } else {
   1.274 +    cb.call();
   1.275 +  }
   1.276 +  if (!cb.success()) {
   1.277 +    return false;
   1.278 +  }
   1.279 +  EventNativeMethodSample *event = &_events_native[_added_native - 1];
   1.280 +  traceid id = JfrStackTraceRepository::add(cb.stacktrace());
   1.281 +  assert(id != 0, "Stacktrace id should not be 0");
   1.282 +  event->set_stackTrace(id);
   1.283 +  return true;
   1.284 +}
   1.285 +
   1.286 +static const uint MAX_NR_OF_JAVA_SAMPLES = 5;
   1.287 +static const uint MAX_NR_OF_NATIVE_SAMPLES = 1;
   1.288 +
   1.289 +void JfrThreadSampleClosure::commit_events(JfrSampleType type) {
   1.290 +  if (JAVA_SAMPLE == type) {
   1.291 +    assert(_added_java <= MAX_NR_OF_JAVA_SAMPLES, "invariant");
   1.292 +    for (uint i = 0; i < _added_java; ++i) {
   1.293 +      _events[i].commit();
   1.294 +    }
   1.295 +  } else {
   1.296 +    assert(NATIVE_SAMPLE == type, "invariant");
   1.297 +    assert(_added_native <= MAX_NR_OF_NATIVE_SAMPLES, "invariant");
   1.298 +    for (uint i = 0; i < _added_native; ++i) {
   1.299 +      _events_native[i].commit();
   1.300 +    }
   1.301 +  }
   1.302 +}
   1.303 +
   1.304 +JfrThreadSampleClosure::JfrThreadSampleClosure(EventExecutionSample* events, EventNativeMethodSample* events_native) :
   1.305 +  _events(events),
   1.306 +  _events_native(events_native),
   1.307 +  _self(Thread::current()),
   1.308 +  _added_java(0),
   1.309 +  _added_native(0) {
   1.310 +}
   1.311 +
   1.312 +class JfrThreadSampler : public Thread {
   1.313 +  friend class JfrThreadSampling;
   1.314 + private:
   1.315 +  Semaphore _sample;
   1.316 +  Thread* _sampler_thread;
   1.317 +  JfrStackFrame* const _frames;
   1.318 +  JavaThread* _last_thread_java;
   1.319 +  JavaThread* _last_thread_native;
   1.320 +  size_t _interval_java;
   1.321 +  size_t _interval_native;
   1.322 +  int _cur_index;
   1.323 +  const u4 _max_frames;
   1.324 +  volatile bool _disenrolled;
   1.325 +  static Monitor* _transition_block_lock;
   1.326 +
   1.327 +//  JavaThread* next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current);
   1.328 +  void task_stacktrace(JfrSampleType type, JavaThread** last_thread);
   1.329 +  JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames);
   1.330 +  ~JfrThreadSampler();
   1.331 +
   1.332 +  void start_thread();
   1.333 +
   1.334 +  void enroll();
   1.335 +  void disenroll();
   1.336 +  void set_java_interval(size_t interval) { _interval_java = interval; };
   1.337 +  void set_native_interval(size_t interval) { _interval_native = interval; };
   1.338 +  size_t get_java_interval() { return _interval_java; };
   1.339 +  size_t get_native_interval() { return _interval_native; };
   1.340 +
   1.341 + public:
   1.342 +  void run();
   1.343 +  static Monitor* transition_block() { return _transition_block_lock; }
   1.344 +  static void on_javathread_suspend(JavaThread* thread);
   1.345 +};
   1.346 +
   1.347 +Monitor* JfrThreadSampler::_transition_block_lock = new Monitor(Mutex::leaf, "Trace block", true);
   1.348 +
   1.349 +static void clear_transition_block(JavaThread* jt) {
   1.350 +//  jt->clear_trace_flag();
   1.351 +  JfrThreadLocal* const tl = jt->jfr_thread_local();
   1.352 +  if (tl->is_trace_block()) {
   1.353 +    MutexLockerEx ml(JfrThreadSampler::transition_block(), Mutex::_no_safepoint_check_flag);
   1.354 +    JfrThreadSampler::transition_block()->notify_all();
   1.355 +  }
   1.356 +}
   1.357 +
   1.358 +bool JfrThreadSampleClosure::do_sample_thread(JavaThread* thread, JfrStackFrame* frames, u4 max_frames, JfrSampleType type) {
   1.359 +  assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   1.360 +  if (thread->is_hidden_from_external_view() || thread->in_deopt_handler()) {
   1.361 +    return false;
   1.362 +  }
   1.363 +
   1.364 +  bool ret = false;
   1.365 +//  thread->set_trace_flag();
   1.366 +  if (!UseMembar) {
   1.367 +    os::serialize_thread_states();
   1.368 +  }
   1.369 +  if (JAVA_SAMPLE == type) {
   1.370 +    if (thread_state_in_java(thread)) {
   1.371 +      ret = sample_thread_in_java(thread, frames, max_frames);
   1.372 +    }
   1.373 +  } else {
   1.374 +    assert(NATIVE_SAMPLE == type, "invariant");
   1.375 +    if (thread_state_in_native(thread)) {
   1.376 +      ret = sample_thread_in_native(thread, frames, max_frames);
   1.377 +    }
   1.378 +  }
   1.379 +  clear_transition_block(thread);
   1.380 +  return ret;
   1.381 +}
   1.382 +
   1.383 +JfrThreadSampler::JfrThreadSampler(size_t interval_java, size_t interval_native, u4 max_frames) :
   1.384 +  _sample(),
   1.385 +  _sampler_thread(NULL),
   1.386 +  _frames(JfrCHeapObj::new_array<JfrStackFrame>(max_frames)),
   1.387 +  _last_thread_java(NULL),
   1.388 +  _last_thread_native(NULL),
   1.389 +  _interval_java(interval_java),
   1.390 +  _interval_native(interval_native),
   1.391 +  _cur_index(-1),
   1.392 +  _max_frames(max_frames),
   1.393 +  _disenrolled(true) {
   1.394 +}
   1.395 +
   1.396 +JfrThreadSampler::~JfrThreadSampler() {
   1.397 +  JfrCHeapObj::free(_frames, sizeof(JfrStackFrame) * _max_frames);
   1.398 +}
   1.399 +
   1.400 +void JfrThreadSampler::on_javathread_suspend(JavaThread* thread) {
   1.401 +  JfrThreadLocal* const tl = thread->jfr_thread_local();
   1.402 +  tl->set_trace_block();
   1.403 +  {
   1.404 +//    MutexLockerEx ml(transition_block(), Mutex::_no_safepoint_check_flag);
   1.405 +//    while (thread->is_trace_suspend()) {
   1.406 +//      transition_block()->wait(true);
   1.407 +//    }
   1.408 +//    tl->clear_trace_block();
   1.409 +  }
   1.410 +}
   1.411 +
   1.412 +//JavaThread* JfrThreadSampler::next_thread(ThreadsList* t_list, JavaThread* first_sampled, JavaThread* current) {
   1.413 +//  assert(t_list != NULL, "invariant");
   1.414 +//  assert(Threads_lock->owned_by_self(), "Holding the thread table lock.");
   1.415 +//  assert(_cur_index >= -1 && (uint)_cur_index + 1 <= t_list->length(), "invariant");
   1.416 +//  assert((current == NULL && -1 == _cur_index) || (t_list->find_index_of_JavaThread(current) == _cur_index), "invariant");
   1.417 +//  if ((uint)_cur_index + 1 == t_list->length()) {
   1.418 +//    // wrap
   1.419 +//    _cur_index = 0;
   1.420 +//  } else {
   1.421 +//    _cur_index++;
   1.422 +//  }
   1.423 +//  assert(_cur_index >= 0 && (uint)_cur_index < t_list->length(), "invariant");
   1.424 +//  JavaThread* const next = t_list->thread_at(_cur_index);
   1.425 +//  return next != first_sampled ? next : NULL;
   1.426 +//}
   1.427 +
   1.428 +void JfrThreadSampler::start_thread() {
   1.429 +  // XXX TODO implement sampling
   1.430 +//  if (os::create_thread(this, os::os_thread)) {
   1.431 +//    os::start_thread(this);
   1.432 +//  } else {
   1.433 +//    if (true) tty->print_cr("Failed to create thread for thread sampling");
   1.434 +//  }
   1.435 +}
   1.436 +
   1.437 +void JfrThreadSampler::enroll() {
   1.438 +  if (_disenrolled) {
   1.439 +    if (LogJFR) tty->print_cr("Enrolling thread sampler");
   1.440 +    _sample.signal();
   1.441 +    _disenrolled = false;
   1.442 +  }
   1.443 +}
   1.444 +
   1.445 +void JfrThreadSampler::disenroll() {
   1.446 +  if (!_disenrolled) {
   1.447 +    _sample.wait();
   1.448 +    _disenrolled = true;
   1.449 +    if (LogJFR) tty->print_cr("Disenrolling thread sampler");
   1.450 +  }
   1.451 +}
   1.452 +
   1.453 +static jlong get_monotonic_ms() {
   1.454 +  return os::javaTimeNanos() / 1000000;
   1.455 +}
   1.456 +
   1.457 +void JfrThreadSampler::run() {
   1.458 +  assert(_sampler_thread == NULL, "invariant");
   1.459 +
   1.460 +  initialize_thread_local_storage();
   1.461 +  record_stack_base_and_size();
   1.462 +
   1.463 +  _sampler_thread = this;
   1.464 +
   1.465 +  jlong last_java_ms = get_monotonic_ms();
   1.466 +  jlong last_native_ms = last_java_ms;
   1.467 +  while (true) {
   1.468 +    if (!_sample.trywait()) {
   1.469 +      // disenrolled
   1.470 +      _sample.wait();
   1.471 +      last_java_ms = get_monotonic_ms();
   1.472 +      last_native_ms = last_java_ms;
   1.473 +    }
   1.474 +    _sample.signal();
   1.475 +    jlong java_interval = _interval_java == 0 ? max_jlong : MAX2<jlong>(_interval_java, 10);
   1.476 +    jlong native_interval = _interval_native == 0 ? max_jlong : MAX2<jlong>(_interval_native, 10);
   1.477 +
   1.478 +    jlong now_ms = get_monotonic_ms();
   1.479 +
   1.480 +    jlong next_j = java_interval + last_java_ms - now_ms;
   1.481 +    jlong next_n = native_interval + last_native_ms - now_ms;
   1.482 +
   1.483 +    jlong sleep_to_next = MIN2<jlong>(next_j, next_n);
   1.484 +
   1.485 +    if (sleep_to_next > 0) {
   1.486 +      os::naked_short_sleep(sleep_to_next);
   1.487 +    }
   1.488 +
   1.489 +    if ((next_j - sleep_to_next) <= 0) {
   1.490 +      task_stacktrace(JAVA_SAMPLE, &_last_thread_java);
   1.491 +      last_java_ms = get_monotonic_ms();
   1.492 +    }
   1.493 +    if ((next_n - sleep_to_next) <= 0) {
   1.494 +      task_stacktrace(NATIVE_SAMPLE, &_last_thread_native);
   1.495 +      last_native_ms = get_monotonic_ms();
   1.496 +    }
   1.497 +  }
   1.498 +  delete this;
   1.499 +}
   1.500 +
   1.501 +
   1.502 +void JfrThreadSampler::task_stacktrace(JfrSampleType type, JavaThread** last_thread) {
   1.503 +  ResourceMark rm;
   1.504 +  EventExecutionSample samples[MAX_NR_OF_JAVA_SAMPLES];
   1.505 +  EventNativeMethodSample samples_native[MAX_NR_OF_NATIVE_SAMPLES];
   1.506 +  JfrThreadSampleClosure sample_task(samples, samples_native);
   1.507 +
   1.508 +  const uint sample_limit = JAVA_SAMPLE == type ? MAX_NR_OF_JAVA_SAMPLES : MAX_NR_OF_NATIVE_SAMPLES;
   1.509 +  uint num_sample_attempts = 0;
   1.510 +  JavaThread* start = NULL;
   1.511 +
   1.512 +  {
   1.513 +    elapsedTimer sample_time;
   1.514 +    sample_time.start();
   1.515 +    {
   1.516 +//      MonitorLockerEx tlock(Threads_lock, Mutex::_allow_vm_block_flag);
   1.517 +//      ThreadsListHandle tlh;
   1.518 +//      // Resolve a sample session relative start position index into the thread list array.
   1.519 +//      // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
   1.520 +//      _cur_index = tlh.list()->find_index_of_JavaThread(*last_thread);
   1.521 +//      JavaThread* current = _cur_index != -1 ? *last_thread : NULL;
   1.522 +//
   1.523 +//      while (num_sample_attempts < sample_limit) {
   1.524 +//        current = next_thread(tlh.list(), start, current);
   1.525 +//        if (current == NULL) {
   1.526 +//          break;
   1.527 +//        }
   1.528 +//        if (start == NULL) {
   1.529 +//          start = current;  // remember the thread where we started to attempt sampling
   1.530 +//        }
   1.531 +//        if (current->is_Compiler_thread()) {
   1.532 +//          continue;
   1.533 +//        }
   1.534 +//        sample_task.do_sample_thread(current, _frames, _max_frames, type);
   1.535 +//        num_sample_attempts++;
   1.536 +//      }
   1.537 +//      *last_thread = current;  // remember the thread we last attempted to sample
   1.538 +    }
   1.539 +    sample_time.stop();
   1.540 +    if (LogJFR && Verbose) tty->print_cr("JFR thread sampling done in %3.7f secs with %d java %d native samples",
   1.541 +                   sample_time.seconds(), sample_task.java_entries(), sample_task.native_entries());
   1.542 +  }
   1.543 +  if (num_sample_attempts > 0) {
   1.544 +    sample_task.commit_events(type);
   1.545 +  }
   1.546 +}
   1.547 +
   1.548 +static JfrThreadSampling* _instance = NULL;
   1.549 +
   1.550 +JfrThreadSampling& JfrThreadSampling::instance() {
   1.551 +  return *_instance;
   1.552 +}
   1.553 +
   1.554 +JfrThreadSampling* JfrThreadSampling::create() {
   1.555 +  assert(_instance == NULL, "invariant");
   1.556 +  _instance = new JfrThreadSampling();
   1.557 +  return _instance;
   1.558 +}
   1.559 +
   1.560 +void JfrThreadSampling::destroy() {
   1.561 +  if (_instance != NULL) {
   1.562 +    delete _instance;
   1.563 +    _instance = NULL;
   1.564 +  }
   1.565 +}
   1.566 +
   1.567 +JfrThreadSampling::JfrThreadSampling() : _sampler(NULL) {}
   1.568 +
   1.569 +JfrThreadSampling::~JfrThreadSampling() {
   1.570 +  if (_sampler != NULL) {
   1.571 +    _sampler->disenroll();
   1.572 +  }
   1.573 +}
   1.574 +
   1.575 +static void log(size_t interval_java, size_t interval_native) {
   1.576 +  if (LogJFR) tty->print_cr("Updated thread sampler for java: " SIZE_FORMAT "  ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
   1.577 +}
   1.578 +
   1.579 +void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
   1.580 +  assert(_sampler == NULL, "invariant");
   1.581 +  if (LogJFR) tty->print_cr("Enrolling thread sampler");
   1.582 +  _sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth());
   1.583 +  _sampler->start_thread();
   1.584 +  _sampler->enroll();
   1.585 +}
   1.586 +
   1.587 +void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period) {
   1.588 +  size_t interval_java = 0;
   1.589 +  size_t interval_native = 0;
   1.590 +  if (_sampler != NULL) {
   1.591 +    interval_java = _sampler->get_java_interval();
   1.592 +    interval_native = _sampler->get_native_interval();
   1.593 +  }
   1.594 +  if (java_interval) {
   1.595 +    interval_java = period;
   1.596 +  } else {
   1.597 +    interval_native = period;
   1.598 +  }
   1.599 +  if (interval_java > 0 || interval_native > 0) {
   1.600 +    if (_sampler == NULL) {
   1.601 +      if (LogJFR) tty->print_cr("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
   1.602 +      start_sampler(interval_java, interval_native);
   1.603 +    } else {
   1.604 +      _sampler->set_java_interval(interval_java);
   1.605 +      _sampler->set_native_interval(interval_native);
   1.606 +      _sampler->enroll();
   1.607 +    }
   1.608 +    assert(_sampler != NULL, "invariant");
   1.609 +    log(interval_java, interval_native);
   1.610 +  } else if (_sampler != NULL) {
   1.611 +    _sampler->disenroll();
   1.612 +  }
   1.613 +}
   1.614 +
   1.615 +void JfrThreadSampling::set_java_sample_interval(size_t period) {
   1.616 +  if (_instance == NULL && 0 == period) {
   1.617 +    return;
   1.618 +  }
   1.619 +  instance().set_sampling_interval(true, period);
   1.620 +}
   1.621 +
   1.622 +void JfrThreadSampling::set_native_sample_interval(size_t period) {
   1.623 +  if (_instance == NULL && 0 == period) {
   1.624 +    return;
   1.625 +  }
   1.626 +  instance().set_sampling_interval(false, period);
   1.627 +}
   1.628 +
   1.629 +void JfrThreadSampling::on_javathread_suspend(JavaThread* thread) {
   1.630 +  JfrThreadSampler::on_javathread_suspend(thread);
   1.631 +}
   1.632 +
   1.633 +Thread* JfrThreadSampling::sampler_thread() {
   1.634 +  if (_instance == NULL) {
   1.635 +    return NULL;
   1.636 +  }
   1.637 +  return _instance->_sampler != NULL ? _instance->_sampler->_sampler_thread : NULL;
   1.638 +}

mercurial