[compiler-rt] [llvm] [tsan] Introduce Adaptive Delay Scheduling to TSAN (PR #178836)

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 15 02:35:00 PST 2026


================
@@ -0,0 +1,170 @@
+//===-- tsan_adaptive_delay.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of ThreadSanitizer (TSan), a race detector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TSAN_ADAPTIVE_DELAY_H
+#define TSAN_ADAPTIVE_DELAY_H
+
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __tsan {
+
+extern bool is_adaptive_delay_enabled;
+
+// AdaptiveDelay injects delays at synchronization points, atomic operations,
+// and thread lifecycle events to increase the likelihood of exposing data
+// races. The delay injection is controlled by an approximate time budget to
+// maintain a configurable overhead target.
+//
+// SyncOp() delays non-atomic synchronization points (those with clear
+// happens-before relationships):
+//  - Acquire operations like locking a mutex delays before the mutex is locked.
+//  - Release operations like unlocking a mutex delays after the mutex is
+//  unlocked
+// These are more likely to expose interesting (rare) thread interleavings.
+// For example, delaying a thread that unlocks a mutex from running to allow
+// newly woken thread to execute before the unlocking thread would normally
+// execute.
+struct AdaptiveDelay {
+  ALWAYS_INLINE static void Init() { InitImpl(); }
+
+  ALWAYS_INLINE static void SyncOp() {
+    if (!is_adaptive_delay_enabled)
+      return;
+    SyncOpImpl();
+  }
+
+  ALWAYS_INLINE static void AtomicOpFence(int mo) {
+    if (!is_adaptive_delay_enabled)
+      return;
+    AtomicOpFenceImpl(mo);
+  }
+
+  ALWAYS_INLINE static void AtomicOpAddr(__sanitizer::uptr addr, int mo) {
+    if (!is_adaptive_delay_enabled)
+      return;
+    AtomicOpAddrImpl(addr, mo);
+  }
+
+  ALWAYS_INLINE static void AfterThreadCreation() {
+    if (!is_adaptive_delay_enabled)
+      return;
+    AfterThreadCreationImpl();
+  }
+
+  ALWAYS_INLINE static void BeforeChildThreadRuns() {
+    if (!is_adaptive_delay_enabled)
+      return;
+    BeforeChildThreadRunsImpl();
+  }
+
+ private:
+  static void InitImpl();
+
+  static void SyncOpImpl();
+
+  static void AtomicOpFenceImpl(int mo);
+  static void AtomicOpAddrImpl(__sanitizer::uptr addr, int mo);
+
+  static void AfterThreadCreationImpl();
+  static void BeforeChildThreadRunsImpl();
+};
+
+AdaptiveDelay& GetAdaptiveDelay();
----------------
dvyukov wrote:

This does not seem to be used.

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


More information about the llvm-commits mailing list