4545
4646#include " signals_posix.hpp"
4747
48- static const int64_t AUTOADAPT_INTERVAL_MS = 100 ;
48+ static const int64_t RECOMPUTE_INTERVAL_MS = 100 ;
4949
5050static bool is_excluded (JavaThread* jt) {
5151 return jt->is_hidden_from_external_view () ||
@@ -163,20 +163,42 @@ void JfrCPUTimeTraceQueue::clear() {
163163 Atomic::release_store (&_head, (u4)0 );
164164}
165165
166- static int64_t compute_sampling_period (double rate) {
167- if (rate == 0 ) {
168- return 0 ;
166+ // A throttle is either a rate or a fixed period
167+ class JfrCPUSamplerThrottle {
168+
169+ union {
170+ double _rate;
171+ u8 _period_nanos;
172+ };
173+ bool _is_rate;
174+
175+ public:
176+
177+ JfrCPUSamplerThrottle (double rate) : _rate(rate), _is_rate(true ) {
178+ assert (rate >= 0 , " invariant" );
169179 }
170- return os::active_processor_count () * 1000000000.0 / rate;
171- }
180+
181+ JfrCPUSamplerThrottle (u8 period_nanos) : _period_nanos(period_nanos), _is_rate(false ) {}
182+
183+ bool enabled () const { return _is_rate ? _rate > 0 : _period_nanos > 0 ; }
184+
185+ int64_t compute_sampling_period () const {
186+ if (_is_rate) {
187+ if (_rate == 0 ) {
188+ return 0 ;
189+ }
190+ return os::active_processor_count () * 1000000000.0 / _rate;
191+ }
192+ return _period_nanos;
193+ }
194+ };
172195
173196class JfrCPUSamplerThread : public NonJavaThread {
174197 friend class JfrCPUTimeThreadSampling ;
175198 private:
176199 Semaphore _sample;
177200 NonJavaThread* _sampler_thread;
178- double _rate;
179- bool _auto_adapt;
201+ JfrCPUSamplerThrottle _throttle;
180202 volatile int64_t _current_sampling_period_ns;
181203 volatile bool _disenrolled;
182204 // top bit is used to indicate that no signal handler should proceed
@@ -187,17 +209,17 @@ class JfrCPUSamplerThread : public NonJavaThread {
187209
188210 static const u4 STOP_SIGNAL_BIT = 0x80000000 ;
189211
190- JfrCPUSamplerThread (double rate, bool auto_adapt );
212+ JfrCPUSamplerThread (JfrCPUSamplerThrottle& throttle );
191213
192214 void start_thread ();
193215
194216 void enroll ();
195217 void disenroll ();
196218 void update_all_thread_timers ();
197219
198- void auto_adapt_period_if_needed ();
220+ void recompute_period_if_needed ();
199221
200- void set_rate ( double rate, bool auto_adapt );
222+ void set_throttle (JfrCPUSamplerThrottle& throttle );
201223 int64_t get_sampling_period () const { return Atomic::load (&_current_sampling_period_ns); };
202224
203225 void sample_thread (JfrSampleRequest& request, void * ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now);
@@ -231,18 +253,16 @@ class JfrCPUSamplerThread : public NonJavaThread {
231253 void trigger_async_processing_of_cpu_time_jfr_requests ();
232254};
233255
234- JfrCPUSamplerThread::JfrCPUSamplerThread (double rate, bool auto_adapt ) :
256+ JfrCPUSamplerThread::JfrCPUSamplerThread (JfrCPUSamplerThrottle& throttle ) :
235257 _sample(),
236258 _sampler_thread(nullptr ),
237- _rate(rate),
238- _auto_adapt(auto_adapt),
239- _current_sampling_period_ns(compute_sampling_period(rate)),
259+ _throttle(throttle),
260+ _current_sampling_period_ns(throttle.compute_sampling_period()),
240261 _disenrolled(true ),
241262 _active_signal_handlers(STOP_SIGNAL_BIT),
242263 _is_async_processing_of_cpu_time_jfr_requests_triggered(false ),
243264 _warned_about_timer_creation_failure(false ),
244265 _signal_handler_installed(false ) {
245- assert (rate >= 0 , " invariant" );
246266}
247267
248268void JfrCPUSamplerThread::trigger_async_processing_of_cpu_time_jfr_requests () {
@@ -321,17 +341,17 @@ void JfrCPUSamplerThread::disenroll() {
321341void JfrCPUSamplerThread::run () {
322342 assert (_sampler_thread == nullptr , " invariant" );
323343 _sampler_thread = this ;
324- int64_t last_auto_adapt_check = os::javaTimeNanos ();
344+ int64_t last_recompute_check = os::javaTimeNanos ();
325345 while (true ) {
326346 if (!_sample.trywait ()) {
327347 // disenrolled
328348 _sample.wait ();
329349 }
330350 _sample.signal ();
331351
332- if (os::javaTimeNanos () - last_auto_adapt_check > AUTOADAPT_INTERVAL_MS * 1000000 ) {
333- auto_adapt_period_if_needed ();
334- last_auto_adapt_check = os::javaTimeNanos ();
352+ if (os::javaTimeNanos () - last_recompute_check > RECOMPUTE_INTERVAL_MS * 1000000 ) {
353+ recompute_period_if_needed ();
354+ last_recompute_check = os::javaTimeNanos ();
335355 }
336356
337357 if (Atomic::cmpxchg (&_is_async_processing_of_cpu_time_jfr_requests_triggered, true , false )) {
@@ -442,42 +462,50 @@ JfrCPUTimeThreadSampling::~JfrCPUTimeThreadSampling() {
442462 }
443463}
444464
445- void JfrCPUTimeThreadSampling::create_sampler (double rate, bool auto_adapt ) {
465+ void JfrCPUTimeThreadSampling::create_sampler (JfrCPUSamplerThrottle& throttle ) {
446466 assert (_sampler == nullptr , " invariant" );
447- _sampler = new JfrCPUSamplerThread (rate, auto_adapt );
467+ _sampler = new JfrCPUSamplerThread (throttle );
448468 _sampler->start_thread ();
449469 _sampler->enroll ();
450470}
451471
452- void JfrCPUTimeThreadSampling::update_run_state (double rate, bool auto_adapt ) {
453- if (rate != 0 ) {
472+ void JfrCPUTimeThreadSampling::update_run_state (JfrCPUSamplerThrottle& throttle ) {
473+ if (throttle. enabled () ) {
454474 if (_sampler == nullptr ) {
455- create_sampler (rate, auto_adapt );
475+ create_sampler (throttle );
456476 } else {
457- _sampler->set_rate (rate, auto_adapt );
477+ _sampler->set_throttle (throttle );
458478 _sampler->enroll ();
459479 }
460480 return ;
461481 }
462482 if (_sampler != nullptr ) {
463- _sampler->set_rate (rate /* 0 */ , auto_adapt );
483+ _sampler->set_throttle (throttle );
464484 _sampler->disenroll ();
465485 }
466486}
467487
468- void JfrCPUTimeThreadSampling::set_rate (double rate, bool auto_adapt) {
469- assert (rate >= 0 , " invariant" );
488+ void JfrCPUTimeThreadSampling::set_rate (double rate) {
489+ if (_instance == nullptr ) {
490+ return ;
491+ }
492+ JfrCPUSamplerThrottle throttle (rate);
493+ instance ().set_throttle_value (throttle);
494+ }
495+
496+ void JfrCPUTimeThreadSampling::set_period (u8 nanos) {
470497 if (_instance == nullptr ) {
471498 return ;
472499 }
473- instance ().set_rate_value (rate, auto_adapt);
500+ JfrCPUSamplerThrottle throttle (nanos);
501+ instance ().set_throttle_value (throttle);
474502}
475503
476- void JfrCPUTimeThreadSampling::set_rate_value ( double rate, bool auto_adapt ) {
504+ void JfrCPUTimeThreadSampling::set_throttle_value (JfrCPUSamplerThrottle& throttle ) {
477505 if (_sampler != nullptr ) {
478- _sampler->set_rate (rate, auto_adapt );
506+ _sampler->set_throttle (throttle );
479507 }
480- update_run_state (rate, auto_adapt );
508+ update_run_state (throttle );
481509}
482510
483511void JfrCPUTimeThreadSampling::on_javathread_create (JavaThread *thread) {
@@ -704,24 +732,21 @@ void JfrCPUSamplerThread::stop_timer() {
704732 VMThread::execute (&op);
705733}
706734
707- void JfrCPUSamplerThread::auto_adapt_period_if_needed () {
735+ void JfrCPUSamplerThread::recompute_period_if_needed () {
708736 int64_t current_period = get_sampling_period ();
709- if (_auto_adapt || current_period == -1 ) {
710- int64_t period = compute_sampling_period (_rate);
711- if (period != current_period) {
712- Atomic::store (&_current_sampling_period_ns, period);
713- update_all_thread_timers ();
714- }
737+ int64_t period = _throttle.compute_sampling_period ();
738+ if (period != current_period) {
739+ Atomic::store (&_current_sampling_period_ns, period);
740+ update_all_thread_timers ();
715741 }
716742}
717743
718- void JfrCPUSamplerThread::set_rate (double rate, bool auto_adapt) {
719- _rate = rate;
720- _auto_adapt = auto_adapt;
721- if (_rate > 0 && Atomic::load_acquire (&_disenrolled) == false ) {
722- auto_adapt_period_if_needed ();
744+ void JfrCPUSamplerThread::set_throttle (JfrCPUSamplerThrottle& throttle) {
745+ _throttle = throttle;
746+ if (_throttle.enabled () && Atomic::load_acquire (&_disenrolled) == false ) {
747+ recompute_period_if_needed ();
723748 } else {
724- Atomic::store (&_current_sampling_period_ns, compute_sampling_period (rate ));
749+ Atomic::store (&_current_sampling_period_ns, _throttle. compute_sampling_period ());
725750 }
726751}
727752
@@ -765,12 +790,18 @@ void JfrCPUTimeThreadSampling::destroy() {
765790 _instance = nullptr ;
766791}
767792
768- void JfrCPUTimeThreadSampling::set_rate (double rate, bool auto_adapt ) {
793+ void JfrCPUTimeThreadSampling::set_rate (double rate) {
769794 if (rate != 0 ) {
770795 warn ();
771796 }
772797}
773798
799+ void JfrCPUTimeThreadSampling::set_period (u8 period_nanos) {
800+ if (period_nanos != 0 ) {
801+ warn ();
802+ }
803+ }
804+
774805void JfrCPUTimeThreadSampling::on_javathread_create (JavaThread* thread) {
775806}
776807
0 commit comments