@@ -396,20 +396,6 @@ static bool decodeJavaBlockState(jint state, OSThreadState &decoded) {
396396 return false ;
397397}
398398
399- static OSThreadState decodeTaskBlockObservedState (jint state) {
400- switch (static_cast <OSThreadState>(state)) {
401- case OSThreadState::MONITOR_WAIT :
402- case OSThreadState::CONDVAR_WAIT :
403- case OSThreadState::OBJECT_WAIT :
404- case OSThreadState::SLEEPING :
405- case OSThreadState::SYSCALL :
406- case OSThreadState::IO_WAIT :
407- return static_cast <OSThreadState>(state);
408- default :
409- return OSThreadState::UNKNOWN ;
410- }
411- }
412-
413399static bool snapshotAndExitBlockedRun (jlong token, BlockRunSnapshot *snapshot) {
414400 if (token <= 0 ) {
415401 return false ;
@@ -433,23 +419,6 @@ static bool snapshotAndExitBlockedRun(jlong token, BlockRunSnapshot *snapshot) {
433419 return tf->exitBlockedRun (slot_id, generation);
434420}
435421
436- static void writeBlockRunSnapshot (JNIEnv *env, jlongArray snapshot_array,
437- const BlockRunSnapshot *snapshot) {
438- if (snapshot_array == nullptr || env->GetArrayLength (snapshot_array) < 3 ) {
439- return ;
440- }
441- jlong values[3 ] = {0 , 0 , static_cast <jlong>(OSThreadState::UNKNOWN )};
442- if (snapshot != nullptr ) {
443- OSThreadState observed_state = snapshot->sampled_state != OSThreadState::UNKNOWN
444- ? snapshot->sampled_state
445- : snapshot->active_state ;
446- values[0 ] = snapshot->has_stack_reference ? static_cast <jlong>(snapshot->call_trace_id ) : 0 ;
447- values[1 ] = snapshot->has_stack_reference ? static_cast <jlong>(snapshot->correlation_id ) : 0 ;
448- values[2 ] = static_cast <jlong>(observed_state);
449- }
450- env->SetLongArrayRegion (snapshot_array, 0 , 3 , values);
451- }
452-
453422extern " C" DLLEXPORT jlong JNICALL
454423Java_com_datadoghq_profiler_JavaProfiler_blockEnter0 (
455424 JNIEnv *env, jclass unused, jint state) {
@@ -479,18 +448,79 @@ Java_com_datadoghq_profiler_JavaProfiler_blockExit0(
479448 snapshotAndExitBlockedRun (token, nullptr );
480449}
481450
482- extern " C" DLLEXPORT void JNICALL
483- Java_com_datadoghq_profiler_JavaProfiler_blockExitWithSnapshot0 (
484- JNIEnv *env, jclass unused, jlong token, jlongArray snapshotArray) {
451+ extern " C" DLLEXPORT jlong JNICALL
452+ Java_com_datadoghq_profiler_JavaProfiler_beginTaskBlock0 (
453+ JNIEnv *env, jclass unused, jint state) {
454+ OSThreadState decoded;
455+ if (!decodeJavaBlockState (state, decoded)) {
456+ return 0 ;
457+ }
458+ ProfiledThread* current = ProfiledThread::current ();
459+ if (current == nullptr ) {
460+ return 0 ;
461+ }
462+ if (VM::isHotspot () && VM::hotspot_version () >= 21 ) {
463+ VMThread* carrier = VMThread::current ();
464+ if (carrier != nullptr && carrier->isCarryingVirtualThread ()) {
465+ return 0 ;
466+ }
467+ }
468+ Profiler* profiler = Profiler::instance ();
469+ if (!profiler->isRunning () || !profiler->taskBlockAsyncActive ()) {
470+ return 0 ;
471+ }
472+ ThreadFilter* tf = profiler->threadFilter ();
473+ ThreadFilter::SlotID slot_id = current->filterSlotId ();
474+ if (!tf->enabled () || slot_id < 0 ) {
475+ return 0 ;
476+ }
477+ u64 token = tf->enterBlockedRun (slot_id, decoded, BlockRunOwner::JAVA );
478+ if (!current->taskBlockEnter (token, TSC::ticks (), ContextApi::snapshot ())) {
479+ tf->exitBlockedRun (slot_id, ThreadFilter::tokenGeneration (token));
480+ return 0 ;
481+ }
482+ return static_cast <jlong>(token);
483+ }
484+
485+ extern " C" DLLEXPORT jboolean JNICALL
486+ Java_com_datadoghq_profiler_JavaProfiler_endTaskBlock0 (
487+ JNIEnv *env, jclass unused, jlong token, jlong blocker,
488+ jlong unblockingSpanId) {
489+ ProfiledThread* current = ProfiledThread::current ();
490+ if (current == nullptr || token <= 0 ) {
491+ return JNI_FALSE ;
492+ }
493+ u64 start_ticks = 0 ;
494+ Context context{};
495+ if (!current->taskBlockExit (static_cast <u64 >(token), start_ticks, context)) {
496+ return JNI_FALSE ;
497+ }
498+ Profiler* profiler = Profiler::instance ();
499+ bool activity = profiler->tryEnterTaskBlockActivity ();
500+ if (!activity) {
501+ profiler->waitForTaskBlockRotation ();
502+ }
503+ ThreadFilter* tf = profiler->threadFilter ();
504+ ThreadFilter::SlotID slot_id = ThreadFilter::tokenSlotId (static_cast <u64 >(token));
485505 BlockRunSnapshot snapshot{};
486- snapshot.active_state = OSThreadState::UNKNOWN ;
487- snapshot.sampled_state = OSThreadState::UNKNOWN ;
488- snapshot.owner = BlockRunOwner::NONE ;
489- if (snapshotAndExitBlockedRun (token, &snapshot)) {
490- writeBlockRunSnapshot (env, snapshotArray, &snapshot);
491- } else {
492- writeBlockRunSnapshot (env, snapshotArray, nullptr );
506+ bool exited = current->filterSlotId () == slot_id &&
507+ tf->snapshotAndExitBlockedRun (
508+ slot_id, ThreadFilter::tokenGeneration (static_cast <u64 >(token)), &snapshot);
509+ if (!activity) {
510+ Counters::increment (TASK_BLOCK_DROPPED_ROTATION );
511+ return JNI_FALSE ;
512+ }
513+ bool recorded = false ;
514+ if (exited) {
515+ OSThreadState observed_state = snapshot.sampled_state != OSThreadState::UNKNOWN
516+ ? snapshot.sampled_state : snapshot.active_state ;
517+ recorded = recordTaskBlockWithStackReferenceIfEligible (
518+ current->tid (), start_ticks, TSC::ticks (), context, (u64 )blocker,
519+ (u64 )unblockingSpanId, snapshot.call_trace_id ,
520+ snapshot.correlation_id , observed_state, true );
493521 }
522+ profiler->leaveTaskBlockActivity ();
523+ return recorded ? JNI_TRUE : JNI_FALSE ;
494524}
495525
496526extern " C" DLLEXPORT jboolean JNICALL
@@ -528,40 +558,6 @@ Java_com_datadoghq_profiler_JavaProfiler_recordTaskBlockWithContext0(
528558 : JNI_FALSE ;
529559}
530560
531- extern " C" DLLEXPORT jboolean JNICALL
532- Java_com_datadoghq_profiler_JavaProfiler_recordTaskBlockFromContext0 (
533- JNIEnv *env, jclass unused, jint tid, jlong startTicks, jlong endTicks,
534- jlong blocker, jlong unblockingSpanId, jlong spanId, jlong rootSpanId) {
535- // Drain-thread path: called from background drain thread on behalf of the sleeping thread.
536- // tid is the OS tid of the sleeping thread; span context is explicit to bypass OTEP TLS.
537- if ((int )tid < 0 ) {
538- return JNI_FALSE ;
539- }
540- Context ctx{(u64 )spanId, (u64 )rootSpanId};
541- return recordTaskBlockWithStackReferenceIfEligible (
542- (int )tid, (u64 )startTicks, (u64 )endTicks, ctx, (u64 )blocker,
543- (u64 )unblockingSpanId, 0 , 0 , OSThreadState::UNKNOWN )
544- ? JNI_TRUE
545- : JNI_FALSE ;
546- }
547-
548- extern " C" DLLEXPORT jboolean JNICALL
549- Java_com_datadoghq_profiler_JavaProfiler_recordTaskBlockFromContextWithStackReference0 (
550- JNIEnv *env, jclass unused, jint tid, jlong startTicks, jlong endTicks,
551- jlong blocker, jlong unblockingSpanId, jlong spanId, jlong rootSpanId,
552- jlong callTraceId, jlong correlationId, jint observedBlockingState) {
553- if ((int )tid < 0 ) {
554- return JNI_FALSE ;
555- }
556- Context ctx{(u64 )spanId, (u64 )rootSpanId};
557- return recordTaskBlockWithStackReferenceIfEligible (
558- (int )tid, (u64 )startTicks, (u64 )endTicks, ctx, (u64 )blocker,
559- (u64 )unblockingSpanId, (u64 )callTraceId, (u64 )correlationId,
560- decodeTaskBlockObservedState (observedBlockingState))
561- ? JNI_TRUE
562- : JNI_FALSE ;
563- }
564-
565561extern " C" DLLEXPORT jlong JNICALL
566562Java_com_datadoghq_profiler_JavaProfiler_currentTicks0 (JNIEnv *env,
567563 jclass unused) {
0 commit comments