Move pthread_create and related shims to a separate file.
This commit is contained in:
parent
aef4c95599
commit
1f33f04fd4
@ -42,6 +42,7 @@ pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
|
||||
pub use crate::shims::os_str::EvalContextExt as OsStrEvalContextExt;
|
||||
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as PanicEvalContextExt};
|
||||
pub use crate::shims::sync::{EvalContextExt as SyncEvalContextExt};
|
||||
pub use crate::shims::threads::EvalContextExt as ThreadShimsEvalContextExt;
|
||||
pub use crate::shims::time::EvalContextExt as TimeEvalContextExt;
|
||||
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
|
||||
pub use crate::shims::EvalContextExt as ShimsEvalContextExt;
|
||||
|
@ -6,7 +6,6 @@ use std::convert::TryFrom;
|
||||
use log::trace;
|
||||
|
||||
use crate::*;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir;
|
||||
use rustc_target::abi::{Align, LayoutOf, Size};
|
||||
|
||||
@ -316,66 +315,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
|
||||
// Threading
|
||||
"pthread_create" => {
|
||||
println!("WARNING: The thread support is experimental. \
|
||||
For example, Miri does not detect data races yet.");
|
||||
assert_eq!(args.len(), 4);
|
||||
let func = args[2];
|
||||
let fn_ptr = this.read_scalar(func)?.not_undef()?;
|
||||
let fn_val = this.memory.get_fn(fn_ptr)?;
|
||||
let instance = match fn_val {
|
||||
rustc_mir::interpret::FnVal::Instance(instance) => instance,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let thread_info_place = this.deref_operand(args[0])?;
|
||||
let thread_info_type = args[0].layout.ty
|
||||
.builtin_deref(true)
|
||||
.ok_or_else(|| err_ub_format!(
|
||||
"wrong signature used for `pthread_create`: first argument must be a raw pointer."
|
||||
))?
|
||||
.ty;
|
||||
let thread_info_layout = this.layout_of(thread_info_type)?;
|
||||
let func_arg = match *args[3] {
|
||||
rustc_mir::interpret::Operand::Immediate(immediate) => immediate,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let func_args = [func_arg];
|
||||
let ret_place =
|
||||
this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into());
|
||||
let new_thread_id = this.create_thread()?;
|
||||
let old_thread_id = this.set_active_thread(new_thread_id)?;
|
||||
this.call_function(
|
||||
instance,
|
||||
&func_args[..],
|
||||
Some(ret_place.into()),
|
||||
StackPopCleanup::None { cleanup: true },
|
||||
)?;
|
||||
this.set_active_thread(old_thread_id)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_uint(new_thread_id.index() as u128, thread_info_layout.size),
|
||||
thread_info_place.into(),
|
||||
)?;
|
||||
|
||||
// Return success (`0`).
|
||||
this.write_null(dest)?;
|
||||
let result = this.pthread_create(args[0], args[1], args[2], args[3])?;
|
||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
||||
}
|
||||
"pthread_join" => {
|
||||
assert_eq!(args.len(), 2);
|
||||
assert!(
|
||||
this.is_null(this.read_scalar(args[1])?.not_undef()?)?,
|
||||
"Miri supports pthread_join only with retval==NULL"
|
||||
);
|
||||
let thread = this.read_scalar(args[0])?.not_undef()?.to_machine_usize(this)?;
|
||||
this.join_thread(thread.into())?;
|
||||
|
||||
// Return success (`0`).
|
||||
this.write_null(dest)?;
|
||||
let result = this.pthread_join(args[0], args[1])?;
|
||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
||||
}
|
||||
"pthread_detach" => {
|
||||
let thread = this.read_scalar(args[0])?.not_undef()?.to_machine_usize(this)?;
|
||||
this.detach_thread(thread.into())?;
|
||||
|
||||
// Return success (`0`).
|
||||
this.write_null(dest)?;
|
||||
assert_eq!(args.len(), 1);
|
||||
let result = this.pthread_detach(args[0])?;
|
||||
this.write_scalar(Scalar::from_i32(result), dest)?;
|
||||
}
|
||||
|
||||
"pthread_attr_getguardsize" => {
|
||||
|
@ -6,6 +6,7 @@ pub mod intrinsics;
|
||||
pub mod os_str;
|
||||
pub mod panic;
|
||||
pub mod sync;
|
||||
pub mod threads;
|
||||
pub mod time;
|
||||
pub mod tls;
|
||||
|
||||
|
84
src/shims/threads.rs
Normal file
84
src/shims/threads.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use crate::*;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn pthread_create(
|
||||
&mut self,
|
||||
thread: OpTy<'tcx, Tag>,
|
||||
_attr: OpTy<'tcx, Tag>,
|
||||
start_routine: OpTy<'tcx, Tag>,
|
||||
arg: OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
println!(
|
||||
"WARNING: The thread support is experimental. \
|
||||
For example, Miri does not detect data races yet."
|
||||
);
|
||||
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let new_thread_id = this.create_thread()?;
|
||||
let old_thread_id = this.set_active_thread(new_thread_id)?;
|
||||
|
||||
let thread_info_place = this.deref_operand(thread)?;
|
||||
let thread_info_type = thread.layout.ty
|
||||
.builtin_deref(true)
|
||||
.ok_or_else(|| err_ub_format!(
|
||||
"wrong signature used for `pthread_create`: first argument must be a raw pointer."
|
||||
))?
|
||||
.ty;
|
||||
let thread_info_layout = this.layout_of(thread_info_type)?;
|
||||
this.write_scalar(
|
||||
Scalar::from_uint(new_thread_id.index() as u128, thread_info_layout.size),
|
||||
thread_info_place.into(),
|
||||
)?;
|
||||
|
||||
let fn_ptr = this.read_scalar(start_routine)?.not_undef()?;
|
||||
let instance = this.memory.get_fn(fn_ptr)?.as_instance()?;
|
||||
|
||||
let func_arg = match *arg {
|
||||
rustc_mir::interpret::Operand::Immediate(immediate) => immediate,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let func_args = [func_arg];
|
||||
|
||||
let ret_place =
|
||||
this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into());
|
||||
|
||||
this.call_function(
|
||||
instance,
|
||||
&func_args[..],
|
||||
Some(ret_place.into()),
|
||||
StackPopCleanup::None { cleanup: true },
|
||||
)?;
|
||||
|
||||
this.set_active_thread(old_thread_id)?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
fn pthread_join(
|
||||
&mut self,
|
||||
thread: OpTy<'tcx, Tag>,
|
||||
retval: OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
if !this.is_null(this.read_scalar(retval)?.not_undef()?)? {
|
||||
throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
|
||||
}
|
||||
|
||||
let thread_id = this.read_scalar(thread)?.not_undef()?.to_machine_usize(this)?;
|
||||
this.join_thread(thread_id.into())?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
fn pthread_detach(&mut self, thread: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let thread_id = this.read_scalar(thread)?.not_undef()?.to_machine_usize(this)?;
|
||||
this.detach_thread(thread_id.into())?;
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
@ -91,9 +91,6 @@ pub struct ThreadSet<'mir, 'tcx> {
|
||||
///
|
||||
/// Note that this vector also contains terminated threads.
|
||||
threads: IndexVec<ThreadId, Thread<'mir, 'tcx>>,
|
||||
|
||||
/// List of threads that just terminated. TODO: Cleanup.
|
||||
terminated_threads: Vec<ThreadId>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> Default for ThreadSet<'mir, 'tcx> {
|
||||
@ -103,7 +100,6 @@ impl<'mir, 'tcx> Default for ThreadSet<'mir, 'tcx> {
|
||||
Self {
|
||||
active_thread: ThreadId::new(0),
|
||||
threads: threads,
|
||||
terminated_threads: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user