Skip to content

do not protect SRW items #2248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/stacked_borrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,13 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
} else {
Permission::SharedReadWrite
};
let protector = if frozen {
protector
} else {
// We do not protect inside UnsafeCell.
// This fixes https://github.com/rust-lang/rust/issues/55005.
None
};
let item = Item { perm, tag: new_tag, protector };
let mut global = this.machine.stacked_borrows.as_ref().unwrap().borrow_mut();
stacked_borrows.for_each(range, |offset, stack, history| {
Expand Down
17 changes: 0 additions & 17 deletions tests/fail/stacked_borrows/deallocate_against_barrier2.rs

This file was deleted.

38 changes: 0 additions & 38 deletions tests/fail/stacked_borrows/deallocate_against_barrier2.stderr

This file was deleted.

19 changes: 19 additions & 0 deletions tests/pass/0concurrency_arc_drop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// ignore-windows: Concurrency on Windows is not supported yet.
use std::sync::Arc;
use std::thread;

/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005)
fn main() {
// The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9).
for _ in 0..700 {
let arc_1 = Arc::new(());
let arc_2 = arc_1.clone();
let thread = thread::spawn(|| drop(arc_2));
let mut i = 0;
while i < 256 {
i += 1;
}
drop(arc_1);
thread.join().unwrap();
}
}
2 changes: 1 addition & 1 deletion tests/pass/0weak_memory_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ fn test_single_thread() {
}

pub fn main() {
for _ in 0..50 {
for _ in 0..75 {
test_single_thread();
test_mixed_access();
test_load_buffering_acq_rel();
Expand Down
33 changes: 1 addition & 32 deletions tests/pass/concurrency/sync.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// ignore-windows: Concurrency on Windows is not supported yet.
// We are making scheduler assumptions here.
// compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance -Zmiri-preemption-rate=0
// compile-flags: -Zmiri-disable-isolation -Zmiri-strict-provenance

use std::sync::{Arc, Barrier, Condvar, Mutex, Once, RwLock};
use std::thread;
Expand Down Expand Up @@ -53,35 +52,6 @@ fn check_conditional_variables_notify_one() {
}
}

fn check_conditional_variables_notify_all() {
let pair = Arc::new(((Mutex::new(())), Condvar::new()));

// Spawn threads and block them on the conditional variable.
let handles: Vec<_> = (0..5)
.map(|_| {
let pair2 = pair.clone();
thread::spawn(move || {
let (lock, cvar) = &*pair2;
let guard = lock.lock().unwrap();
// Block waiting on the conditional variable.
let _ = cvar.wait(guard).unwrap();
})
})
.inspect(|_| {
thread::yield_now();
thread::yield_now();
})
.collect();

let (_, cvar) = &*pair;
// Unblock all threads.
cvar.notify_all();

for handle in handles {
handle.join().unwrap();
}
}

/// Test that waiting on a conditional variable with a timeout does not
/// deadlock.
fn check_conditional_variables_timed_wait_timeout() {
Expand Down Expand Up @@ -301,7 +271,6 @@ fn check_condvar() {
fn main() {
check_barriers();
check_conditional_variables_notify_one();
check_conditional_variables_notify_all();
check_conditional_variables_timed_wait_timeout();
check_conditional_variables_timed_wait_notimeout();
check_mutex();
Expand Down
40 changes: 40 additions & 0 deletions tests/pass/concurrency/sync_nopreempt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// ignore-windows: Concurrency on Windows is not supported yet.
// We are making scheduler assumptions here.
// compile-flags: -Zmiri-strict-provenance -Zmiri-preemption-rate=0

use std::sync::{Condvar, Mutex, Arc};
use std::thread;

fn check_conditional_variables_notify_all() {
let pair = Arc::new(((Mutex::new(())), Condvar::new()));

// Spawn threads and block them on the conditional variable.
let handles: Vec<_> = (0..5)
.map(|_| {
let pair2 = pair.clone();
thread::spawn(move || {
let (lock, cvar) = &*pair2;
let guard = lock.lock().unwrap();
// Block waiting on the conditional variable.
let _ = cvar.wait(guard).unwrap();
})
})
.inspect(|_| {
// Ensure the other threads all run and block on the `wait`.
thread::yield_now();
thread::yield_now();
})
.collect();

let (_, cvar) = &*pair;
// Unblock all threads.
cvar.notify_all();

for handle in handles {
handle.join().unwrap();
}
}

fn main() {
check_conditional_variables_notify_all();
}
35 changes: 34 additions & 1 deletion tests/pass/stacked-borrows/interior_mutability.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// compile-flags: -Zmiri-tag-raw-pointers
use std::cell::{Cell, RefCell, UnsafeCell};
use std::mem::MaybeUninit;
use std::mem::{self, MaybeUninit};

fn main() {
aliasing_mut_and_shr();
aliasing_frz_and_shr();
into_interior_mutability();
unsafe_cell_2phase();
unsafe_cell_deallocate();
unsafe_cell_invalidate();
}

fn aliasing_mut_and_shr() {
Expand Down Expand Up @@ -67,3 +70,33 @@ fn unsafe_cell_2phase() {
let _val = (*x2.get()).get(0);
}
}

/// Make sure we can deallocate an UnsafeCell that was passed to an active fn call.
/// (This is the fix for https://github.com/rust-lang/rust/issues/55005.)
fn unsafe_cell_deallocate() {
fn f(x: &UnsafeCell<i32>) {
let b: Box<i32> = unsafe { Box::from_raw(x as *const _ as *mut i32) };
drop(b)
}

let b = Box::new(0i32);
f(unsafe { mem::transmute(Box::into_raw(b)) });
}

/// As a side-effect of the above, we also allow this -- at least for now.
fn unsafe_cell_invalidate() {
fn f(_x: &UnsafeCell<i32>, y: *mut i32) {
// Writing to y invalidates x, but that is okay.
unsafe {
*y += 1;
}
}

let mut x = 0i32;
let raw1 = &mut x as *mut _;
let ref1 = unsafe { &mut *raw1 };
let raw2 = ref1 as *mut _;
// Now the borrow stack is: raw1, ref2, raw2.
// So using raw1 invalidates raw2.
f(unsafe { mem::transmute(raw2) }, raw1);
}