[llvm-branch-commits] [compiler-rt] [NFC][TSan] Move ObtainCurrentStack out of ThreadRegistryLock scope (PR #228794)

Vitaly Buka via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Oct 3 19:07:13 PDT 2026


https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/228794

>From 5729303d68d2a4ad588e6e4126ac477073e09b96 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Sat, 3 Oct 2026 19:00:54 -0700
Subject: [PATCH] [NFC][TSan] Move ObtainCurrentStack out of ThreadRegistryLock
 scope

ObtainCurrentStack only reads the current thread's shadow stack and
allocates a VarSizeStackTrace buffer, which does not require
ThreadRegistryLock (and already runs outside ThreadRegistryLock in
ReportRace, SignalUnsafeCall, and ReportErrnoSpoiling).

Move ObtainCurrentStack (and dummy_pc in ReportDeadlock) before
ScopedReport in ReportMutexHeldWrongContext, ReportMutexMisuse,
ReportDeadlock, and ReportDestroyLocked so the stack trace buffers also
outlive ScopedReport and OutputReport.

Assisted-by: Gemini

Pull Request: https://github.com/llvm/llvm-project/pull/228794
---
 compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp |  4 ++--
 compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp     | 11 ++++++-----
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
index 526dc5a753c24f3..e520ead1d36aa4a 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
@@ -441,6 +441,8 @@ void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
 }
 
 static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
+  VarSizeStackTrace trace;
+  ObtainCurrentStack(thr, pc, &trace);
   // Use alloca, because malloc during signal handling deadlocks
   ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
   // Release locks before symbolizing and outputting the report to avoid
@@ -452,8 +454,6 @@ static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
       MutexSet::Desc desc = thr->mset.Get(i);
       rep->AddMutex(desc.addr, desc.stack_id);
     }
-    VarSizeStackTrace trace;
-    ObtainCurrentStack(thr, pc, &trace);
     rep->AddStack(trace, true);
   }
   OutputReport(thr, *rep);
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
index 271412f4c408853..71f77596c8ae221 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
@@ -56,6 +56,8 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
     return;
   if (!ShouldReport(thr, typ))
     return;
+  VarSizeStackTrace trace;
+  ObtainCurrentStack(thr, pc, &trace);
   // Use alloca, because malloc during signal handling deadlocks
   ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
   // Release locks before symbolizing and outputting the report to avoid
@@ -64,8 +66,6 @@ static void ReportMutexMisuse(ThreadState *thr, uptr pc, ReportType typ,
     ThreadRegistryLock l(&ctx->thread_registry);
     new (rep) ScopedReport(typ);
     rep->AddMutex(addr, creation_stack_id);
-    VarSizeStackTrace trace;
-    ObtainCurrentStack(thr, pc, &trace);
     rep->AddStack(trace, true);
     rep->AddLocation(addr, 1);
   }
@@ -538,6 +538,7 @@ void AfterSleep(ThreadState *thr, uptr pc) {
 void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
   if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
     return;
+  uptr dummy_pc = 0x42;
   // Use alloca, because malloc during signal handling deadlocks
   ScopedReport *rep = (ScopedReport *)__builtin_alloca(sizeof(ScopedReport));
   // Release locks before symbolizing and outputting the report to avoid
@@ -550,7 +551,6 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
       rep->AddUniqueTid((int)r->loop[i].thr_ctx);
       rep->AddThread((int)r->loop[i].thr_ctx);
     }
-    uptr dummy_pc = 0x42;
     for (int i = 0; i < r->n; i++) {
       for (int j = 0; j < (flags()->second_deadlock_stack ? 2 : 1); j++) {
         u32 stk = r->loop[i].stk[j];
@@ -590,6 +590,9 @@ void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
       return;
   }
 
+  VarSizeStackTrace trace;
+  ObtainCurrentStack(thr, pc, &trace);
+
   // Use alloca, because malloc during signal handling deadlocks
   ScopedReport* rep = (ScopedReport*)__builtin_alloca(sizeof(ScopedReport));
   // Release locks before symbolizing and outputting the report to avoid
@@ -598,8 +601,6 @@ void ReportDestroyLocked(ThreadState *thr, uptr pc, uptr addr,
     ThreadRegistryLock l0(&ctx->thread_registry);
     new (rep) ScopedReport(ReportTypeMutexDestroyLocked);
     rep->AddMutex(addr, creation_stack_id);
-    VarSizeStackTrace trace;
-    ObtainCurrentStack(thr, pc, &trace);
     rep->AddStack(trace, true);
     rep->AddStack(last_lock_stack, true);
     rep->AddLocation(addr, 1);



More information about the llvm-branch-commits mailing list