[clang] [compiler-rt] [tsan] Add simulation to TSAN (PR #183200)

Chris Cotter via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 12 20:59:37 PDT 2026


================
@@ -327,6 +327,281 @@ Increase sampling frequency for mutex operations:
 
   $ TSAN_OPTIONS=enable_adaptive_delay=1:adaptive_delay_mutex_sample_rate=5 ./myapp
 
+Simulation Scheduler
+--------------------
+
+Overview
+~~~~~~~~
+
+The Simulation Scheduler is an optional ThreadSanitizer feature that enables
+systematic exploration of thread interleavings to expose data races that may be
+difficult to trigger in normal execution. Unlike standard ThreadSanitizer which
+detects races as they occur naturally during program execution, the simulation
+scheduler takes control of thread scheduling to deliberately explore different
+execution orderings.
+
+Simulation is particularly useful for:
+
+* Testing concurrent data structure or algorithms during development to ensure
+  correctness (for example, a lock free queue).
+* Finding races in rarely-executed interleavings that standard TSAN may miss
+* Reproducing specific race conditions deterministically
+
+Simulation is not useful for running full applications, and will likely not
+work in these scenarios. The code run in simulation should almost always be a
+small unit test exercising very specific functionality.
+
+When enabled via the ``__tsan_simulate()`` API, the simulation scheduler runs
+the program's concurrent code multiple times (iterations), choosing different
+thread interleavings in each iteration. The scheduler injects context switches
+at synchronization points (atomic operations, mutex operations, thread lifecycle
+events) to maximize coverage of possible execution orderings. If a data race is
+detected, the simulation stops and reports which iteration exposed the race,
+allowing that specific interleaving to be reproduced.
+
+Usage
+~~~~~
+
+To use simulation, wrap the concurrent code you want to test in a callback
+function and invoke it through the ``__tsan_simulate()`` API:
+
+.. code-block:: c
+
+    extern "C" int __tsan_simulate(void (*callback)(void *), void *arg);
+
+    void test_concurrent_code(void *arg) {
+      // Create threads, run concurrent operations
+      pthread_t t1, t2;
+      pthread_create(&t1, NULL, thread_func, NULL);
+      pthread_create(&t2, NULL, thread_func, NULL);
+      pthread_join(t1, NULL);
+      pthread_join(t2, NULL);
+    }
+
+    int main() {
+      return __tsan_simulate(test_concurrent_code, NULL);
+    }
+
+Then compile with ThreadSanitizer and enable the simulation scheduler:
+
+.. code-block:: console
+
+  $ clang -fsanitize=thread -g -O1 mytest.c
+  $ TSAN_OPTIONS=simulate_scheduler=random ./a.out
+  ThreadSanitizer: simulation starting (iterations 0..999, max_depth=10000, scheduler=random)
+
+Automatic Main Wrapping
----------------
ccotter wrote:

I updated the docs suggesting the --wrap approach and removed the feature from being implemented within clang.

https://github.com/llvm/llvm-project/pull/183200


More information about the cfe-commits mailing list