aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang18-rt/include/sanitizer/tsan_interface.h
blob: e11a4175cd8ed9fad0dd7c832156b2011b075e2e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//===-- tsan_interface.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.
//
// Public interface header for TSan.
//===----------------------------------------------------------------------===//
#ifndef SANITIZER_TSAN_INTERFACE_H
#define SANITIZER_TSAN_INTERFACE_H

#include <sanitizer/common_interface_defs.h>

#ifdef __cplusplus
extern "C" {
#endif

// __tsan_release establishes a happens-before relation with a preceding
// __tsan_acquire on the same address.
void SANITIZER_CDECL __tsan_acquire(void *addr);
void SANITIZER_CDECL __tsan_release(void *addr);

// Annotations for custom mutexes.
// The annotations allow to get better reports (with sets of locked mutexes),
// detect more types of bugs (e.g. mutex misuses, races between lock/unlock and
// destruction and potential deadlocks) and improve precision and performance
// (by ignoring individual atomic operations in mutex code). However, the
// downside is that annotated mutex code itself is not checked for correctness.

// Mutex creation flags are passed to __tsan_mutex_create annotation.
// If mutex has no constructor and __tsan_mutex_create is not called,
// the flags may be passed to __tsan_mutex_pre_lock/__tsan_mutex_post_lock
// annotations.

// Mutex has static storage duration and no-op constructor and destructor.
// This effectively makes tsan ignore destroy annotation.
static const unsigned __tsan_mutex_linker_init      = 1 << 0;
// Mutex is write reentrant.
static const unsigned __tsan_mutex_write_reentrant  = 1 << 1;
// Mutex is read reentrant.
static const unsigned __tsan_mutex_read_reentrant   = 1 << 2;
// Mutex does not have static storage duration, and must not be used after
// its destructor runs.  The opposite of __tsan_mutex_linker_init.
// If this flag is passed to __tsan_mutex_destroy, then the destruction
// is ignored unless this flag was previously set on the mutex.
static const unsigned __tsan_mutex_not_static       = 1 << 8;

// Mutex operation flags:

// Denotes read lock operation.
static const unsigned __tsan_mutex_read_lock = 1 << 3;
// Denotes try lock operation.
static const unsigned __tsan_mutex_try_lock = 1 << 4;
// Denotes that a try lock operation has failed to acquire the mutex.
static const unsigned __tsan_mutex_try_lock_failed = 1 << 5;
// Denotes that the lock operation acquires multiple recursion levels.
// Number of levels is passed in recursion parameter.
// This is useful for annotation of e.g. Java builtin monitors,
// for which wait operation releases all recursive acquisitions of the mutex.
static const unsigned __tsan_mutex_recursive_lock = 1 << 6;
// Denotes that the unlock operation releases all recursion levels.
// Number of released levels is returned and later must be passed to
// the corresponding __tsan_mutex_post_lock annotation.
static const unsigned __tsan_mutex_recursive_unlock = 1 << 7;

// Convenient composed constants.
static const unsigned __tsan_mutex_try_read_lock =
    __tsan_mutex_read_lock | __tsan_mutex_try_lock;
static const unsigned __tsan_mutex_try_read_lock_failed =
    __tsan_mutex_try_read_lock | __tsan_mutex_try_lock_failed;

// Annotate creation of a mutex.
// Supported flags: mutex creation flags.
void SANITIZER_CDECL __tsan_mutex_create(void *addr, unsigned flags);

// Annotate destruction of a mutex.
// Supported flags:
//   - __tsan_mutex_linker_init
//   - __tsan_mutex_not_static
void SANITIZER_CDECL __tsan_mutex_destroy(void *addr, unsigned flags);

// Annotate start of lock operation.
// Supported flags:
//   - __tsan_mutex_read_lock
//   - __tsan_mutex_try_lock
//   - all mutex creation flags
void SANITIZER_CDECL __tsan_mutex_pre_lock(void *addr, unsigned flags);

// Annotate end of lock operation.
// Supported flags:
//   - __tsan_mutex_read_lock (must match __tsan_mutex_pre_lock)
//   - __tsan_mutex_try_lock (must match __tsan_mutex_pre_lock)
//   - __tsan_mutex_try_lock_failed
//   - __tsan_mutex_recursive_lock
//   - all mutex creation flags
void SANITIZER_CDECL __tsan_mutex_post_lock(void *addr, unsigned flags,
                                            int recursion);

// Annotate start of unlock operation.
// Supported flags:
//   - __tsan_mutex_read_lock
//   - __tsan_mutex_recursive_unlock
int SANITIZER_CDECL __tsan_mutex_pre_unlock(void *addr, unsigned flags);

// Annotate end of unlock operation.
// Supported flags:
//   - __tsan_mutex_read_lock (must match __tsan_mutex_pre_unlock)
void SANITIZER_CDECL __tsan_mutex_post_unlock(void *addr, unsigned flags);

// Annotate start/end of notify/signal/broadcast operation.
// Supported flags: none.
void SANITIZER_CDECL __tsan_mutex_pre_signal(void *addr, unsigned flags);
void SANITIZER_CDECL __tsan_mutex_post_signal(void *addr, unsigned flags);

// Annotate start/end of a region of code where lock/unlock/signal operation
// diverts to do something else unrelated to the mutex. This can be used to
// annotate, for example, calls into cooperative scheduler or contention
// profiling code.
// These annotations must be called only from within
// __tsan_mutex_pre/post_lock, __tsan_mutex_pre/post_unlock,
// __tsan_mutex_pre/post_signal regions.
// Supported flags: none.
void SANITIZER_CDECL __tsan_mutex_pre_divert(void *addr, unsigned flags);
void SANITIZER_CDECL __tsan_mutex_post_divert(void *addr, unsigned flags);

// Check that the current thread does not hold any mutexes,
// report a bug report otherwise.
void SANITIZER_CDECL __tsan_check_no_mutexes_held();

// External race detection API.
// Can be used by non-instrumented libraries to detect when their objects are
// being used in an unsafe manner.
//   - __tsan_external_read/__tsan_external_write annotates the logical reads
//       and writes of the object at the specified address. 'caller_pc' should
//       be the PC of the library user, which the library can obtain with e.g.
//       `__builtin_return_address(0)`.
//   - __tsan_external_register_tag registers a 'tag' with the specified name,
//       which is later used in read/write annotations to denote the object type
//   - __tsan_external_assign_tag can optionally mark a heap object with a tag
void *SANITIZER_CDECL __tsan_external_register_tag(const char *object_type);
void SANITIZER_CDECL __tsan_external_register_header(void *tag,
                                                     const char *header);
void SANITIZER_CDECL __tsan_external_assign_tag(void *addr, void *tag);
void SANITIZER_CDECL __tsan_external_read(void *addr, void *caller_pc,
                                          void *tag);
void SANITIZER_CDECL __tsan_external_write(void *addr, void *caller_pc,
                                           void *tag);

// Fiber switching API.
//   - TSAN context for fiber can be created by __tsan_create_fiber
//     and freed by __tsan_destroy_fiber.
//   - TSAN context of current fiber or thread can be obtained
//     by calling __tsan_get_current_fiber.
//   - __tsan_switch_to_fiber should be called immediately before switch
//     to fiber, such as call of swapcontext.
//   - Fiber name can be set by __tsan_set_fiber_name.
void *SANITIZER_CDECL __tsan_get_current_fiber(void);
void *SANITIZER_CDECL __tsan_create_fiber(unsigned flags);
void SANITIZER_CDECL __tsan_destroy_fiber(void *fiber);
void SANITIZER_CDECL __tsan_switch_to_fiber(void *fiber, unsigned flags);
void SANITIZER_CDECL __tsan_set_fiber_name(void *fiber, const char *name);

// Flags for __tsan_switch_to_fiber:
// Do not establish a happens-before relation between fibers
static const unsigned __tsan_switch_to_fiber_no_sync = 1 << 0;

// User-provided callback invoked on TSan initialization.
void SANITIZER_CDECL __tsan_on_initialize();

// User-provided callback invoked on TSan shutdown.
// `failed` - Nonzero if TSan did detect issues, zero otherwise.
// Return `0` if TSan should exit as if no issues were detected.  Return nonzero
// if TSan should exit as if issues were detected.
int SANITIZER_CDECL __tsan_on_finalize(int failed);

// Release TSan internal memory in a best-effort manner.
void SANITIZER_CDECL __tsan_flush_memory();

// User-provided default TSAN options.
const char *SANITIZER_CDECL __tsan_default_options(void);

// User-provided default TSAN suppressions.
const char *SANITIZER_CDECL __tsan_default_suppressions(void);

/// Returns a report's description.
///
/// Returns a report's description (issue type), number of duplicate issues
/// found, counts of array data (stack traces, memory operations, locations,
/// mutexes, threads, unique thread IDs) and a stack trace of a <c>sleep()</c>
/// call (if one was involved in the issue).
///
/// \param report Opaque pointer to the current report.
/// \param[out] description Report type description.
/// \param[out] count Count of duplicate issues.
/// \param[out] stack_count Count of stack traces.
/// \param[out] mop_count Count of memory operations.
/// \param[out] loc_count Count of locations.
/// \param[out] mutex_count Count of mutexes.
/// \param[out] thread_count Count of threads.
/// \param[out] unique_tid_count Count of unique thread IDs.
/// \param sleep_trace A buffer to store the stack trace of a <c>sleep()</c>
/// call.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_data(
    void *report, const char **description, int *count, int *stack_count,
    int *mop_count, int *loc_count, int *mutex_count, int *thread_count,
    int *unique_tid_count, void **sleep_trace, unsigned long trace_size);

