Chris Cotter a591a44653
[tsan] Introduce Adaptive Delay Scheduling to TSAN (#178836)
This commit introduces an "adaptive delay" feature to the
ThreadSanitizer runtime to improve race detection by perturbing thread
schedules. At various synchronization points (atomic operations,
mutexes, and thread lifecycle events), the runtime may inject small
delays (spin loops, yields, or sleeps) to explore different thread
interleavings and expose data races that would otherwise occur only in
rare execution orders.

This change is inspired by prior work, which is discussed in more detail
on

https://discourse.llvm.org/t/rfc-tsan-implementing-a-fuzz-scheduler-for-tsan/80969.
In short, https://reviews.llvm.org/D65383 was an earlier unmerged
attempt at adding a random delays. Feedback on the RFC led to the
version in this commit, aiming to limit the amount of delay.

The adaptive delay feature uses a configurable time budget and tiered
sampling strategy to balance race exposure against performance impact.
It prioritizes high-value synchronization points with clear
happens-before relationships: relaxed atomics receive lightweight spin
delays with low sampling, synchronizing atomics (acquire / release /
seq_cst) receive moderate delays with higher sampling, and mutex and
thread lifecycle operations receive the longest delays with highest
sampling.

The feature is disabled by default and incurs minimal overhead when not
enabled. Nearly all checks are guarded by an inline check on a global
variable that is only set when enable_adaptive_delay=1. Microbenchmarks
with tight loops of atomic operations showed no meaningful performance
difference between an unmodified TSAN runtime and this version when
running with empty TSAN_OPTIONS.

An LLM assisted in writing portions of the adaptive delay logic,
including the TimeBudget class, tiering concept, address sampler, and
per-thread quota system. I reviewed the output and made amendments to
reduce duplication and simplify the behavior. I also replaced the LLM's
original double-based calculation logic with the integer-based Percent
class. The LLM also helped write unit test cases for Percent.

cc @dvyukov 

## Examples

I used the delay scheduler to find novel bugs that rarely or never
occurred with the unmodified TSAN runtime. Some of the bugs below were
found with earlier versions of the delay scheduler that I iterated on,
but with this most recent implementation in this PR, I can still find
the bugs far more reliably than with the standard TSAN runtime.

- A use-after-free in the
[BlazingMQ](https://github.com/bloomberg/blazingmq) broker during
ungraceful producer disconnect.
 - Race in stdexec: https://github.com/NVIDIA/stdexec/pull/1395
- Race in stdexec's MPSC queue:
https://github.com/NVIDIA/stdexec/pull/1812
- A few races in [BDE](https://github.com/bloomberg/bde) thread enabled
data structures/algorithms.
- The "Data race on variable a" test from
https://ceur-ws.org/Vol-2344/paper9.pdf is more reliably reproduced with
more aggressive adaptive scheduler options

# Outstanding work

- The
[RFC](https://discourse.llvm.org/t/rfc-tsan-implementing-a-fuzz-scheduler-for-tsan/80969)
suggests moving the scheduler to sanitizer_common, so that ASAN can
leverage this. This should be done (should it be done in this PR?).
 - Missing interceptors for libdispatch
2026-02-16 12:20:40 +01:00
..
2025-08-01 07:01:50 -07:00
2025-11-08 07:41:23 -08:00
2025-11-08 07:41:23 -08:00
2025-09-21 19:16:58 -07:00
2025-11-08 07:41:23 -08:00
2025-11-08 07:41:23 -08:00
2025-11-08 07:41:23 -08:00
2025-08-01 07:01:50 -07:00
2026-02-13 14:12:51 -08:00
2025-11-15 08:06:23 -08:00
2025-11-15 08:06:23 -08:00

LLVM Documentation
==================

LLVM's documentation is written in reStructuredText, a lightweight
plaintext markup language (file extension `.rst`). While the
reStructuredText documentation should be quite readable in source form, it
is mostly meant to be processed by the Sphinx documentation generation
system to create HTML pages which are hosted on <https://llvm.org/docs/> and
updated after every commit. Manpage output is also supported, see below.

If you instead would like to generate and view the HTML locally, install
Sphinx <http://sphinx-doc.org/> and then do:

    cd <build-dir>
    cmake -DLLVM_ENABLE_SPHINX=true -DSPHINX_OUTPUT_HTML=true <src-dir>
    make -j3 docs-llvm-html
    $BROWSER <build-dir>/docs/html/index.html

The mapping between reStructuredText files and generated documentation is
`docs/Foo.rst` <-> `<build-dir>/docs//html/Foo.html` <-> `https://llvm.org/docs/Foo.html`.

If you are interested in writing new documentation, you will want to read
`SphinxQuickstartTemplate.rst` which will get you writing documentation
very fast and includes examples of the most important reStructuredText
markup syntax.

Manpage Output
===============

Building the manpages is similar to building the HTML documentation. The
primary difference is to use the `man` makefile target, instead of the
default (which is `html`). Sphinx then produces the man pages in the
directory `<build-dir>/docs/man/`.

    cd <build-dir>
    cmake -DLLVM_ENABLE_SPHINX=true -DSPHINX_OUTPUT_MAN=true <src-dir>
    make -j3 docs-llvm-man
    man -l <build-dir>/docs/man/FileCheck.1

The correspondence between .rst files and man pages is
`docs/CommandGuide/Foo.rst` <-> `<build-dir>/docs//man/Foo.1`.
These .rst files are also included during HTML generation so they are also
viewable online (as noted above) at e.g.
`https://llvm.org/docs/CommandGuide/Foo.html`.

Checking links
==============

The reachability of external links in the documentation can be checked by
running:

    cd llvm/docs/
    sphinx-build -b linkcheck . _build/lintcheck/
    # report will be generated in _build/lintcheck/output.txt

Doxygen page Output
==============

Install doxygen <https://www.doxygen.nl/download.html> and dot2tex <https://dot2tex.readthedocs.io/en/latest>.

    cd <build-dir>
    cmake -DLLVM_ENABLE_DOXYGEN=On <llvm-top-src-dir>
    make doxygen-llvm # for LLVM docs
    make doxygen-clang # for clang docs

It will generate html in

    <build-dir>/docs/doxygen/html # for LLVM docs
    <build-dir>/tools/clang/docs/doxygen/html # for clang docs