Skip to content

Commit 1e87c9f

Browse files
committed
Auto merge of #1390 - RalfJung:conc, r=RalfJung
Make spin_loop yield, and a panicking thread test @vakaras agreed it would make sense to make `spin_loop` yield, so this implements that. Also add a test for a panic being raised in one thread, caught by the panic machinery, and then expose through the join handle. Miraculously, that just works. :)
2 parents 9ec5264 + 6b18f6e commit 1e87c9f

File tree

9 files changed

+62
-14
lines changed

9 files changed

+62
-14
lines changed

src/shims/foreign_items.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
434434
}
435435

436436
// Architecture-specific shims
437-
"llvm.x86.sse2.pause" if this.tcx.sess.target.target.arch == "x86" || this.tcx.sess.target.target.arch == "x86_64" => {}
437+
"llvm.x86.sse2.pause" if this.tcx.sess.target.target.arch == "x86" || this.tcx.sess.target.target.arch == "x86_64" => {
438+
this.sched_yield()?;
439+
}
438440

439441
// Platform-specific shims
440442
_ => match this.tcx.sess.target.target.target_os.as_str() {

src/shims/foreign_items/posix/macos.rs

+6
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9898
this.write_scalar(stack_size, dest)?;
9999
}
100100

101+
// Threading
102+
"pthread_setname_np" => {
103+
let ptr = this.read_scalar(args[0])?.not_undef()?;
104+
this.pthread_setname_np(ptr)?;
105+
}
106+
101107
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
102108
// These shims are enabled only when the caller is in the standard library.
103109
"mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {

src/shims/thread.rs

+14
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9595
_arg5: OpTy<'tcx, Tag>,
9696
) -> InterpResult<'tcx, i32> {
9797
let this = self.eval_context_mut();
98+
this.assert_target_os("linux", "prctl");
9899

99100
let option = this.read_scalar(option)?.to_i32()?;
100101
if option == this.eval_libc_i32("PR_SET_NAME")? {
@@ -118,6 +119,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
118119
Ok(0)
119120
}
120121

122+
fn pthread_setname_np(
123+
&mut self,
124+
ptr: Scalar<Tag>,
125+
) -> InterpResult<'tcx> {
126+
let this = self.eval_context_mut();
127+
this.assert_target_os("macos", "pthread_setname_np");
128+
129+
let name = this.memory.read_c_str(ptr)?.to_owned();
130+
this.set_active_thread_name(name)?;
131+
132+
Ok(())
133+
}
134+
121135
fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
122136
let this = self.eval_context_mut();
123137

src/thread.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -134,16 +134,20 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
134134
}
135135
false
136136
}
137+
138+
/// Get the name of the current thread, or `<unnamed>` if it was not set.
139+
fn thread_name(&self) -> &[u8] {
140+
if let Some(ref thread_name) = self.thread_name {
141+
thread_name
142+
} else {
143+
b"<unnamed>"
144+
}
145+
}
137146
}
138147

139148
impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
140149
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141-
if let Some(ref name) = self.thread_name {
142-
write!(f, "{}", String::from_utf8_lossy(name))?;
143-
} else {
144-
write!(f, "<unnamed>")?;
145-
}
146-
write!(f, "({:?}, {:?})", self.state, self.join_status)
150+
write!(f, "{}({:?}, {:?})", String::from_utf8_lossy(self.thread_name()), self.state, self.join_status)
147151
}
148152
}
149153

@@ -314,11 +318,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
314318

315319
/// Get the name of the active thread.
316320
fn get_thread_name(&self) -> &[u8] {
317-
if let Some(ref thread_name) = self.active_thread_ref().thread_name {
318-
thread_name
319-
} else {
320-
b"<unnamed>"
321-
}
321+
self.active_thread_ref().thread_name()
322322
}
323323

324324
/// Allocate a new blockset id.

tests/run-pass/concurrency/simple.rs

+21
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,25 @@ fn create_move_out() {
4949
assert_eq!(result.len(), 6);
5050
}
5151

52+
fn panic() {
53+
let result = thread::spawn(|| {
54+
panic!("Hello!")
55+
})
56+
.join()
57+
.unwrap_err();
58+
let msg = result.downcast_ref::<&'static str>().unwrap();
59+
assert_eq!(*msg, "Hello!");
60+
}
61+
62+
fn panic_named() {
63+
thread::Builder::new().name("childthread".to_string()).spawn(move || {
64+
panic!("Hello, world!");
65+
})
66+
.unwrap()
67+
.join()
68+
.unwrap_err();
69+
}
70+
5271
fn main() {
5372
create_and_detach();
5473
create_and_join();
@@ -58,4 +77,6 @@ fn main() {
5877
create_nested_and_join();
5978
create_move_in();
6079
create_move_out();
80+
panic();
81+
panic_named();
6182
}
+2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
warning: thread support is experimental. For example, Miri does not detect data races yet.
22

3+
thread '<unnamed>' panicked at 'Hello!', $DIR/simple.rs:54:9
4+
thread 'childthread' panicked at 'Hello, world!', $DIR/simple.rs:64:9

tests/run-pass/sync.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
#![feature(rustc_private)]
1+
#![feature(rustc_private, renamed_spin_loop)]
22

33
use std::sync::{Mutex, TryLockError};
44
use std::sync::atomic;
5+
use std::hint;
56

67
fn main() {
78
test_mutex_stdlib();
@@ -56,6 +57,7 @@ impl<T> TryLockErrorExt<T> for TryLockError<T> {
5657

5758
fn test_spin_loop_hint() {
5859
atomic::spin_loop_hint();
60+
hint::spin_loop();
5961
}
6062

6163
fn test_thread_yield_now() {

tests/run-pass/transmute_fat2.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ fn main() {
88
let bad = unsafe {
99
std::mem::transmute::<u64, &[u8]>(42)
1010
};
11+
// This created a slice with length 0, so the following will fail the bounds check.
1112
bad[0];
1213
}

tests/run-pass/transmute_fat2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', $DIR/transmute_fat2.rs:11:5
1+
thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', $DIR/transmute_fat2.rs:12:5

0 commit comments

Comments
 (0)