/// Returns information about stack traces included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's stacks.
/// \param trace A buffer to store the stack trace.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_stack(void *report, unsigned long idx,
                                            void **trace,
                                            unsigned long trace_size);

/// Returns information about memory operations included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's memory operations.
/// \param[out] tid Thread ID of the memory operation.
/// \param[out] addr Address of the memory operation.
/// \param[out] size Size of the memory operation.
/// \param[out] write Write flag of the memory operation.
/// \param[out] atomic Atomicity flag of the memory operation.
/// \param trace A buffer to store the stack trace.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_mop(void *report, unsigned long idx,
                                          int *tid, void **addr, int *size,
                                          int *write, int *atomic, void **trace,
                                          unsigned long trace_size);

/// Returns information about locations included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's locations.
/// \param[out] type Type of the location.
/// \param[out] addr Address of the location.
/// \param[out] start Start of the location.
/// \param[out] size Size of the location.
/// \param[out] tid Thread ID of the location.
/// \param[out] fd File descriptor of the location.
/// \param[out] suppressable Suppressable flag.
/// \param trace A buffer to store the stack trace.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_loc(void *report, unsigned long idx,
                                          const char **type, void **addr,
                                          void **start, unsigned long *size,
                                          int *tid, int *fd, int *suppressable,
                                          void **trace,
                                          unsigned long trace_size);

