diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp
index 0157d354f40..e900d5695ae 100644
--- a/src/hotspot/os/posix/signals_posix.cpp
+++ b/src/hotspot/os/posix/signals_posix.cpp
@@ -1505,14 +1505,6 @@ bool PosixSignals::is_sig_ignored(int sig) {
}
}
-void* PosixSignals::get_signal_handler_for_signal(int sig) {
- struct sigaction oact;
- if (sigaction(sig, (struct sigaction*)nullptr, &oact) == -1) {
- return nullptr;
- }
- return get_signal_handler(&oact);
-}
-
static void signal_sets_init() {
sigemptyset(&preinstalled_sigs);
diff --git a/src/hotspot/os/posix/signals_posix.hpp b/src/hotspot/os/posix/signals_posix.hpp
index c1cb70df153..9deade4db18 100644
--- a/src/hotspot/os/posix/signals_posix.hpp
+++ b/src/hotspot/os/posix/signals_posix.hpp
@@ -52,8 +52,6 @@ public:
static bool is_sig_ignored(int sig);
- static void* get_signal_handler_for_signal(int sig);
-
static void hotspot_sigmask(Thread* thread);
static void print_signal_handler(outputStream* st, int sig, char* buf, size_t buflen);
diff --git a/src/hotspot/share/jfr/jfr.inline.hpp b/src/hotspot/share/jfr/jfr.inline.hpp
index 5b6fc62d0ea..bdb47f600e6 100644
--- a/src/hotspot/share/jfr/jfr.inline.hpp
+++ b/src/hotspot/share/jfr/jfr.inline.hpp
@@ -32,8 +32,7 @@
inline bool Jfr::has_sample_request(JavaThread* jt) {
assert(jt != nullptr, "invariant");
- JfrThreadLocal* tl = jt->jfr_thread_local();
- return tl->has_sample_request() || tl->has_cpu_time_jfr_requests();
+ return jt->jfr_thread_local()->has_sample_request();
}
inline void Jfr::check_and_process_sample_request(JavaThread* jt) {
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
index bc2412a90c1..6f1c1936574 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp
@@ -24,7 +24,6 @@
#include "jfr/jfr.hpp"
#include "jfr/jfrEvents.hpp"
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/recorder/jfrEventSetting.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
@@ -170,11 +169,6 @@ NO_TRANSITION(jboolean, jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_ty
return JNI_TRUE;
NO_TRANSITION_END
-JVM_ENTRY_NO_ENV(void, jfr_set_cpu_throttle(JNIEnv* env, jclass jvm, jdouble rate, jboolean auto_adapt))
- JfrEventSetting::set_enabled(JfrCPUTimeSampleEvent, rate > 0);
- JfrCPUTimeThreadSampling::set_rate(rate, auto_adapt == JNI_TRUE);
-JVM_END
-
NO_TRANSITION(void, jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong event_type_id, jlong value))
JfrEventSetting::set_miscellaneous(event_type_id, value);
const JfrEventId typed_event_id = (JfrEventId)event_type_id;
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp
index dbea7f0180d..9c78c6239d4 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethod.hpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethod.hpp
@@ -129,8 +129,6 @@ jlong JNICALL jfr_get_unloaded_event_classes_count(JNIEnv* env, jclass jvm);
jboolean JNICALL jfr_set_throttle(JNIEnv* env, jclass jvm, jlong event_type_id, jlong event_sample_size, jlong period_ms);
-void JNICALL jfr_set_cpu_throttle(JNIEnv* env, jclass jvm, jdouble rate, jboolean auto_adapt);
-
void JNICALL jfr_set_miscellaneous(JNIEnv* env, jclass jvm, jlong id, jlong value);
void JNICALL jfr_emit_old_object_samples(JNIEnv* env, jclass jvm, jlong cutoff_ticks, jboolean, jboolean);
diff --git a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
index 82ef93d95b2..33a564dee2f 100644
--- a/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
+++ b/src/hotspot/share/jfr/jni/jfrJniMethodRegistration.cpp
@@ -83,7 +83,6 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
(char*)"getUnloadedEventClassCount", (char*)"()J", (void*)jfr_get_unloaded_event_classes_count,
(char*)"setMiscellaneous", (char*)"(JJ)V", (void*)jfr_set_miscellaneous,
(char*)"setThrottle", (char*)"(JJJ)Z", (void*)jfr_set_throttle,
- (char*)"setCPUThrottle", (char*)"(DZ)V", (void*)jfr_set_cpu_throttle,
(char*)"emitOldObjectSamples", (char*)"(JZZ)V", (void*)jfr_emit_old_object_samples,
(char*)"shouldRotateDisk", (char*)"()Z", (void*)jfr_should_rotate_disk,
(char*)"exclude", (char*)"(Ljava/lang/Thread;)V", (void*)jfr_exclude_thread,
diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml
index 03daca946f6..9c04ec3dca1 100644
--- a/src/hotspot/share/jfr/metadata/metadata.xml
+++ b/src/hotspot/share/jfr/metadata/metadata.xml
@@ -962,22 +962,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp
deleted file mode 100644
index ae8877ee3f2..00000000000
--- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
-#include "logging/log.hpp"
-
-
-#if defined(LINUX)
-#include "jfr/periodic/sampling/jfrThreadSampling.hpp"
-#include "jfr/support/jfrThreadLocal.hpp"
-#include "jfr/utilities/jfrTime.hpp"
-#include "jfr/utilities/jfrThreadIterator.hpp"
-#include "jfr/utilities/jfrTypes.hpp"
-#include "jfrfiles/jfrEventClasses.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/javaThread.hpp"
-#include "runtime/osThread.hpp"
-#include "runtime/safepointMechanism.inline.hpp"
-#include "runtime/threadSMR.hpp"
-#include "runtime/vmOperation.hpp"
-#include "runtime/vmThread.hpp"
-#include "utilities/ticks.hpp"
-
-#include "signals_posix.hpp"
-
-static const int64_t AUTOADAPT_INTERVAL_MS = 100;
-
-static bool is_excluded(JavaThread* jt) {
- return jt->is_hidden_from_external_view() ||
- jt->jfr_thread_local()->is_excluded() ||
- jt->is_JfrRecorder_thread();
-}
-
-static JavaThread* get_java_thread_if_valid() {
- Thread* raw_thread = Thread::current_or_null_safe();
- if (raw_thread == nullptr) {
- // probably while shutting down
- return nullptr;
- }
- assert(raw_thread->is_Java_thread(), "invariant");
- JavaThread* jt = JavaThread::cast(raw_thread);
- if (is_excluded(jt) || jt->is_exiting()) {
- return nullptr;
- }
- return jt;
-}
-
-JfrCPUTimeTraceQueue::JfrCPUTimeTraceQueue(u4 capacity) :
- _capacity(capacity), _head(0), _lost_samples(0) {
- _data = JfrCHeapObj::new_array(capacity);
-}
-
-JfrCPUTimeTraceQueue::~JfrCPUTimeTraceQueue() {
- JfrCHeapObj::free(_data, _capacity * sizeof(JfrCPUTimeSampleRequest));
-}
-
-bool JfrCPUTimeTraceQueue::enqueue(JfrCPUTimeSampleRequest& request) {
- assert(JavaThread::current()->jfr_thread_local()->is_cpu_time_jfr_enqueue_locked(), "invariant");
- assert(&JavaThread::current()->jfr_thread_local()->cpu_time_jfr_queue() == this, "invariant");
- u4 elementIndex;
- do {
- elementIndex = Atomic::load_acquire(&_head);
- if (elementIndex >= _capacity) {
- return false;
- }
- } while (Atomic::cmpxchg(&_head, elementIndex, elementIndex + 1) != elementIndex);
- _data[elementIndex] = request;
- return true;
-}
-
-JfrCPUTimeSampleRequest& JfrCPUTimeTraceQueue::at(u4 index) {
- assert(index < _head, "invariant");
- return _data[index];
-}
-
-static volatile u4 _lost_samples_sum = 0;
-
-u4 JfrCPUTimeTraceQueue::size() const {
- return Atomic::load_acquire(&_head);
-}
-
-void JfrCPUTimeTraceQueue::set_size(u4 size) {
- Atomic::release_store(&_head, size);
-}
-
-u4 JfrCPUTimeTraceQueue::capacity() const {
- return _capacity;
-}
-
-void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) {
- _head = 0;
- JfrCHeapObj::free(_data, _capacity * sizeof(JfrCPUTimeSampleRequest));
- _data = JfrCHeapObj::new_array(capacity);
- _capacity = capacity;
-}
-
-bool JfrCPUTimeTraceQueue::is_empty() const {
- return Atomic::load_acquire(&_head) == 0;
-}
-
-u4 JfrCPUTimeTraceQueue::lost_samples() const {
- return Atomic::load(&_lost_samples);
-}
-
-void JfrCPUTimeTraceQueue::increment_lost_samples() {
- Atomic::inc(&_lost_samples_sum);
- Atomic::inc(&_lost_samples);
-}
-
-u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() {
- return Atomic::xchg(&_lost_samples, (u4)0);
-}
-
-void JfrCPUTimeTraceQueue::resize(u4 capacity) {
- if (capacity != _capacity) {
- set_capacity(capacity);
- }
-}
-
-void JfrCPUTimeTraceQueue::resize_for_period(u4 period_millis) {
- u4 capacity = CPU_TIME_QUEUE_CAPACITY;
- if (period_millis > 0 && period_millis < 10) {
- capacity = (u4) ((double) capacity * 10 / period_millis);
- }
- resize(capacity);
-}
-
-void JfrCPUTimeTraceQueue::clear() {
- Atomic::release_store(&_head, (u4)0);
-}
-
-static int64_t compute_sampling_period(double rate) {
- if (rate == 0) {
- return 0;
- }
- return os::active_processor_count() * 1000000000.0 / rate;
-}
-
-class JfrCPUSamplerThread : public NonJavaThread {
- friend class JfrCPUTimeThreadSampling;
- private:
- Semaphore _sample;
- NonJavaThread* _sampler_thread;
- double _rate;
- bool _auto_adapt;
- volatile int64_t _current_sampling_period_ns;
- volatile bool _disenrolled;
- // top bit is used to indicate that no signal handler should proceed
- volatile u4 _active_signal_handlers;
- volatile bool _is_async_processing_of_cpu_time_jfr_requests_triggered;
- volatile bool _warned_about_timer_creation_failure;
- volatile bool _signal_handler_installed;
-
- static const u4 STOP_SIGNAL_BIT = 0x80000000;
-
- JfrCPUSamplerThread(double rate, bool auto_adapt);
-
- void start_thread();
-
- void enroll();
- void disenroll();
- void update_all_thread_timers();
-
- void auto_adapt_period_if_needed();
-
- void set_rate(double rate, bool auto_adapt);
- int64_t get_sampling_period() const { return Atomic::load(&_current_sampling_period_ns); };
-
- void sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now);
-
- // process the queues for all threads that are in native state (and requested to be processed)
- void stackwalk_threads_in_native();
- bool create_timer_for_thread(JavaThread* thread, timer_t &timerid);
-
- void stop_signal_handlers();
-
- // returns false if the stop signal bit was set, true otherwise
- bool increment_signal_handler_count();
-
- void decrement_signal_handler_count();
-
- void initialize_active_signal_handler_counter();
-
-protected:
- virtual void post_run();
-public:
- virtual const char* name() const { return "JFR CPU Sampler Thread"; }
- virtual const char* type_name() const { return "JfrCPUTimeSampler"; }
- void run();
- void on_javathread_create(JavaThread* thread);
- void on_javathread_terminate(JavaThread* thread);
-
- void handle_timer_signal(siginfo_t* info, void* context);
- bool init_timers();
- void stop_timer();
-
- void trigger_async_processing_of_cpu_time_jfr_requests();
-};
-
-JfrCPUSamplerThread::JfrCPUSamplerThread(double rate, bool auto_adapt) :
- _sample(),
- _sampler_thread(nullptr),
- _rate(rate),
- _auto_adapt(auto_adapt),
- _current_sampling_period_ns(compute_sampling_period(rate)),
- _disenrolled(true),
- _active_signal_handlers(STOP_SIGNAL_BIT),
- _is_async_processing_of_cpu_time_jfr_requests_triggered(false),
- _warned_about_timer_creation_failure(false),
- _signal_handler_installed(false) {
- assert(rate >= 0, "invariant");
-}
-
-void JfrCPUSamplerThread::trigger_async_processing_of_cpu_time_jfr_requests() {
- Atomic::release_store(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true);
-}
-
-void JfrCPUSamplerThread::on_javathread_create(JavaThread* thread) {
- if (thread->is_hidden_from_external_view() || thread->is_JfrRecorder_thread() ||
- !Atomic::load_acquire(&_signal_handler_installed)) {
- return;
- }
- JfrThreadLocal* tl = thread->jfr_thread_local();
- assert(tl != nullptr, "invariant");
- tl->cpu_time_jfr_queue().resize_for_period(_current_sampling_period_ns / 1000000);
- timer_t timerid;
- if (create_timer_for_thread(thread, timerid)) {
- tl->set_cpu_timer(&timerid);
- } else {
- if (!Atomic::or_then_fetch(&_warned_about_timer_creation_failure, true)) {
- log_warning(jfr)("Failed to create timer for a thread");
- }
- tl->deallocate_cpu_time_jfr_queue();
- }
-}
-
-void JfrCPUSamplerThread::on_javathread_terminate(JavaThread* thread) {
- JfrThreadLocal* tl = thread->jfr_thread_local();
- assert(tl != nullptr, "invariant");
- timer_t* timer = tl->cpu_timer();
- if (timer == nullptr) {
- return; // no timer was created for this thread
- }
- tl->unset_cpu_timer();
- tl->deallocate_cpu_time_jfr_queue();
- s4 lost_samples = tl->cpu_time_jfr_queue().lost_samples();
- if (lost_samples > 0) {
- JfrCPUTimeThreadSampling::send_lost_event(JfrTicks::now(), JfrThreadLocal::thread_id(thread), lost_samples);
- }
-}
-
-void JfrCPUSamplerThread::start_thread() {
- if (os::create_thread(this, os::os_thread)) {
- os::start_thread(this);
- } else {
- log_error(jfr)("Failed to create thread for thread sampling");
- }
-}
-
-void JfrCPUSamplerThread::enroll() {
- if (Atomic::cmpxchg(&_disenrolled, true, false)) {
- Atomic::store(&_warned_about_timer_creation_failure, false);
- initialize_active_signal_handler_counter();
- log_trace(jfr)("Enrolling CPU thread sampler");
- _sample.signal();
- if (!init_timers()) {
- log_error(jfr)("Failed to initialize timers for CPU thread sampler");
- disenroll();
- return;
- }
- log_trace(jfr)("Enrolled CPU thread sampler");
- }
-}
-
-void JfrCPUSamplerThread::disenroll() {
- if (!Atomic::cmpxchg(&_disenrolled, false, true)) {
- log_trace(jfr)("Disenrolling CPU thread sampler");
- if (Atomic::load_acquire(&_signal_handler_installed)) {
- stop_timer();
- stop_signal_handlers();
- }
- _sample.wait();
- log_trace(jfr)("Disenrolled CPU thread sampler");
- }
-}
-
-void JfrCPUSamplerThread::run() {
- assert(_sampler_thread == nullptr, "invariant");
- _sampler_thread = this;
- int64_t last_auto_adapt_check = os::javaTimeNanos();
- while (true) {
- if (!_sample.trywait()) {
- // disenrolled
- _sample.wait();
- }
- _sample.signal();
-
- if (os::javaTimeNanos() - last_auto_adapt_check > AUTOADAPT_INTERVAL_MS * 1000000) {
- auto_adapt_period_if_needed();
- last_auto_adapt_check = os::javaTimeNanos();
- }
-
- if (Atomic::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) {
- stackwalk_threads_in_native();
- }
- os::naked_sleep(100);
- }
-}
-
-void JfrCPUSamplerThread::stackwalk_threads_in_native() {
- ResourceMark rm;
- // Required to prevent JFR from sampling through an ongoing safepoint
- MutexLocker tlock(Threads_lock);
- ThreadsListHandle tlh;
- Thread* current = Thread::current();
- for (size_t i = 0; i < tlh.list()->length(); i++) {
- JavaThread* jt = tlh.list()->thread_at(i);
- JfrThreadLocal* tl = jt->jfr_thread_local();
- if (tl->wants_async_processing_of_cpu_time_jfr_requests()) {
- if (jt->thread_state() != _thread_in_native || !tl->try_acquire_cpu_time_jfr_dequeue_lock()) {
- tl->set_do_async_processing_of_cpu_time_jfr_requests(false);
- continue;
- }
- if (jt->has_last_Java_frame()) {
- JfrThreadSampling::process_cpu_time_request(jt, tl, current, false);
- } else {
- tl->set_do_async_processing_of_cpu_time_jfr_requests(false);
- }
- tl->release_cpu_time_jfr_queue_lock();
- }
- }
-}
-
-static volatile size_t count = 0;
-
-void JfrCPUTimeThreadSampling::send_empty_event(const JfrTicks &start_time, traceid tid, Tickspan cpu_time_period) {
- EventCPUTimeSample event(UNTIMED);
- event.set_failed(true);
- event.set_starttime(start_time);
- event.set_eventThread(tid);
- event.set_stackTrace(0);
- event.set_samplingPeriod(cpu_time_period);
- event.set_biased(false);
- event.commit();
-}
-
-
-static volatile size_t biased_count = 0;
-
-void JfrCPUTimeThreadSampling::send_event(const JfrTicks &start_time, traceid sid, traceid tid, Tickspan cpu_time_period, bool biased) {
- EventCPUTimeSample event(UNTIMED);
- event.set_failed(false);
- event.set_starttime(start_time);
- event.set_eventThread(tid);
- event.set_stackTrace(sid);
- event.set_samplingPeriod(cpu_time_period);
- event.set_biased(biased);
- event.commit();
- Atomic::inc(&count);
- if (biased) {
- Atomic::inc(&biased_count);
- }
- if (Atomic::load(&count) % 1000 == 0) {
- log_debug(jfr)("CPU thread sampler sent %zu events, lost %d, biased %zu\n", Atomic::load(&count), Atomic::load(&_lost_samples_sum), Atomic::load(&biased_count));
- }
-}
-
-void JfrCPUTimeThreadSampling::send_lost_event(const JfrTicks &time, traceid tid, s4 lost_samples) {
- if (!EventCPUTimeSamplesLost::is_enabled()) {
- return;
- }
- EventCPUTimeSamplesLost event(UNTIMED);
- event.set_starttime(time);
- event.set_lostSamples(lost_samples);
- event.set_eventThread(tid);
- event.commit();
-}
-
-void JfrCPUSamplerThread::post_run() {
- this->NonJavaThread::post_run();
- delete this;
-}
-
-static JfrCPUTimeThreadSampling* _instance = nullptr;
-
-JfrCPUTimeThreadSampling& JfrCPUTimeThreadSampling::instance() {
- return *_instance;
-}
-
-JfrCPUTimeThreadSampling* JfrCPUTimeThreadSampling::create() {
- assert(_instance == nullptr, "invariant");
- _instance = new JfrCPUTimeThreadSampling();
- return _instance;
-}
-
-void JfrCPUTimeThreadSampling::destroy() {
- if (_instance != nullptr) {
- delete _instance;
- _instance = nullptr;
- }
-}
-
-JfrCPUTimeThreadSampling::JfrCPUTimeThreadSampling() : _sampler(nullptr) {}
-
-JfrCPUTimeThreadSampling::~JfrCPUTimeThreadSampling() {
- if (_sampler != nullptr) {
- _sampler->disenroll();
- }
-}
-
-void JfrCPUTimeThreadSampling::create_sampler(double rate, bool auto_adapt) {
- assert(_sampler == nullptr, "invariant");
- _sampler = new JfrCPUSamplerThread(rate, auto_adapt);
- _sampler->start_thread();
- _sampler->enroll();
-}
-
-void JfrCPUTimeThreadSampling::update_run_state(double rate, bool auto_adapt) {
- if (rate != 0) {
- if (_sampler == nullptr) {
- create_sampler(rate, auto_adapt);
- } else {
- _sampler->set_rate(rate, auto_adapt);
- _sampler->enroll();
- }
- return;
- }
- if (_sampler != nullptr) {
- _sampler->set_rate(rate /* 0 */, auto_adapt);
- _sampler->disenroll();
- }
-}
-
-void JfrCPUTimeThreadSampling::set_rate(double rate, bool auto_adapt) {
- assert(rate >= 0, "invariant");
- if (_instance == nullptr) {
- return;
- }
- instance().set_rate_value(rate, auto_adapt);
-}
-
-void JfrCPUTimeThreadSampling::set_rate_value(double rate, bool auto_adapt) {
- if (_sampler != nullptr) {
- _sampler->set_rate(rate, auto_adapt);
- }
- update_run_state(rate, auto_adapt);
-}
-
-void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread *thread) {
- if (_instance != nullptr && _instance->_sampler != nullptr) {
- _instance->_sampler->on_javathread_create(thread);
- }
-}
-
-void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread *thread) {
- if (_instance != nullptr && _instance->_sampler != nullptr) {
- _instance->_sampler->on_javathread_terminate(thread);
- }
-}
-
-void JfrCPUTimeThreadSampling::trigger_async_processing_of_cpu_time_jfr_requests() {
- if (_instance != nullptr && _instance->_sampler != nullptr) {
- _instance->_sampler->trigger_async_processing_of_cpu_time_jfr_requests();
- }
-}
-
-void handle_timer_signal(int signo, siginfo_t* info, void* context) {
- assert(_instance != nullptr, "invariant");
- _instance->handle_timer_signal(info, context);
-}
-
-
-void JfrCPUTimeThreadSampling::handle_timer_signal(siginfo_t* info, void* context) {
- if (info->si_code != SI_TIMER) {
- // not the signal we are interested in
- return;
- }
- assert(_sampler != nullptr, "invariant");
-
- if (!_sampler->increment_signal_handler_count()) {
- return;
- }
- _sampler->handle_timer_signal(info, context);
- _sampler->decrement_signal_handler_count();
-}
-
-void JfrCPUSamplerThread::sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now) {
- JfrSampleRequestBuilder::build_cpu_time_sample_request(request, ucontext, jt, jt->jfr_thread_local(), now);
-}
-
-static bool check_state(JavaThread* thread) {
- switch (thread->thread_state()) {
- case _thread_in_Java:
- case _thread_in_native:
- return true;
- default:
- return false;
- }
-}
-
-void JfrCPUSamplerThread::handle_timer_signal(siginfo_t* info, void* context) {
- JfrTicks now = JfrTicks::now();
- JavaThread* jt = get_java_thread_if_valid();
- if (jt == nullptr) {
- return;
- }
- JfrThreadLocal* tl = jt->jfr_thread_local();
- JfrCPUTimeTraceQueue& queue = tl->cpu_time_jfr_queue();
- if (!check_state(jt)) {
- queue.increment_lost_samples();
- return;
- }
- if (!tl->try_acquire_cpu_time_jfr_enqueue_lock()) {
- queue.increment_lost_samples();
- return;
- }
-
- JfrCPUTimeSampleRequest request;
- // the sampling period might be too low for the current Linux configuration
- // so samples might be skipped and we have to compute the actual period
- int64_t period = get_sampling_period() * (info->si_overrun + 1);
- request._cpu_time_period = Ticks(period / 1000000000.0 * JfrTime::frequency()) - Ticks(0);
- sample_thread(request._request, context, jt, tl, now);
-
- if (queue.enqueue(request)) {
- if (queue.size() == 1) {
- tl->set_has_cpu_time_jfr_requests(true);
- SafepointMechanism::arm_local_poll_release(jt);
- }
- } else {
- queue.increment_lost_samples();
- }
-
- if (jt->thread_state() == _thread_in_native) {
- if (!tl->wants_async_processing_of_cpu_time_jfr_requests()) {
- tl->set_do_async_processing_of_cpu_time_jfr_requests(true);
- JfrCPUTimeThreadSampling::trigger_async_processing_of_cpu_time_jfr_requests();
- }
- } else {
- tl->set_do_async_processing_of_cpu_time_jfr_requests(false);
- }
-
- tl->release_cpu_time_jfr_queue_lock();
-}
-
-static const int SIG = SIGPROF;
-
-static void set_timer_time(timer_t timerid, int64_t period_nanos) {
- struct itimerspec its;
- if (period_nanos == 0) {
- its.it_interval.tv_sec = 0;
- its.it_interval.tv_nsec = 0;
- } else {
- its.it_interval.tv_sec = period_nanos / NANOSECS_PER_SEC;
- its.it_interval.tv_nsec = period_nanos % NANOSECS_PER_SEC;
- }
- its.it_value = its.it_interval;
- if (timer_settime(timerid, 0, &its, nullptr) == -1) {
- warning("Failed to set timer for thread sampling: %s", os::strerror(os::get_last_error()));
- }
-}
-
-bool JfrCPUSamplerThread::create_timer_for_thread(JavaThread* thread, timer_t& timerid) {
- struct sigevent sev;
- sev.sigev_notify = SIGEV_THREAD_ID;
- sev.sigev_signo = SIG;
- sev.sigev_value.sival_ptr = nullptr;
- ((int*)&sev.sigev_notify)[1] = thread->osthread()->thread_id();
- clockid_t clock;
- int err = pthread_getcpuclockid(thread->osthread()->pthread_id(), &clock);
- if (err != 0) {
- log_error(jfr)("Failed to get clock for thread sampling: %s", os::strerror(err));
- return false;
- }
- if (timer_create(clock, &sev, &timerid) < 0) {
- return false;
- }
- int64_t period = get_sampling_period();
- if (period != 0) {
- set_timer_time(timerid, period);
- }
- return true;
-}
-
-
-void JfrCPUSamplerThread::stop_signal_handlers() {
- // set the stop signal bit
- Atomic::or_then_fetch(&_active_signal_handlers, STOP_SIGNAL_BIT, memory_order_acq_rel);
- while (Atomic::load_acquire(&_active_signal_handlers) > STOP_SIGNAL_BIT) {
- // wait for all signal handlers to finish
- os::naked_short_nanosleep(1000);
- }
-}
-
-// returns false if the stop signal bit was set, true otherwise
-bool JfrCPUSamplerThread::increment_signal_handler_count() {
- // increment the count of active signal handlers
- u4 old_value = Atomic::fetch_then_add(&_active_signal_handlers, (u4)1, memory_order_acq_rel);
- if ((old_value & STOP_SIGNAL_BIT) != 0) {
- // if the stop signal bit was set, we are not allowed to increment
- Atomic::dec(&_active_signal_handlers, memory_order_acq_rel);
- return false;
- }
- return true;
-}
-
-void JfrCPUSamplerThread::decrement_signal_handler_count() {
- Atomic::dec(&_active_signal_handlers, memory_order_acq_rel);
-}
-
-void JfrCPUSamplerThread::initialize_active_signal_handler_counter() {
- Atomic::release_store(&_active_signal_handlers, (u4)0);
-}
-
-class VM_JFRInitializeCPUTimeSampler : public VM_Operation {
- private:
- JfrCPUSamplerThread* const _sampler;
-
- public:
- VM_JFRInitializeCPUTimeSampler(JfrCPUSamplerThread* sampler) : _sampler(sampler) {}
-
- VMOp_Type type() const { return VMOp_JFRInitializeCPUTimeSampler; }
- void doit() {
- JfrJavaThreadIterator iter;
- while (iter.has_next()) {
- _sampler->on_javathread_create(iter.next());
- }
- };
-};
-
-bool JfrCPUSamplerThread::init_timers() {
- // install sig handler for sig
- void* prev_handler = PosixSignals::get_signal_handler_for_signal(SIG);
- if ((prev_handler != SIG_DFL && prev_handler != SIG_IGN && prev_handler != (void*)::handle_timer_signal) ||
- PosixSignals::install_generic_signal_handler(SIG, (void*)::handle_timer_signal) == (void*)-1) {
- log_error(jfr)("Conflicting SIGPROF handler found: %p. CPUTimeSample events will not be recorded", prev_handler);
- return false;
- }
- Atomic::release_store(&_signal_handler_installed, true);
- VM_JFRInitializeCPUTimeSampler op(this);
- VMThread::execute(&op);
- return true;
-}
-
-class VM_JFRTerminateCPUTimeSampler : public VM_Operation {
- private:
- JfrCPUSamplerThread* const _sampler;
-
- public:
- VM_JFRTerminateCPUTimeSampler(JfrCPUSamplerThread* sampler) : _sampler(sampler) {}
-
- VMOp_Type type() const { return VMOp_JFRTerminateCPUTimeSampler; }
- void doit() {
- JfrJavaThreadIterator iter;
- while (iter.has_next()) {
- JavaThread *thread = iter.next();
- JfrThreadLocal* tl = thread->jfr_thread_local();
- timer_t* timer = tl->cpu_timer();
- if (timer == nullptr) {
- continue;
- }
- timer_delete(*timer);
- tl->deallocate_cpu_time_jfr_queue();
- tl->unset_cpu_timer();
- }
- };
-};
-
-void JfrCPUSamplerThread::stop_timer() {
- VM_JFRTerminateCPUTimeSampler op(this);
- VMThread::execute(&op);
-}
-
-void JfrCPUSamplerThread::auto_adapt_period_if_needed() {
- int64_t current_period = get_sampling_period();
- if (_auto_adapt || current_period == -1) {
- int64_t period = compute_sampling_period(_rate);
- if (period != current_period) {
- Atomic::store(&_current_sampling_period_ns, period);
- update_all_thread_timers();
- }
- }
-}
-
-void JfrCPUSamplerThread::set_rate(double rate, bool auto_adapt) {
- _rate = rate;
- _auto_adapt = auto_adapt;
- if (_rate > 0 && Atomic::load_acquire(&_disenrolled) == false) {
- auto_adapt_period_if_needed();
- } else {
- Atomic::store(&_current_sampling_period_ns, compute_sampling_period(rate));
- }
-}
-
-void JfrCPUSamplerThread::update_all_thread_timers() {
- int64_t period_millis = get_sampling_period();
- ThreadsListHandle tlh;
- for (size_t i = 0; i < tlh.length(); i++) {
- JavaThread* thread = tlh.thread_at(i);
- JfrThreadLocal* tl = thread->jfr_thread_local();
- assert(tl != nullptr, "invariant");
- timer_t* timer = tl->cpu_timer();
- if (timer != nullptr) {
- set_timer_time(*timer, period_millis);
- }
- }
-}
-
-#else
-
-static void warn() {
- static bool displayed_warning = false;
- if (!displayed_warning) {
- warning("CPU time method sampling not supported in JFR on your platform");
- displayed_warning = true;
- }
-}
-
-static JfrCPUTimeThreadSampling* _instance = nullptr;
-
-JfrCPUTimeThreadSampling& JfrCPUTimeThreadSampling::instance() {
- return *_instance;
-}
-
-JfrCPUTimeThreadSampling* JfrCPUTimeThreadSampling::create() {
- _instance = new JfrCPUTimeThreadSampling();
- return _instance;
-}
-
-void JfrCPUTimeThreadSampling::destroy() {
- delete _instance;
- _instance = nullptr;
-}
-
-void JfrCPUTimeThreadSampling::set_rate(double rate, bool auto_adapt) {
- if (rate != 0) {
- warn();
- }
-}
-
-void JfrCPUTimeThreadSampling::on_javathread_create(JavaThread* thread) {
-}
-
-void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread* thread) {
-}
-
-#endif // defined(LINUX) && defined(INCLUDE_JFR)
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp
deleted file mode 100644
index 7c0545f4772..00000000000
--- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_JFR_PERIODIC_SAMPLING_JFRCPUTIMETHREADSAMPLER_HPP
-#define SHARE_JFR_PERIODIC_SAMPLING_JFRCPUTIMETHREADSAMPLER_HPP
-
-#include "jfr/utilities/jfrAllocation.hpp"
-
-class JavaThread;
-
-#if defined(LINUX)
-
-#include "jfr/periodic/sampling/jfrSampleRequest.hpp"
-#include "jfr/utilities/jfrTypes.hpp"
-
-struct JfrCPUTimeSampleRequest {
- JfrSampleRequest _request;
- Tickspan _cpu_time_period;
-
- JfrCPUTimeSampleRequest() {}
-};
-
-// Fixed size async-signal-safe SPSC linear queue backed by an array.
-// Designed to be only used under lock and read linearly
-class JfrCPUTimeTraceQueue {
-
- // the default queue capacity, scaled if the sampling period is smaller than 10ms
- // when the thread is started
- static const u4 CPU_TIME_QUEUE_CAPACITY = 500;
-
- JfrCPUTimeSampleRequest* _data;
- u4 _capacity;
- // next unfilled index
- volatile u4 _head;
-
- volatile u4 _lost_samples;
-
-public:
- JfrCPUTimeTraceQueue(u4 capacity);
-
- ~JfrCPUTimeTraceQueue();
-
- // signal safe, but can't be interleaved with dequeue
- bool enqueue(JfrCPUTimeSampleRequest& trace);
-
- JfrCPUTimeSampleRequest& at(u4 index);
-
- u4 size() const;
-
- void set_size(u4 size);
-
- u4 capacity() const;
-
- // deletes all samples in the queue
- void set_capacity(u4 capacity);
-
- bool is_empty() const;
-
- u4 lost_samples() const;
-
- void increment_lost_samples();
-
- // returns the previous lost samples count
- u4 get_and_reset_lost_samples();
-
- void resize(u4 capacity);
-
- void resize_for_period(u4 period_millis);
-
- void clear();
-
-};
-
-
-class JfrCPUSamplerThread;
-
-class JfrCPUTimeThreadSampling : public JfrCHeapObj {
- friend class JfrRecorder;
- private:
-
- JfrCPUSamplerThread* _sampler;
-
- void create_sampler(double rate, bool auto_adapt);
- void set_rate_value(double rate, bool auto_adapt);
-
- JfrCPUTimeThreadSampling();
- ~JfrCPUTimeThreadSampling();
-
- static JfrCPUTimeThreadSampling& instance();
- static JfrCPUTimeThreadSampling* create();
- static void destroy();
-
- void update_run_state(double rate, bool auto_adapt);
-
- public:
- static void set_rate(double rate, bool auto_adapt);
-
- static void on_javathread_create(JavaThread* thread);
- static void on_javathread_terminate(JavaThread* thread);
- void handle_timer_signal(siginfo_t* info, void* context);
-
- static void send_empty_event(const JfrTicks& start_time, traceid tid, Tickspan cpu_time_period);
- static void send_event(const JfrTicks& start_time, traceid sid, traceid tid, Tickspan cpu_time_period, bool biased);
- static void send_lost_event(const JfrTicks& time, traceid tid, s4 lost_samples);
-
- static void trigger_async_processing_of_cpu_time_jfr_requests();
-};
-
-#else
-
-// a basic implementation on other platforms that
-// emits warnings
-
-class JfrCPUTimeThreadSampling : public JfrCHeapObj {
- friend class JfrRecorder;
-private:
- static JfrCPUTimeThreadSampling& instance();
- static JfrCPUTimeThreadSampling* create();
- static void destroy();
-
- public:
- static void set_rate(double rate, bool auto_adapt);
-
- static void on_javathread_create(JavaThread* thread);
- static void on_javathread_terminate(JavaThread* thread);
-};
-
-#endif // defined(LINUX)
-
-
-#endif // SHARE_JFR_PERIODIC_SAMPLING_JFRCPUTIMETHREADSAMPLER_HPP
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.cpp
index 7049df0198b..f8e63e2e344 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.cpp
@@ -24,7 +24,6 @@
#include "asm/codeBuffer.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/periodic/sampling/jfrSampleRequest.hpp"
-#include "jfr/utilities/jfrTime.hpp"
#include "runtime/continuationEntry.hpp"
#include "runtime/frame.inline.hpp"
#include "runtime/javaThread.inline.hpp"
@@ -172,7 +171,7 @@ static bool build(JfrSampleRequest& request, intptr_t* fp, JavaThread* jt) {
assert(request._sample_sp != nullptr, "invariant");
assert(request._sample_pc != nullptr, "invariant");
assert(jt != nullptr, "invariant");
- assert(jt->thread_state() == _thread_in_Java || jt->thread_state() == _thread_in_native, "invariant");
+ assert(jt->thread_state() == _thread_in_Java, "invariant");
// 1. Interpreter frame?
if (is_interpreter(request)) {
@@ -304,33 +303,3 @@ JfrSampleResult JfrSampleRequestBuilder::build_java_sample_request(const void* u
}
return set_biased_java_sample(request, tl, jt);
}
-
-
-// A biased sample request is denoted by an empty bcp and an empty pc.
-static inline void set_cpu_time_biased_sample(JfrSampleRequest& request, JavaThread* jt) {
- if (request._sample_bcp != nullptr) {
- request._sample_bcp = nullptr;
- }
- assert(request._sample_bcp == nullptr, "invariant");
- request._sample_pc = nullptr;
-}
-
-void JfrSampleRequestBuilder::build_cpu_time_sample_request(JfrSampleRequest& request,
- void* ucontext,
- JavaThread* jt,
- JfrThreadLocal* tl,
- JfrTicks& now) {
- assert(jt != nullptr, "invariant");
- request._sample_ticks = now;
-
- // Prioritize the ljf, if one exists.
- request._sample_sp = jt->last_Java_sp();
- if (request._sample_sp == nullptr || !build_from_ljf(request, tl, jt)) {
- intptr_t* fp;
- request._sample_pc = os::fetch_frame_from_context(ucontext, reinterpret_cast(&request._sample_sp), &fp);
- assert(sp_in_stack(request, jt), "invariant");
- if (!build(request, fp, jt)) {
- set_cpu_time_biased_sample(request, jt);
- }
- }
-}
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.hpp
index 20e737e0cbf..6567e7f8bff 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.hpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrSampleRequest.hpp
@@ -81,11 +81,6 @@ class JfrSampleRequestBuilder : AllStatic {
static JfrSampleResult build_java_sample_request(const void* ucontext,
JfrThreadLocal* tl,
JavaThread* jt);
- static void build_cpu_time_sample_request(JfrSampleRequest &request,
- void* ucontext,
- JavaThread* jt,
- JfrThreadLocal* tl,
- JfrTicks& now);
};
#endif // SHARE_JFR_PERIODIC_SAMPLING_JFRSAMPLEREQUEST_HPP
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
index ddc9d59b295..aa72c29cf50 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.cpp
@@ -28,7 +28,6 @@
#include "code/nmethod.hpp"
#include "interpreter/interpreter.hpp"
#include "jfr/jfrEvents.hpp"
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jfr/periodic/sampling/jfrSampleMonitor.hpp"
#include "jfr/periodic/sampling/jfrSampleRequest.hpp"
#include "jfr/periodic/sampling/jfrThreadSampling.hpp"
@@ -162,7 +161,7 @@ static inline bool is_valid(const PcDesc* pc_desc) {
return pc_desc != nullptr && pc_desc->scope_decode_offset() != DebugInformationRecorder::serialized_null;
}
-static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame, bool& in_continuation, JavaThread* jt, bool& biased) {
+static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame, bool& in_continuation, JavaThread* jt) {
assert(jt != nullptr, "invariant");
if (!jt->has_last_Java_frame()) {
@@ -179,7 +178,6 @@ static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame,
// A biased sample is requested or no code blob.
top_frame = jt->last_frame();
in_continuation = is_in_continuation(top_frame, jt);
- biased = true;
return true;
}
@@ -229,8 +227,6 @@ static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame,
assert(!stream.current()->is_safepoint_blob_frame(), "invariant");
- biased = true;
-
// Search the first frame that is above the sampled sp.
for (; !stream.is_done(); stream.next()) {
frame* const current = stream.current();
@@ -254,7 +250,6 @@ static bool compute_top_frame(const JfrSampleRequest& request, frame& top_frame,
const PcDesc* const pc_desc = get_pc_desc(sampled_nm, sampled_pc);
if (is_valid(pc_desc)) {
current->adjust_pc(pc_desc->real_pc(sampled_nm));
- biased = false;
}
}
}
@@ -275,9 +270,8 @@ static void record_thread_in_java(const JfrSampleRequest& request, const JfrTick
assert(current != nullptr, "invariant");
frame top_frame;
- bool biased = false;
bool in_continuation;
- if (!compute_top_frame(request, top_frame, in_continuation, jt, biased)) {
+ if (!compute_top_frame(request, top_frame, in_continuation, jt)) {
return;
}
@@ -299,42 +293,6 @@ static void record_thread_in_java(const JfrSampleRequest& request, const JfrTick
}
}
-#ifdef LINUX
-static void record_cpu_time_thread(const JfrCPUTimeSampleRequest& request, const JfrTicks& now, const JfrThreadLocal* tl, JavaThread* jt, Thread* current) {
- assert(jt != nullptr, "invariant");
- assert(tl != nullptr, "invariant");
- assert(current != nullptr, "invariant");
- frame top_frame;
- bool biased = false;
- bool in_continuation = false;
- bool could_compute_top_frame = compute_top_frame(request._request, top_frame, in_continuation, jt, biased);
- const traceid tid = in_continuation ? tl->vthread_id_with_epoch_update(jt) : JfrThreadLocal::jvm_thread_id(jt);
-
- if (!could_compute_top_frame) {
- JfrCPUTimeThreadSampling::send_empty_event(request._request._sample_ticks, tid, request._cpu_time_period);
- return;
- }
- traceid sid;
- {
- ResourceMark rm(current);
- JfrStackTrace stacktrace;
- if (!stacktrace.record(jt, top_frame, in_continuation, request._request)) {
- // Unable to record stacktrace. Fail.
- JfrCPUTimeThreadSampling::send_empty_event(request._request._sample_ticks, tid, request._cpu_time_period);
- return;
- }
- sid = JfrStackTraceRepository::add(stacktrace);
- }
- assert(sid != 0, "invariant");
-
-
- JfrCPUTimeThreadSampling::send_event(request._request._sample_ticks, sid, tid, request._cpu_time_period, biased);
- if (current == jt) {
- send_safepoint_latency_event(request._request, now, sid, jt);
- }
-}
-#endif
-
static void drain_enqueued_requests(const JfrTicks& now, JfrThreadLocal* tl, JavaThread* jt, Thread* current) {
assert(tl != nullptr, "invariant");
assert(jt != nullptr, "invariant");
@@ -350,49 +308,6 @@ static void drain_enqueued_requests(const JfrTicks& now, JfrThreadLocal* tl, Jav
assert(!tl->has_enqueued_requests(), "invariant");
}
-static void drain_enqueued_cpu_time_requests(const JfrTicks& now, JfrThreadLocal* tl, JavaThread* jt, Thread* current, bool lock) {
- assert(tl != nullptr, "invariant");
- assert(jt != nullptr, "invariant");
- assert(current != nullptr, "invariant");
-#ifdef LINUX
- tl->set_do_async_processing_of_cpu_time_jfr_requests(false);
- if (lock) {
- tl->acquire_cpu_time_jfr_dequeue_lock();
- }
- JfrCPUTimeTraceQueue& queue = tl->cpu_time_jfr_queue();
- for (u4 i = 0; i < queue.size(); i++) {
- record_cpu_time_thread(queue.at(i), now, tl, jt, current);
- }
- queue.clear();
- assert(queue.is_empty(), "invariant");
- tl->set_has_cpu_time_jfr_requests(false);
- if (queue.lost_samples() > 0) {
- JfrCPUTimeThreadSampling::send_lost_event( now, JfrThreadLocal::thread_id(jt), queue.get_and_reset_lost_samples());
- }
- if (lock) {
- tl->release_cpu_time_jfr_queue_lock();
- }
-#endif
-}
-
-// Entry point for a thread that has been sampled in native code and has a pending JFR CPU time request.
-void JfrThreadSampling::process_cpu_time_request(JavaThread* jt, JfrThreadLocal* tl, Thread* current, bool lock) {
- assert(jt != nullptr, "invariant");
-
- const JfrTicks now = JfrTicks::now();
- drain_enqueued_cpu_time_requests(now, tl, jt, current, lock);
-}
-
-static void drain_all_enqueued_requests(const JfrTicks& now, JfrThreadLocal* tl, JavaThread* jt, Thread* current) {
- assert(tl != nullptr, "invariant");
- assert(jt != nullptr, "invariant");
- assert(current != nullptr, "invariant");
- drain_enqueued_requests(now, tl, jt, current);
- if (tl->has_cpu_time_jfr_requests()) {
- drain_enqueued_cpu_time_requests(now, tl, jt, current, true);
- }
-}
-
// Only entered by the JfrSampler thread.
bool JfrThreadSampling::process_native_sample_request(JfrThreadLocal* tl, JavaThread* jt, Thread* sampler_thread) {
assert(tl != nullptr, "invairant");
@@ -467,6 +382,5 @@ void JfrThreadSampling::process_sample_request(JavaThread* jt) {
break;
}
}
- drain_all_enqueued_requests(now, tl, jt, jt);
+ drain_enqueued_requests(now, tl, jt, jt);
}
-
diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.hpp
index 3c4d1a126b0..d4c4bc0d873 100644
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.hpp
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampling.hpp
@@ -33,10 +33,8 @@ class Thread;
class JfrThreadSampling : AllStatic {
friend class JfrSamplerThread;
- friend class JfrCPUSamplerThread;
private:
static bool process_native_sample_request(JfrThreadLocal* tl, JavaThread* jt, Thread* sampler_thread);
- static void process_cpu_time_request(JavaThread* jt, JfrThreadLocal* tl, Thread* current, bool lock);
public:
static void process_sample_request(JavaThread* jt);
};
diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
index dd75cb2929f..384305862ca 100644
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp
@@ -29,7 +29,6 @@
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/leakprofiler/sampling/objectSampler.hpp"
#include "jfr/periodic/jfrOSInterface.hpp"
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jfr/periodic/sampling/jfrThreadSampler.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
@@ -305,9 +304,6 @@ bool JfrRecorder::create_components() {
if (!create_thread_sampler()) {
return false;
}
- if (!create_cpu_time_thread_sampling()) {
- return false;
- }
if (!create_event_throttler()) {
return false;
}
@@ -322,7 +318,6 @@ static JfrStackTraceRepository* _stack_trace_repository;
static JfrStringPool* _stringpool = nullptr;
static JfrOSInterface* _os_interface = nullptr;
static JfrThreadSampler* _thread_sampler = nullptr;
-static JfrCPUTimeThreadSampling* _cpu_time_thread_sampling = nullptr;
static JfrCheckpointManager* _checkpoint_manager = nullptr;
bool JfrRecorder::create_java_event_writer() {
@@ -395,12 +390,6 @@ bool JfrRecorder::create_thread_sampler() {
return _thread_sampler != nullptr;
}
-bool JfrRecorder::create_cpu_time_thread_sampling() {
- assert(_cpu_time_thread_sampling == nullptr, "invariant");
- _cpu_time_thread_sampling = JfrCPUTimeThreadSampling::create();
- return _cpu_time_thread_sampling != nullptr;
-}
-
bool JfrRecorder::create_event_throttler() {
return JfrEventThrottler::create();
}
@@ -439,10 +428,6 @@ void JfrRecorder::destroy_components() {
JfrThreadSampler::destroy();
_thread_sampler = nullptr;
}
- if (_cpu_time_thread_sampling != nullptr) {
- JfrCPUTimeThreadSampling::destroy();
- _cpu_time_thread_sampling = nullptr;
- }
JfrEventThrottler::destroy();
}
diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
index 3099c8ad344..b917904c5fb 100644
--- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
+++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp
@@ -54,7 +54,6 @@ class JfrRecorder : public JfrCHeapObj {
static bool create_storage();
static bool create_stringpool();
static bool create_thread_sampler();
- static bool create_cpu_time_thread_sampling();
static bool create_event_throttler();
static bool create_components();
static void destroy_components();
diff --git a/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp
index f660a01c04c..0befaae7751 100644
--- a/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp
+++ b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp
@@ -34,7 +34,6 @@ constexpr static const JfrSamplerParams _disabled_params = {
false // reconfigure
};
-static JfrEventThrottler* _disabled_cpu_time_sample_throttler = nullptr;
static JfrEventThrottler* _object_allocation_throttler = nullptr;
static JfrEventThrottler* _safepoint_latency_throttler = nullptr;
@@ -49,9 +48,6 @@ JfrEventThrottler::JfrEventThrottler(JfrEventId event_id) :
_update(false) {}
bool JfrEventThrottler::create() {
- assert(_disabled_cpu_time_sample_throttler == nullptr, "invariant");
- _disabled_cpu_time_sample_throttler = new JfrEventThrottler(JfrCPUTimeSampleEvent);
- _disabled_cpu_time_sample_throttler->_disabled = true;
assert(_object_allocation_throttler == nullptr, "invariant");
_object_allocation_throttler = new JfrEventThrottler(JfrObjectAllocationSampleEvent);
if (_object_allocation_throttler == nullptr || !_object_allocation_throttler->initialize()) {
@@ -63,8 +59,6 @@ bool JfrEventThrottler::create() {
}
void JfrEventThrottler::destroy() {
- delete _disabled_cpu_time_sample_throttler;
- _disabled_cpu_time_sample_throttler = nullptr;
delete _object_allocation_throttler;
_object_allocation_throttler = nullptr;
delete _safepoint_latency_throttler;
@@ -75,19 +69,15 @@ void JfrEventThrottler::destroy() {
// and another for the SamplingLatency event.
// When introducing many more throttlers, consider adding a lookup map keyed by event id.
JfrEventThrottler* JfrEventThrottler::for_event(JfrEventId event_id) {
- assert(_disabled_cpu_time_sample_throttler != nullptr, "Disabled CPU time throttler has not been properly initialized");
assert(_object_allocation_throttler != nullptr, "ObjectAllocation throttler has not been properly initialized");
assert(_safepoint_latency_throttler != nullptr, "SafepointLatency throttler has not been properly initialized");
- assert(event_id == JfrObjectAllocationSampleEvent || event_id == JfrSafepointLatencyEvent || event_id == JfrCPUTimeSampleEvent, "Event type has an unconfigured throttler");
+ assert(event_id == JfrObjectAllocationSampleEvent || event_id == JfrSafepointLatencyEvent, "Event type has an unconfigured throttler");
if (event_id == JfrObjectAllocationSampleEvent) {
return _object_allocation_throttler;
}
if (event_id == JfrSafepointLatencyEvent) {
return _safepoint_latency_throttler;
}
- if (event_id == JfrCPUTimeSampleEvent) {
- return _disabled_cpu_time_sample_throttler;
- }
return nullptr;
}
diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
index 4b805a98a32..503aa85e02f 100644
--- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
+++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp
@@ -26,7 +26,6 @@
#include "jfr/jni/jfrJavaSupport.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/periodic/jfrThreadCPULoadEvent.hpp"
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrOopTraceId.inline.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
@@ -79,15 +78,7 @@ JfrThreadLocal::JfrThreadLocal() :
_enqueued_requests(false),
_vthread(false),
_notified(false),
- _dead(false)
-#ifdef LINUX
- ,_cpu_timer(nullptr),
- _cpu_time_jfr_locked(UNLOCKED),
- _has_cpu_time_jfr_requests(false),
- _cpu_time_jfr_queue(0),
- _do_async_processing_of_cpu_time_jfr_requests(false)
-#endif
- {
+ _dead(false) {
Thread* thread = Thread::current_or_null();
_parent_trace_id = thread != nullptr ? jvm_thread_id(thread) : (traceid)0;
}
@@ -138,9 +129,7 @@ void JfrThreadLocal::on_start(Thread* t) {
if (JfrRecorder::is_recording()) {
JfrCheckpointManager::write_checkpoint(t);
if (t->is_Java_thread()) {
- JavaThread *const jt = JavaThread::cast(t);
- JfrCPUTimeThreadSampling::on_javathread_create(jt);
- send_java_thread_start_event(jt);
+ send_java_thread_start_event(JavaThread::cast(t));
}
}
if (t->jfr_thread_local()->has_cached_stack_trace()) {
@@ -232,7 +221,6 @@ void JfrThreadLocal::on_exit(Thread* t) {
if (t->is_Java_thread()) {
JavaThread* const jt = JavaThread::cast(t);
send_java_thread_end_event(jt, JfrThreadLocal::jvm_thread_id(jt));
- JfrCPUTimeThreadSampling::on_javathread_terminate(jt);
JfrThreadCPULoadEvent::send_event_for_thread(jt);
}
release(tl, Thread::current()); // because it could be that Thread::current() != t
@@ -549,85 +537,3 @@ Arena* JfrThreadLocal::dcmd_arena(JavaThread* jt) {
tl->_dcmd_arena = arena;
return arena;
}
-
-
-#ifdef LINUX
-
-void JfrThreadLocal::set_cpu_timer(timer_t* timer) {
- if (_cpu_timer == nullptr) {
- _cpu_timer = JfrCHeapObj::new_array(1);
- }
- *_cpu_timer = *timer;
-}
-
-void JfrThreadLocal::unset_cpu_timer() {
- if (_cpu_timer != nullptr) {
- timer_delete(*_cpu_timer);
- JfrCHeapObj::free(_cpu_timer, sizeof(timer_t));
- _cpu_timer = nullptr;
- }
-}
-
-timer_t* JfrThreadLocal::cpu_timer() const {
- return _cpu_timer;
-}
-
-bool JfrThreadLocal::is_cpu_time_jfr_enqueue_locked() {
- return Atomic::load_acquire(&_cpu_time_jfr_locked) == ENQUEUE;
-}
-
-bool JfrThreadLocal::is_cpu_time_jfr_dequeue_locked() {
- return Atomic::load_acquire(&_cpu_time_jfr_locked) == DEQUEUE;
-}
-
-bool JfrThreadLocal::try_acquire_cpu_time_jfr_enqueue_lock() {
- return Atomic::cmpxchg(&_cpu_time_jfr_locked, UNLOCKED, ENQUEUE) == UNLOCKED;
-}
-
-bool JfrThreadLocal::try_acquire_cpu_time_jfr_dequeue_lock() {
- CPUTimeLockState got;
- while (true) {
- CPUTimeLockState got = Atomic::cmpxchg(&_cpu_time_jfr_locked, UNLOCKED, DEQUEUE);
- if (got == UNLOCKED) {
- return true; // successfully locked for dequeue
- }
- if (got == DEQUEUE) {
- return false; // already locked for dequeue
- }
- // else wait for the lock to be released from a signal handler
- }
-}
-
-void JfrThreadLocal::acquire_cpu_time_jfr_dequeue_lock() {
- while (Atomic::cmpxchg(&_cpu_time_jfr_locked, UNLOCKED, DEQUEUE) != UNLOCKED);
-}
-
-void JfrThreadLocal::release_cpu_time_jfr_queue_lock() {
- Atomic::release_store(&_cpu_time_jfr_locked, UNLOCKED);
-}
-
-void JfrThreadLocal::set_has_cpu_time_jfr_requests(bool has_requests) {
- Atomic::release_store(&_has_cpu_time_jfr_requests, has_requests);
-}
-
-bool JfrThreadLocal::has_cpu_time_jfr_requests() {
- return Atomic::load_acquire(&_has_cpu_time_jfr_requests);
-}
-
-JfrCPUTimeTraceQueue& JfrThreadLocal::cpu_time_jfr_queue() {
- return _cpu_time_jfr_queue;
-}
-
-void JfrThreadLocal::deallocate_cpu_time_jfr_queue() {
- cpu_time_jfr_queue().resize(0);
-}
-
-void JfrThreadLocal::set_do_async_processing_of_cpu_time_jfr_requests(bool wants) {
- Atomic::release_store(&_do_async_processing_of_cpu_time_jfr_requests, wants);
-}
-
-bool JfrThreadLocal::wants_async_processing_of_cpu_time_jfr_requests() {
- return Atomic::load_acquire(&_do_async_processing_of_cpu_time_jfr_requests);
-}
-
-#endif
diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp
index 715a2c44f93..8e545d9c429 100644
--- a/src/hotspot/share/jfr/support/jfrThreadLocal.hpp
+++ b/src/hotspot/share/jfr/support/jfrThreadLocal.hpp
@@ -33,10 +33,6 @@
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
-#ifdef LINUX
-#include "jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp"
-#endif
-
class Arena;
class JavaThread;
class JfrBuffer;
@@ -83,22 +79,6 @@ class JfrThreadLocal {
bool _dead;
bool _sampling_critical_section;
-#ifdef LINUX
- timer_t* _cpu_timer;
-
- enum CPUTimeLockState {
- UNLOCKED,
- // locked for enqueuing
- ENQUEUE,
- // locked for dequeuing
- DEQUEUE
- };
- volatile CPUTimeLockState _cpu_time_jfr_locked;
- volatile bool _has_cpu_time_jfr_requests;
- JfrCPUTimeTraceQueue _cpu_time_jfr_queue;
- volatile bool _do_async_processing_of_cpu_time_jfr_requests;
-#endif
-
JfrBuffer* install_native_buffer() const;
JfrBuffer* install_java_buffer() const;
void release(Thread* t);
@@ -362,39 +342,6 @@ class JfrThreadLocal {
void set_thread_blob(const JfrBlobHandle& handle);
const JfrBlobHandle& thread_blob() const;
- // CPU time sampling
-#ifdef LINUX
- void set_cpu_timer(timer_t* timer);
- void unset_cpu_timer();
- timer_t* cpu_timer() const;
-
- // The CPU time JFR lock has three different states:
- // - ENQUEUE: lock for enqueuing CPU time requests
- // - DEQUEUE: lock for dequeuing CPU time requests
- // - UNLOCKED: no lock held
- // This ensures that we can safely enqueue and dequeue CPU time requests,
- // without interleaving
-
- bool is_cpu_time_jfr_enqueue_locked();
- bool is_cpu_time_jfr_dequeue_locked();
-
- bool try_acquire_cpu_time_jfr_enqueue_lock();
- bool try_acquire_cpu_time_jfr_dequeue_lock();
- void acquire_cpu_time_jfr_dequeue_lock();
- void release_cpu_time_jfr_queue_lock();
-
- void set_has_cpu_time_jfr_requests(bool has_events);
- bool has_cpu_time_jfr_requests();
-
- JfrCPUTimeTraceQueue& cpu_time_jfr_queue();
- void deallocate_cpu_time_jfr_queue();
-
- void set_do_async_processing_of_cpu_time_jfr_requests(bool wants);
- bool wants_async_processing_of_cpu_time_jfr_requests();
-#else
- bool has_cpu_time_jfr_requests() { return false; }
-#endif
-
// Hooks
static void on_start(Thread* t);
static void on_exit(Thread* t);
diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp
index 772ef7bbe82..f3a06d5efd2 100644
--- a/src/hotspot/share/runtime/thread.hpp
+++ b/src/hotspot/share/runtime/thread.hpp
@@ -78,7 +78,6 @@ class JavaThread;
// - WorkerThread
// - WatcherThread
// - JfrThreadSampler
-// - JfrCPUSamplerThread
// - LogAsyncWriter
//
// All Thread subclasses must be either JavaThread or NonJavaThread.
diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp
index ac5d37381f9..50d85944485 100644
--- a/src/hotspot/share/runtime/vmOperation.hpp
+++ b/src/hotspot/share/runtime/vmOperation.hpp
@@ -115,8 +115,6 @@
template(JFROldObject) \
template(JvmtiPostObjectFree) \
template(RendezvousGCThreads) \
- template(JFRInitializeCPUTimeSampler) \
- template(JFRTerminateCPUTimeSampler) \
template(ReinitializeMDO)
class Thread;
diff --git a/src/hotspot/share/utilities/ticks.hpp b/src/hotspot/share/utilities/ticks.hpp
index 88dc9a787f9..8d2bbc7ce1f 100644
--- a/src/hotspot/share/utilities/ticks.hpp
+++ b/src/hotspot/share/utilities/ticks.hpp
@@ -236,7 +236,6 @@ class TimeInstant : public Rep {
friend class TimePartitionsTest;
friend class GCTimerTest;
friend class CompilerEvent;
- friend class JfrCPUSamplerThread;
};
#if INCLUDE_JFR
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
index 2ea4725abc8..f43e45b724e 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
@@ -51,7 +51,6 @@ import jdk.jfr.internal.settings.EnabledSetting;
import jdk.jfr.internal.settings.LevelSetting;
import jdk.jfr.internal.settings.MethodSetting;
import jdk.jfr.internal.settings.PeriodSetting;
-import jdk.jfr.internal.settings.CPUThrottleSetting;
import jdk.jfr.internal.settings.StackTraceSetting;
import jdk.jfr.internal.settings.ThresholdSetting;
import jdk.jfr.internal.settings.ThrottleSetting;
@@ -327,9 +326,6 @@ public final class EventControl {
private static Control defineThrottle(PlatformEventType type) {
String def = type.getAnnotationValue(Throttle.class, ThrottleSetting.DEFAULT_VALUE);
type.add(PrivateAccess.getInstance().newSettingDescriptor(TYPE_THROTTLE, Throttle.NAME, def, Collections.emptyList()));
- if (type.getName().equals("jdk.CPUTimeSample")) {
- return new Control(new CPUThrottleSetting(type), def);
- }
return new Control(new ThrottleSetting(type, def), def);
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
index b91f0c337b2..e0eaef74b4c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java
@@ -270,16 +270,6 @@ public final class JVM {
*/
public static native void setMethodSamplingPeriod(long type, long periodMillis);
- /**
- * Set the maximum event emission rate for the CPU time sampler
- *
- * Setting rate to 0 turns off the CPU time sampler.
- *
- * @param rate the new rate in events per second
- * @param autoAdapt true if the rate should be adapted automatically
- */
- public static native void setCPUThrottle(double rate, boolean autoAdapt);
-
/**
* Sets the file where data should be written.
*
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
index 769e7055305..32b59bca4c0 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformEventType.java
@@ -30,10 +30,8 @@ import java.util.List;
import java.util.Objects;
import jdk.jfr.SettingDescriptor;
-import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.internal.periodic.PeriodicEvents;
import jdk.jfr.internal.util.ImplicitFields;
-import jdk.jfr.internal.util.TimespanRate;
import jdk.jfr.internal.util.Utils;
import jdk.jfr.internal.tracing.Modification;
@@ -47,7 +45,6 @@ public final class PlatformEventType extends Type {
private final boolean isJVM;
private final boolean isJDK;
private final boolean isMethodSampling;
- private final boolean isCPUTimeMethodSampling;
private final List settings = new ArrayList<>(5);
private final boolean dynamicSettings;
private final int stackTraceOffset;
@@ -59,7 +56,6 @@ public final class PlatformEventType extends Type {
private boolean stackTraceEnabled = true;
private long thresholdTicks = 0;
private long period = 0;
- private TimespanRate cpuRate;
private boolean hasHook;
private boolean beginChunk;
@@ -79,7 +75,6 @@ public final class PlatformEventType extends Type {
this.dynamicSettings = dynamicSettings;
this.isJVM = Type.isDefinedByJVM(id);
this.isMethodSampling = determineMethodSampling();
- this.isCPUTimeMethodSampling = isJVM && name.equals(Type.EVENT_NAME_PREFIX + "CPUTimeSample");
this.isJDK = isJDK;
this.stackTraceOffset = determineStackTraceOffset();
}
@@ -196,13 +191,6 @@ public final class PlatformEventType extends Type {
}
}
- public void setCPUThrottle(TimespanRate rate) {
- if (isCPUTimeMethodSampling) {
- this.cpuRate = rate;
- JVM.setCPUThrottle(rate.rate(), rate.autoAdapt());
- }
- }
-
public void setHasPeriod(boolean hasPeriod) {
this.hasPeriod = hasPeriod;
}
@@ -263,9 +251,6 @@ public final class PlatformEventType extends Type {
if (isMethodSampling) {
long p = enabled ? period : 0;
JVM.setMethodSamplingPeriod(getId(), p);
- } else if (isCPUTimeMethodSampling) {
- TimespanRate r = enabled ? cpuRate : new TimespanRate(0, false);
- JVM.setCPUThrottle(r.rate(), r.autoAdapt());
} else {
JVM.setEnabled(getId(), enabled);
}
@@ -403,10 +388,6 @@ public final class PlatformEventType extends Type {
return isMethodSampling;
}
- public boolean isCPUTimeMethodSampling() {
- return isCPUTimeMethodSampling;
- }
-
public void setStackFilterId(long id) {
startFilterId = id;
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
index a2ac74142f4..a6192db1ab0 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini
@@ -39,8 +39,7 @@ label = "Active Settings"
table = "COLUMN 'Event Type', 'Enabled', 'Threshold',
'Stack Trace','Period','Cutoff', 'Throttle'
FORMAT none, missing:whitespace, missing:whitespace, missing:whitespace,
- missing:whitespace, missing:whitespace, missing:whitespace,
- missing:whitespace
+ missing:whitespace, missing:whitespace, missing:whitespace
SELECT E.id, LAST_BATCH(E.value), LAST_BATCH(T.value),
LAST_BATCH(S.value), LAST_BATCH(P.value),
LAST_BATCH(C.value), LAST_BATCH(U.value)
@@ -401,28 +400,6 @@ table = "COLUMN 'Method', 'Samples', 'Percent'
SELECT stackTrace.topFrame AS T, COUNT(*), COUNT(*)
FROM ExecutionSample GROUP BY T LIMIT 25"
-[application.cpu-time-hot-methods]
-label = "Java Methods that Execute the Most from CPU Time Sampler"
-table = "COLUMN 'Method', 'Samples', 'Percent'
- FORMAT none, none, normalized
- SELECT stackTrace.topFrame AS T, COUNT(*), COUNT(*)
- FROM CPUTimeSample GROUP BY T LIMIT 25"
-
-[application.cpu-time-statistics]
-label = "CPU Time Sample Statistics"
-form = "COLUMN 'Successful Samples', 'Failed Samples', 'Biased Samples', 'Total Samples', 'Lost Samples'
- SELECT COUNT(S.startTime), COUNT(F.startTime), COUNT(B.startTime), Count(A.startTime), SUM(L.lostSamples)
- FROM
- CPUTimeSample AS S,
- CPUTimeSample AS F,
- CPUTimeSample AS A,
- CPUTimeSample AS B,
- CPUTimeSamplesLost AS L
- WHERE
- S.failed = 'false' AND
- F.failed = 'true' AND
- B.biased = 'true'"
-
[jvm.jdk-agents]
label = "JDK Agents"
table = "COLUMN 'Time', 'Initialization', 'Name', 'Options'
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java
deleted file mode 100644
index c18aeef2132..00000000000
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/CPUThrottleSetting.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2020, Datadog, Inc. All rights reserved.
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.internal.settings;
-
-import static jdk.jfr.internal.util.TimespanUnit.SECONDS;
-import static jdk.jfr.internal.util.TimespanUnit.MILLISECONDS;
-
-import java.util.Objects;
-import java.util.Set;
-
-import jdk.jfr.Description;
-import jdk.jfr.SettingControl;
-import jdk.jfr.Label;
-import jdk.jfr.MetadataDefinition;
-import jdk.jfr.Name;
-import jdk.jfr.internal.PlatformEventType;
-import jdk.jfr.internal.Type;
-import jdk.jfr.internal.util.TimespanRate;
-import jdk.jfr.internal.util.Utils;
-
-@MetadataDefinition
-@Label("CPUThrottleSetting")
-@Description("Upper bounds the emission rate for CPU time samples")
-@Name(Type.SETTINGS_PREFIX + "Rate")
-public final class CPUThrottleSetting extends SettingControl {
- public static final String DEFAULT_VALUE = "0/s";
- private final PlatformEventType eventType;
- private String value = DEFAULT_VALUE;
-
- public CPUThrottleSetting(PlatformEventType eventType) {
- this.eventType = Objects.requireNonNull(eventType);
- }
-
- @Override
- public String combine(Set values) {
- TimespanRate max = null;
- for (String value : values) {
- TimespanRate rate = TimespanRate.of(value);
- if (rate != null) {
- if (max == null || rate.isHigher(max)) {
- max = rate;
- }
- max = new TimespanRate(max.rate(), max.autoAdapt() || rate.autoAdapt());
- }
- }
- // "off" is not supported
- return Objects.requireNonNullElse(max.toString(), DEFAULT_VALUE);
- }
-
- @Override
- public void setValue(String value) {
- TimespanRate rate = TimespanRate.of(value);
- if (rate != null) {
- eventType.setCPUThrottle(rate);
- this.value = value;
- }
- }
-
- @Override
- public String getValue() {
- return value;
- }
-}
-
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Rate.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Rate.java
index 2632cd63848..f32436a5e0f 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Rate.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/Rate.java
@@ -55,8 +55,4 @@ public record Rate(long amount, TimespanUnit unit) {
private double inNanos() {
return (double) amount / unit.nanos;
}
-
- public double perSecond() {
- return inNanos() * 1_000_000_000.0;
- }
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java
deleted file mode 100644
index 5d671310e3c..00000000000
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/util/TimespanRate.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.jfr.internal.util;
-
-import jdk.jfr.internal.settings.CPUThrottleSetting;
-
-/**
- * A rate or fixed period, see {@link jdk.jfr.internal.Rate}
- */
-public record TimespanRate(double rate, boolean autoAdapt) {
-
- public static TimespanRate of(String text) {
- if (text.equals("off")) {
- text = CPUThrottleSetting.DEFAULT_VALUE;
- }
- boolean isPeriod = !text.contains("/");
- if (isPeriod) {
- var period = ValueParser.parseTimespanWithInfinity(text, Long.MAX_VALUE);
- if (period == Long.MAX_VALUE) {
- return null;
- }
- if (period == 0) {
- return new TimespanRate(0, false);
- }
- return new TimespanRate(Runtime.getRuntime().availableProcessors() / (period / 1_000_000_000.0), false);
- }
- Rate r = Rate.of(text);
- if (r == null) {
- return null;
- }
- return new TimespanRate(r.perSecond(), true);
- }
-
- public boolean isHigher(TimespanRate that) {
- return rate() > that.rate();
- }
-
- @Override
- public String toString() {
- if (autoAdapt) {
- return String.format("%d/ns", (long)(rate * 1_000_000_000L));
- }
- return String.format("%dns", (long)(Runtime.getRuntime().availableProcessors() / rate * 1_000_000_000L));
- }
-}
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index 541d1d3aa2f..293af26746f 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -226,16 +226,6 @@
off
-
- false
- 500/s
- true
-
-
-
- true
-
-
true
10 ms
diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc
index 9cec2d9a70f..89a9022d11e 100644
--- a/src/jdk.jfr/share/conf/jfr/profile.jfc
+++ b/src/jdk.jfr/share/conf/jfr/profile.jfc
@@ -206,16 +206,6 @@
20 ms
-
- false
- 10ms
- true
-
-
-
- true
-
-
true
diff --git a/test/jdk/jdk/jfr/event/metadata/TestLookForUntestedEvents.java b/test/jdk/jdk/jfr/event/metadata/TestLookForUntestedEvents.java
index d6e126a493f..5b8aacfb1d2 100644
--- a/test/jdk/jdk/jfr/event/metadata/TestLookForUntestedEvents.java
+++ b/test/jdk/jdk/jfr/event/metadata/TestLookForUntestedEvents.java
@@ -89,10 +89,7 @@ public class TestLookForUntestedEvents {
// Experimental events
private static final Set experimentalEvents = Set.of(
- "Flush", "SyncOnValueBasedClass", "CPUTimeSample", "CPUTimeSamplesLost");
-
- // Subset of the experimental events that should have tests
- private static final Set experimentalButTestedEvents = Set.of("CPUTimeSample");
+ "Flush", "SyncOnValueBasedClass");
public static void main(String[] args) throws Exception {
for (EventType type : FlightRecorder.getFlightRecorder().getEventTypes()) {
@@ -113,9 +110,7 @@ public class TestLookForUntestedEvents {
.collect(Collectors.toList());
Set eventsNotCoveredByTest = new HashSet<>(jfrEventTypes);
- Set checkedEvents = new HashSet<>(jfrEventTypes);
- checkedEvents.addAll(experimentalButTestedEvents);
- for (String event : checkedEvents) {
+ for (String event : jfrEventTypes) {
for (Path p : paths) {
if (findStringInFile(p, event)) {
eventsNotCoveredByTest.remove(event);
diff --git a/test/jdk/jdk/jfr/event/profiling/BaseTestFullStackTrace.java b/test/jdk/jdk/jfr/event/profiling/BaseTestFullStackTrace.java
deleted file mode 100644
index de211b8c454..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/BaseTestFullStackTrace.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
-
-import jdk.jfr.Recording;
-import jdk.jfr.consumer.RecordedEvent;
-import jdk.jfr.consumer.RecordedFrame;
-import jdk.jfr.consumer.RecordedStackTrace;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.jfr.EventNames;
-import jdk.test.lib.jfr.Events;
-import jdk.test.lib.jfr.RecurseThread;
-
-public class BaseTestFullStackTrace {
- private final static int MAX_DEPTH = 64; // currently hardcoded in jvm
-
- private final String eventName;
- private final String threadFieldName;
-
- public BaseTestFullStackTrace(String eventName, String threadFieldName) {
- this.eventName = eventName;
- this.threadFieldName = threadFieldName;
- }
-
- public void run() throws Throwable {
- RecurseThread[] threads = new RecurseThread[3];
- for (int i = 0; i < threads.length; ++i) {
- int depth = MAX_DEPTH - 1 + i;
- threads[i] = new RecurseThread(depth);
- threads[i].setName("recursethread-" + depth);
- threads[i].start();
- }
-
- for (RecurseThread thread : threads) {
- while (!thread.isInRunLoop()) {
- Thread.sleep(20);
- }
- }
-
- assertStackTraces(threads);
-
- for (RecurseThread thread : threads) {
- thread.quit();
- thread.join();
- }
- }
-
- private void assertStackTraces(RecurseThread[] threads) throws Throwable {
- while (true) {
- try (Recording recording = new Recording()) {
- if (eventName.equals(EventNames.CPUTimeSample)) {
- recording.enable(eventName).with("throttle", "50ms");
- } else {
- recording.enable(eventName).withPeriod(Duration.ofMillis(50));
- }
- recording.start();
- Thread.sleep(500);
- recording.stop();
- if (hasValidStackTraces(recording, threads)) {
- break;
- }
- }
- };
- }
-
- private boolean hasValidStackTraces(Recording recording, RecurseThread[] threads) throws Throwable {
- boolean[] isEventFound = new boolean[threads.length];
-
- for (RecordedEvent event : Events.fromRecording(recording)) {
- System.out.println("Event: " + event);
- String threadName = Events.assertField(event, threadFieldName + ".javaName").getValue();
- long threadId = Events.assertField(event, threadFieldName + ".javaThreadId").getValue();
-
- for (int threadIndex = 0; threadIndex < threads.length; ++threadIndex) {
- RecurseThread currThread = threads[threadIndex];
- if (threadId == currThread.getId()) {
- System.out.println("ThreadName=" + currThread.getName() + ", depth=" + currThread.totalDepth);
- Asserts.assertEquals(threadName, currThread.getName(), "Wrong thread name");
- if ("recurseEnd".equals(getTopMethodName(event))) {
- isEventFound[threadIndex] = true;
- checkEvent(event, currThread.totalDepth);
- break;
- }
- }
- }
- }
-
- for (int i = 0; i < threads.length; ++i) {
- String msg = "threadIndex=%d, recurseDepth=%d, isEventFound=%b%n";
- System.out.printf(msg, i, threads[i].totalDepth, isEventFound[i]);
- }
- for (int i = 0; i < threads.length; ++i) {
- if(!isEventFound[i]) {
- // no assertion, let's retry.
- // Could be race condition, i.e safe point during Thread.sleep
- System.out.println("Failed to validate all threads, will retry.");
- return false;
- }
- }
- return true;
- }
-
- public String getTopMethodName(RecordedEvent event) {
- List frames = event.getStackTrace().getFrames();
- Asserts.assertFalse(frames.isEmpty(), "JavaFrames was empty");
- return frames.getFirst().getMethod().getName();
- }
-
- private void checkEvent(RecordedEvent event, int expectedDepth) throws Throwable {
- RecordedStackTrace stacktrace = null;
- try {
- stacktrace = event.getStackTrace();
- List frames = stacktrace.getFrames();
- Asserts.assertEquals(Math.min(MAX_DEPTH, expectedDepth), frames.size(), "Wrong stacktrace depth. Expected:" + expectedDepth);
- List expectedMethods = getExpectedMethods(expectedDepth);
- Asserts.assertEquals(expectedMethods.size(), frames.size(), "Wrong expectedMethods depth. Test error.");
-
- for (int i = 0; i < frames.size(); ++i) {
- String name = frames.get(i).getMethod().getName();
- String expectedName = expectedMethods.get(i);
- System.out.printf("method[%d]=%s, expected=%s%n", i, name, expectedName);
- Asserts.assertEquals(name, expectedName, "Wrong method name");
- }
-
- boolean isTruncated = stacktrace.isTruncated();
- boolean isTruncateExpected = expectedDepth > MAX_DEPTH;
- Asserts.assertEquals(isTruncated, isTruncateExpected, "Wrong value for isTruncated. Expected:" + isTruncateExpected);
-
- String firstMethod = frames.getLast().getMethod().getName();
- boolean isFullTrace = "run".equals(firstMethod);
- String msg = String.format("Wrong values for isTruncated=%b, isFullTrace=%b", isTruncated, isFullTrace);
- Asserts.assertTrue(isTruncated != isFullTrace, msg);
- } catch (Throwable t) {
- System.out.println(String.format("stacktrace:%n%s", stacktrace));
- throw t;
- }
- }
-
- private List getExpectedMethods(int depth) {
- List methods = new ArrayList<>();
- methods.add("recurseEnd");
- for (int i = 0; i < depth - 2; ++i) {
- methods.add((i % 2) == 0 ? "recurseA" : "recurseB");
- }
- methods.add("run");
- if (depth > MAX_DEPTH) {
- methods = methods.subList(0, MAX_DEPTH);
- }
- return methods;
- }
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java
deleted file mode 100644
index eb8d33832b5..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeAndExecutionSample.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import java.time.Duration;
-
-import jdk.jfr.consumer.RecordingStream;
-import jdk.test.lib.jfr.EventNames;
-import jdk.test.lib.jfr.RecurseThread;
-
-/*
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @modules jdk.jfr/jdk.jfr.internal
- * @run main/timeout=30 jdk.jfr.event.profiling.TestCPUTimeAndExecutionSample
- */
-public class TestCPUTimeAndExecutionSample {
-
- static String sampleEvent = EventNames.CPUTimeSample;
-
- // The period is set to 1100 ms to provoke the 1000 ms
- // threshold in the JVM for os::naked_short_sleep().
- public static void main(String[] args) throws Exception {
- run(EventNames.ExecutionSample);
- run(EventNames.CPUTimeSample);
- run(EventNames.ExecutionSample);
- run(EventNames.CPUTimeSample);
- }
-
- private static void run(String eventType) {
- RecurseThread t = new RecurseThread(50);
- t.setDaemon(true);
- try (RecordingStream rs = new RecordingStream()) {
- rs.enable(sampleEvent).with("throttle", "1000/s");
- rs.onEvent(sampleEvent, e -> {
- t.quit();
- rs.close();
- });
- t.start();
- rs.start();
- }
- }
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleFullStackTrace.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleFullStackTrace.java
deleted file mode 100644
index 0d1108346ab..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleFullStackTrace.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import jdk.test.lib.jfr.EventNames;
-
-/**
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @build jdk.jfr.event.profiling.BaseTestFullStackTrace
- * @run main/othervm jdk.jfr.event.profiling.TestCPUTimeSampleFullStackTrace
- */
-public class TestCPUTimeSampleFullStackTrace {
-
- public static void main(String[] args) throws Throwable {
- new BaseTestFullStackTrace(EventNames.CPUTimeSample, "eventThread").run();
- }
-
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java
deleted file mode 100644
index 133df36684c..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleMultipleRecordings.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import java.time.Duration;
-
-import jdk.jfr.Recording;
-import jdk.jfr.consumer.RecordingStream;
-import jdk.jfr.internal.JVM;
-import jdk.test.lib.jfr.EventNames;
-
-/*
- * Tests that creating multiple recordings after another is possible.
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @modules jdk.jfr/jdk.jfr.internal
- * @run main jdk.jfr.event.profiling.TestCPUTimeSampleMultipleRecordings
- */
-public class TestCPUTimeSampleMultipleRecordings {
-
- static String nativeEvent = EventNames.CPUTimeSample;
-
- static volatile boolean alive = true;
-
- public static void main(String[] args) throws Exception {
- Thread t = new Thread(TestCPUTimeSampleMultipleRecordings::nativeMethod);
- t.setDaemon(true);
- t.start();
- for (int i = 0; i < 2; i++) {
- try (RecordingStream rs = new RecordingStream()) {
- rs.enable(nativeEvent).with("throttle", "1ms");
- rs.onEvent(nativeEvent, e -> {
- alive = false;
- rs.close();
- });
-
- rs.start();
- }
- }
- alive = false;
- }
-
- public static void nativeMethod() {
- while (alive) {
- JVM.getPid();
- }
- }
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleNative.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleNative.java
deleted file mode 100644
index 1617bce4ba3..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleNative.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import java.time.Duration;
-
-import jdk.jfr.Recording;
-import jdk.jfr.consumer.RecordingStream;
-import jdk.jfr.internal.JVM;
-import jdk.test.lib.jfr.EventNames;
-
-/*
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @modules jdk.jfr/jdk.jfr.internal
- * @run main jdk.jfr.event.profiling.TestCPUTimeSampleNative
- */
-public class TestCPUTimeSampleNative {
-
- static String nativeEvent = EventNames.CPUTimeSample;
-
- static volatile boolean alive = true;
-
- public static void main(String[] args) throws Exception {
- try (RecordingStream rs = new RecordingStream()) {
- rs.enable(nativeEvent).with("throttle", "1ms");
- rs.onEvent(nativeEvent, e -> {
- alive = false;
- rs.close();
- });
- Thread t = new Thread(TestCPUTimeSampleNative::nativeMethod);
- t.setDaemon(true);
- t.start();
- rs.start();
- }
-
- }
-
- public static void nativeMethod() {
- while (alive) {
- JVM.getPid();
- }
- }
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java
deleted file mode 100644
index 55b350ad096..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-import java.lang.management.ManagementFactory;
-import java.time.Duration;
-import java.time.Instant;
-import java.util.List;
-import java.util.Comparator;
-
-import jdk.jfr.Recording;
-import jdk.jfr.consumer.RecordedEvent;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.jfr.EventNames;
-import jdk.test.lib.jfr.Events;
-
-/**
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @run main/othervm jdk.jfr.event.profiling.TestCPUTimeSampleThrottling
- */
-public class TestCPUTimeSampleThrottling {
-
- public static void main(String[] args) throws Exception {
- testZeroPerSecond();
- testThrottleSettings();
- testThrottleSettingsPeriod();
- }
-
- private static void testZeroPerSecond() throws Exception {
- Asserts.assertTrue(0L == countEvents(1000, "0/s").count());
- }
-
- private static void testThrottleSettings() throws Exception {
- long count = countEvents(1000,
- Runtime.getRuntime().availableProcessors() * 2 + "/s").count();
- Asserts.assertTrue(count > 0 && count < 3,
- "Expected between 0 and 3 events, got " + count);
- }
-
- private static void testThrottleSettingsPeriod() throws Exception {
- float rate = countEvents(1000, "10ms").rate();
- Asserts.assertTrue(rate > 90 && rate < 110, "Expected around 100 events per second, got " + rate);
- }
-
- private record EventCount(long count, float time) {
- float rate() {
- return count / time;
- }
- }
-
- private static EventCount countEvents(int timeMs, String rate) throws Exception {
- try(Recording recording = new Recording()) {
- recording.enable(EventNames.CPUTimeSample)
- .with("throttle", rate);
-
- var bean = ManagementFactory.getThreadMXBean();
-
- recording.start();
-
- long startThreadCpuTime = bean.getCurrentThreadCpuTime();
-
- wasteCPU(timeMs);
-
- long spendCPUTime = bean.getCurrentThreadCpuTime() - startThreadCpuTime;
-
- recording.stop();
-
- long eventCount = Events.fromRecording(recording).stream()
- .filter(e -> e.getThread().getJavaName()
- .equals(Thread.currentThread().getName()))
- .count();
-
- System.out.println("Event count: " + eventCount + ", CPU time: " + spendCPUTime / 1_000_000_000f + "s");
-
- return new EventCount(eventCount, spendCPUTime / 1_000_000_000f);
- }
- }
-
- private static void wasteCPU(int durationMs) {
- long start = System.currentTimeMillis();
- double i = 0;
- while (System.currentTimeMillis() - start < durationMs) {
- for (int j = 0; j < 100000; j++) {
- i = Math.sqrt(i * Math.pow(Math.sqrt(Math.random()), Math.random()));
- }
- }
- }
-
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSamplingLongPeriod.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSamplingLongPeriod.java
deleted file mode 100644
index 69d32d48282..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSamplingLongPeriod.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.jfr.event.profiling;
-
-import java.time.Duration;
-
-import jdk.jfr.consumer.RecordingStream;
-import jdk.test.lib.jfr.EventNames;
-import jdk.test.lib.jfr.RecurseThread;
-
-/*
- * @test
- * @requires vm.hasJFR & os.family == "linux"
- * @library /test/lib
- * @modules jdk.jfr/jdk.jfr.internal
- * @run main jdk.jfr.event.profiling.TestCPUTimeSamplingLongPeriod
- */
-public class TestCPUTimeSamplingLongPeriod {
-
- static String sampleEvent = EventNames.CPUTimeSample;
-
- // The period is set to 1100 ms to provoke the 1000 ms
- // threshold in the JVM for os::naked_short_sleep().
- public static void main(String[] args) throws Exception {
- RecurseThread t = new RecurseThread(50);
- t.setDaemon(true);
- try (RecordingStream rs = new RecordingStream()) {
- rs.enable(sampleEvent).with("throttle", "1100ms");
- rs.onEvent(sampleEvent, e -> {
- t.quit();
- rs.close();
- });
- t.start();
- rs.start();
- }
- }
-}
diff --git a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java
index c337a8128ab..b06f9eed03d 100644
--- a/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java
+++ b/test/jdk/jdk/jfr/event/profiling/TestFullStackTrace.java
@@ -23,20 +23,147 @@
package jdk.jfr.event.profiling;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordedFrame;
+import jdk.jfr.consumer.RecordedStackTrace;
+import jdk.test.lib.Asserts;
import jdk.test.lib.jfr.EventNames;
+import jdk.test.lib.jfr.Events;
+import jdk.test.lib.jfr.RecurseThread;
/**
* @test
* @requires vm.hasJFR
* @requires vm.opt.DeoptimizeALot != true
* @library /test/lib
- * @build jdk.jfr.event.profiling.BaseTestFullStackTrace
* @run main/othervm jdk.jfr.event.profiling.TestFullStackTrace
*/
public class TestFullStackTrace {
+ private final static String EVENT_NAME = EventNames.ExecutionSample;
+ private final static int MAX_DEPTH = 64; // currently hardcoded in jvm
public static void main(String[] args) throws Throwable {
- new BaseTestFullStackTrace(EventNames.ExecutionSample, "sampledThread").run();
+ RecurseThread[] threads = new RecurseThread[3];
+ for (int i = 0; i < threads.length; ++i) {
+ int depth = MAX_DEPTH - 1 + i;
+ threads[i] = new RecurseThread(depth);
+ threads[i].setName("recursethread-" + depth);
+ threads[i].start();
+ }
+
+ for (RecurseThread thread : threads) {
+ while (!thread.isInRunLoop()) {
+ Thread.sleep(20);
+ }
+ }
+
+ assertStackTraces(threads);
+
+ for (RecurseThread thread : threads) {
+ thread.quit();
+ thread.join();
+ }
}
+ private static void assertStackTraces( RecurseThread[] threads) throws Throwable {
+ Recording recording= null;
+ do {
+ recording = new Recording();
+ recording.enable(EVENT_NAME).withPeriod(Duration.ofMillis(50));
+ recording.start();
+ Thread.sleep(500);
+ recording.stop();
+ } while (!hasValidStackTraces(recording, threads));
+ }
+
+ private static boolean hasValidStackTraces(Recording recording, RecurseThread[] threads) throws Throwable {
+ boolean[] isEventFound = new boolean[threads.length];
+
+ for (RecordedEvent event : Events.fromRecording(recording)) {
+ //System.out.println("Event: " + event);
+ String threadName = Events.assertField(event, "sampledThread.javaName").getValue();
+ long threadId = Events.assertField(event, "sampledThread.javaThreadId").getValue();
+
+ for (int threadIndex = 0; threadIndex < threads.length; ++threadIndex) {
+ RecurseThread currThread = threads[threadIndex];
+ if (threadId == currThread.getId()) {
+ System.out.println("ThreadName=" + currThread.getName() + ", depth=" + currThread.totalDepth);
+ Asserts.assertEquals(threadName, currThread.getName(), "Wrong thread name");
+ if ("recurseEnd".equals(getTopMethodName(event))) {
+ isEventFound[threadIndex] = true;
+ checkEvent(event, currThread.totalDepth);
+ break;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < threads.length; ++i) {
+ String msg = "threadIndex=%d, recurseDepth=%d, isEventFound=%b%n";
+ System.out.printf(msg, i, threads[i].totalDepth, isEventFound[i]);
+ }
+ for (int i = 0; i < threads.length; ++i) {
+ if(!isEventFound[i]) {
+ // no assertion, let's retry.
+ // Could be race condition, i.e safe point during Thread.sleep
+ System.out.println("Failed to validate all threads, will retry.");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static String getTopMethodName(RecordedEvent event) {
+ List frames = event.getStackTrace().getFrames();
+ Asserts.assertFalse(frames.isEmpty(), "JavaFrames was empty");
+ return frames.getFirst().getMethod().getName();
+ }
+
+ private static void checkEvent(RecordedEvent event, int expectedDepth) throws Throwable {
+ RecordedStackTrace stacktrace = null;
+ try {
+ stacktrace = event.getStackTrace();
+ List frames = stacktrace.getFrames();
+ Asserts.assertEquals(Math.min(MAX_DEPTH, expectedDepth), frames.size(), "Wrong stacktrace depth. Expected:" + expectedDepth);
+ List expectedMethods = getExpectedMethods(expectedDepth);
+ Asserts.assertEquals(expectedMethods.size(), frames.size(), "Wrong expectedMethods depth. Test error.");
+
+ for (int i = 0; i < frames.size(); ++i) {
+ String name = frames.get(i).getMethod().getName();
+ String expectedName = expectedMethods.get(i);
+ System.out.printf("method[%d]=%s, expected=%s%n", i, name, expectedName);
+ Asserts.assertEquals(name, expectedName, "Wrong method name");
+ }
+
+ boolean isTruncated = stacktrace.isTruncated();
+ boolean isTruncateExpected = expectedDepth > MAX_DEPTH;
+ Asserts.assertEquals(isTruncated, isTruncateExpected, "Wrong value for isTruncated. Expected:" + isTruncateExpected);
+
+ String firstMethod = frames.getLast().getMethod().getName();
+ boolean isFullTrace = "run".equals(firstMethod);
+ String msg = String.format("Wrong values for isTruncated=%b, isFullTrace=%b", isTruncated, isFullTrace);
+ Asserts.assertTrue(isTruncated != isFullTrace, msg);
+ } catch (Throwable t) {
+ System.out.println(String.format("stacktrace:%n%s", stacktrace));
+ throw t;
+ }
+ }
+
+ private static List getExpectedMethods(int depth) {
+ List methods = new ArrayList<>();
+ methods.add("recurseEnd");
+ for (int i = 0; i < depth - 2; ++i) {
+ methods.add((i % 2) == 0 ? "recurseA" : "recurseB");
+ }
+ methods.add("run");
+ if (depth > MAX_DEPTH) {
+ methods = methods.subList(0, MAX_DEPTH);
+ }
+ return methods;
+ }
}
diff --git a/test/jdk/jdk/jfr/event/profiling/classes/test/RecursiveMethods.java b/test/jdk/jdk/jfr/event/profiling/classes/test/RecursiveMethods.java
deleted file mode 100644
index 8dc77fd38da..00000000000
--- a/test/jdk/jdk/jfr/event/profiling/classes/test/RecursiveMethods.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2025 SAP SE. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
- package test;
-
- import java.time.Duration;
-
- /*
- * A class used to create a simple deep call stack for testing purposes
- */
- public class RecursiveMethods {
-
- /** Method that uses recursion to produce a call stack of at least {@code depth} depth */
- public static int entry(int depth) {
- return method2(--depth);
- }
-
- private static int method2(int depth) {
- return method3(--depth);
- }
-
- private static int method3(int depth) {
- return method4(--depth);
- }
-
- private static int method4(int depth) {
- return method5(--depth);
- }
-
- private static int method5(int depth) {
- return method6(--depth);
- }
-
- private static int method6(int depth) {
- return method7(--depth);
- }
-
- private static int method7(int depth) {
- return method8(--depth);
- }
-
- private static int method8(int depth) {
- return method9(--depth);
- }
-
- private static int method9(int depth) {
- return method10(--depth);
- }
-
- private static int method10(int depth) {
- if (depth > 0) {
- return entry(--depth);
- }
- return depth;
- }
-}
diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java
index a00898358a8..904abe8e3e2 100644
--- a/test/lib/jdk/test/lib/jfr/EventNames.java
+++ b/test/lib/jdk/test/lib/jfr/EventNames.java
@@ -77,8 +77,6 @@ public class EventNames {
public static final String ThreadAllocationStatistics = PREFIX + "ThreadAllocationStatistics";
public static final String ExecutionSample = PREFIX + "ExecutionSample";
public static final String NativeMethodSample = PREFIX + "NativeMethodSample";
- public static final String CPUTimeSample = PREFIX + "CPUTimeSample";
- public static final String CPUTimeSamplesLost = PREFIX + "CPUTimeSamplesLost";
public static final String ThreadDump = PREFIX + "ThreadDump";
public static final String OldObjectSample = PREFIX + "OldObjectSample";
public static final String SymbolTableStatistics = PREFIX + "SymbolTableStatistics";