]>
Commit | Line | Data |
---|---|---|
ba9703b0 XL |
1 | // Verifies that ThreadSanitizer is able to detect a data race in heap allocated |
2 | // memory block. | |
3 | // | |
4 | // Test case minimizes the use of the standard library to avoid its ambiguous | |
5 | // status with respect to instrumentation (it could vary depending on whatever | |
6 | // a function call is inlined or not). | |
7 | // | |
8 | // The conflicting data access is de-facto synchronized with a special TSAN | |
9 | // barrier, which does not introduce synchronization from TSAN perspective, but | |
10 | // is necessary to make the test robust. Without the barrier data race detection | |
11 | // would occasionally fail, making test flaky. | |
12 | // | |
13 | // needs-sanitizer-support | |
f035d41b | 14 | // needs-sanitizer-thread |
ba9703b0 XL |
15 | // |
16 | // compile-flags: -Z sanitizer=thread -O | |
17 | // | |
18 | // run-fail | |
19 | // error-pattern: WARNING: ThreadSanitizer: data race | |
20 | // error-pattern: Location is heap block of size 4 | |
21 | // error-pattern: allocated by main thread | |
22 | ||
23 | #![feature(raw_ref_op)] | |
24 | #![feature(rustc_private)] | |
25 | extern crate libc; | |
26 | ||
27 | use std::mem; | |
28 | use std::ptr; | |
29 | ||
30 | static mut BARRIER: u64 = 0; | |
31 | ||
32 | extern "C" { | |
33 | fn __tsan_testonly_barrier_init(barrier: *mut u64, count: u32); | |
34 | fn __tsan_testonly_barrier_wait(barrier: *mut u64); | |
35 | } | |
36 | ||
37 | extern "C" fn start(c: *mut libc::c_void) -> *mut libc::c_void { | |
38 | unsafe { | |
39 | let c: *mut u32 = c.cast(); | |
40 | *c += 1; | |
41 | __tsan_testonly_barrier_wait(&raw mut BARRIER); | |
42 | ptr::null_mut() | |
43 | } | |
44 | } | |
45 | ||
46 | fn main() { | |
47 | unsafe { | |
48 | __tsan_testonly_barrier_init(&raw mut BARRIER, 2); | |
49 | let c: *mut u32 = Box::into_raw(Box::new(1)); | |
50 | let mut t: libc::pthread_t = mem::zeroed(); | |
51 | libc::pthread_create(&mut t, ptr::null(), start, c.cast()); | |
52 | __tsan_testonly_barrier_wait(&raw mut BARRIER); | |
53 | *c += 1; | |
54 | libc::pthread_join(t, ptr::null_mut()); | |
55 | Box::from_raw(c); | |
56 | } | |
57 | } |