/// Returns information about mutexes included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's mutexes.
/// \param[out] mutex_id Id of the mutex.
/// \param[out] addr Address of the mutex.
/// \param[out] destroyed Destroyed mutex flag.
/// \param trace A buffer to store the stack trace.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_mutex(void *report, unsigned long idx,
                                            uint64_t *mutex_id, void **addr,
                                            int *destroyed, void **trace,
                                            unsigned long trace_size);

/// Returns information about threads included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's threads.
/// \param[out] tid Thread ID of the thread.
/// \param[out] os_id Operating system's ID of the thread.
/// \param[out] running Running flag of the thread.
/// \param[out] name Name of the thread.
/// \param[out] parent_tid ID of the parent thread.
/// \param trace A buffer to store the stack trace.
/// \param trace_size Size in bytes of the trace buffer.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_thread(void *report, unsigned long idx,
                                             int *tid, uint64_t *os_id,
                                             int *running, const char **name,
                                             int *parent_tid, void **trace,
                                             unsigned long trace_size);

/// Returns information about unique thread IDs included in the report.
///
/// \param report Opaque pointer to the current report.
/// \param idx Index to the report's unique thread IDs.
/// \param[out] tid Unique thread ID of the report.
/// \returns Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __tsan_get_report_unique_tid(void *report,
                                                 unsigned long idx, int *tid);

/// Returns the current report.
///
/// If TSan is currently reporting a detected issue on the current thread,
/// returns an opaque pointer to the current report. Otherwise returns NULL.
/// \returns An opaque pointer to the current report. Otherwise returns NULL.
void *SANITIZER_CDECL __tsan_get_current_report();

#ifdef __cplusplus
} // extern "C"
#endif

#endif // SANITIZER_TSAN_INTERFACE_H