@@ -154,122 +154,6 @@ void WallClockASGCT::initialize(Arguments& args) {
154154 OS::installSignalHandler (SIGVTALRM, sharedSignalHandler);
155155}
156156
157- /* This method is extremely racy!
158- * Thread references, that are returned from JVMTI::GetAllThreads(), only guarantee thread objects
159- * are not collected by GCs, they don't prevent threads from exiting.
160- * We have to be extremely careful when accessing thread's data, so it may not be valid.
161- */
162- void WallClockJVMTI::timerLoop () {
163- // Check for enablement before attaching/dettaching the current thread
164- if (!isEnabled ()) {
165- return ;
166- }
167-
168- jvmtiEnv* jvmti = VM::jvmti ();
169- if (jvmti == nullptr ) {
170- return ;
171- }
172-
173- // Notice:
174- // We want to cache threads that are captured by collectThread(), so that we can
175- // clean them up in cleanThreadRefs().
176- // The approach is not ideal, but it is cleaner than cleaning individual thread
177- // during filtering phases.
178- jint threads_count = 0 ;
179- jthread* threads_ptr = nullptr ;
180-
181- // Attach to JVM as the first step
182- VM::attachThread (" Datadog Profiler Wallclock Sampler" );
183- auto collectThreads = [&](std::vector<ThreadEntry>& threads) {
184- jvmtiEnv* jvmti = VM::jvmti ();
185- if (jvmti == nullptr ) {
186- return ;
187- }
188-
189- if (jvmti->GetAllThreads (&threads_count, &threads_ptr) != JVMTI_ERROR_NONE ||
190- threads_count == 0 ) {
191- return ;
192- }
193-
194- JNIEnv* jni = VM::jni ();
195-
196- ThreadFilter* threadFilter = Profiler::instance ()->threadFilter ();
197- bool do_filter = threadFilter->enabled ();
198- int self = OS::threadId ();
199-
200- // If filtering is enabled, collect the filtered TIDs first
201- std::vector<int > filtered_tids;
202- if (do_filter) {
203- Profiler::instance ()->threadFilter ()->collect (filtered_tids);
204- // Sort the TIDs for efficient lookup
205- std::sort (filtered_tids.begin (), filtered_tids.end ());
206- }
207-
208- for (int i = 0 ; i < threads_count; i++) {
209- jthread thread = threads_ptr[i];
210- if (thread != nullptr ) {
211- VMThread* nThread = VMThread::fromJavaThread (jni, thread);
212- if (nThread == nullptr ) {
213- continue ;
214- }
215- int tid = nThread->osThreadId ();
216- if (tid != self && (!do_filter ||
217- // Use binary search to efficiently find if tid is in filtered_tids
218- std::binary_search (filtered_tids.begin (), filtered_tids.end (), tid))) {
219- threads.push_back ({nThread, thread, tid});
220- }
221- }
222- }
223- };
224-
225- auto sampleThreads = [&](ThreadEntry& thread_entry, int & num_failures, int & threads_already_exited, int & permission_denied) {
226- static jint max_stack_depth = (jint)Profiler::instance ()->max_stack_depth ();
227-
228- ExecutionEvent event;
229- VMThread* vm_thread = thread_entry.native ;
230- int raw_thread_state = vm_thread->state ();
231- bool is_initialized = raw_thread_state >= JVMJavaThreadState::_thread_in_native &&
232- raw_thread_state < JVMJavaThreadState::_thread_max_state;
233- OSThreadState state = OSThreadState::UNKNOWN;
234- ExecutionMode mode = ExecutionMode::UNKNOWN;
235- if (vm_thread == nullptr || !is_initialized) {
236- return false ;
237- }
238- OSThreadState os_state = vm_thread->osThreadState ();
239- if (os_state == OSThreadState::TERMINATED) {
240- return false ;
241- } else if (os_state == OSThreadState::UNKNOWN) {
242- state = OSThreadState::RUNNABLE;
243- } else {
244- state = os_state;
245- }
246- mode = getThreadExecutionMode ();
247-
248- event._thread_state = state;
249- event._execution_mode = mode;
250- event._weight = 1 ;
251-
252- Profiler::instance ()->recordJVMTISample (1 , thread_entry.tid , thread_entry.java , BCI_WALL, &event, false );
253- return true ;
254- };
255-
256- auto cleanThreadRefs = [&]() {
257- JNIEnv* jni = VM::jni ();
258- for (jint index = 0 ; index < threads_count; index++) {
259- jni->DeleteLocalRef (threads_ptr[index]);
260- }
261- jvmti->Deallocate ((unsigned char *)threads_ptr);
262- threads_ptr = nullptr ;
263- threads_count = 0 ;
264- };
265-
266- timerLoopCommon<ThreadEntry>(collectThreads, sampleThreads, cleanThreadRefs, _reservoir_size, _interval);
267-
268-
269- // Don't forget to detach the thread
270- VM::detachThread ();
271- }
272-
273157void WallClockASGCT::timerLoop () {
274158 // todo: re-allocating the vector every time is not efficient
275159 auto collectThreads = [&](std::vector<int >& tids) {
0 commit comments