summaryrefslogtreecommitdiffstats
path: root/src/test/ui/sanitize/thread.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/sanitize/thread.rs')
-rw-r--r--src/test/ui/sanitize/thread.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/test/ui/sanitize/thread.rs b/src/test/ui/sanitize/thread.rs
new file mode 100644
index 000000000..c70cf5acc
--- /dev/null
+++ b/src/test/ui/sanitize/thread.rs
@@ -0,0 +1,57 @@
+// 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);
+ }
+}