58 lines
1.7 KiB
Rust
58 lines
1.7 KiB
Rust
// Verifies that ThreadSanitizer is able to detect a data race in heap allocated
|
|
// memory block.
|
|
//
|
|
// Test case minimizes the use of the standard library to avoid its ambiguous
|
|
// status with respect to instrumentation (it could vary depending on whatever
|
|
// a function call is inlined or not).
|
|
//
|
|
// The conflicting data access is de-facto synchronized with a special TSAN
|
|
// barrier, which does not introduce synchronization from TSAN perspective, but
|
|
// is necessary to make the test robust. Without the barrier data race detection
|
|
// would occasionally fail, making test flaky.
|
|
//
|
|
// needs-sanitizer-support
|
|
// needs-sanitizer-thread
|
|
//
|
|
// compile-flags: -Z sanitizer=thread -O
|
|
//
|
|
// run-fail
|
|
// error-pattern: WARNING: ThreadSanitizer: data race
|
|
// error-pattern: Location is heap block of size 4
|
|
// error-pattern: allocated by main thread
|
|
|
|
#![feature(raw_ref_op)]
|
|
#![feature(rustc_private)]
|
|
extern crate libc;
|
|
|
|
use std::mem;
|
|
use std::ptr;
|
|
|
|
static mut BARRIER: u64 = 0;
|
|
|
|
extern "C" {
|
|
fn __tsan_testonly_barrier_init(barrier: *mut u64, count: u32);
|
|
fn __tsan_testonly_barrier_wait(barrier: *mut u64);
|
|
}
|
|
|
|
extern "C" fn start(c: *mut libc::c_void) -> *mut libc::c_void {
|
|
unsafe {
|
|
let c: *mut u32 = c.cast();
|
|
*c += 1;
|
|
__tsan_testonly_barrier_wait(&raw mut BARRIER);
|
|
ptr::null_mut()
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
unsafe {
|
|
__tsan_testonly_barrier_init(&raw mut BARRIER, 2);
|
|
let c: *mut u32 = Box::into_raw(Box::new(1));
|
|
let mut t: libc::pthread_t = mem::zeroed();
|
|
libc::pthread_create(&mut t, ptr::null(), start, c.cast());
|
|
__tsan_testonly_barrier_wait(&raw mut BARRIER);
|
|
*c += 1;
|
|
libc::pthread_join(t, ptr::null_mut());
|
|
Box::from_raw(c);
|
|
}
|
|
}
|