2 use rustc_middle::ty::layout::LayoutOf;
3 use rustc_target::spec::abi::Abi;
5 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
6 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
9 thread: &OpTy<'tcx, Provenance>,
10 _attr: &OpTy<'tcx, Provenance>,
11 start_routine: &OpTy<'tcx, Provenance>,
12 arg: &OpTy<'tcx, Provenance>,
13 ) -> InterpResult<'tcx, i32> {
14 let this = self.eval_context_mut();
16 let thread_info_place = this.deref_operand(thread)?;
18 let start_routine = this.read_pointer(start_routine)?;
20 let func_arg = this.read_immediate(arg)?;
22 this.start_regular_thread(
23 Some(thread_info_place),
25 Abi::C { unwind: false },
27 this.layout_of(this.tcx.types.usize)?,
35 thread: &OpTy<'tcx, Provenance>,
36 retval: &OpTy<'tcx, Provenance>,
37 ) -> InterpResult<'tcx, i32> {
38 let this = self.eval_context_mut();
40 if !this.ptr_is_null(this.read_pointer(retval)?)? {
41 // FIXME: implement reading the thread function's return place.
42 throw_unsup_format!("Miri supports pthread_join only with retval==NULL");
45 let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
46 this.join_thread_exclusive(thread_id.try_into().expect("thread ID should fit in u32"))?;
51 fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
52 let this = self.eval_context_mut();
54 let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
56 thread_id.try_into().expect("thread ID should fit in u32"),
57 /*allow_terminated_joined*/ false,
63 fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
64 let this = self.eval_context_mut();
66 let thread_id = this.get_active_thread();
67 Ok(Scalar::from_machine_usize(thread_id.into(), this))
70 /// Set the name of the current thread. `max_name_len` is the maximal length of the name
71 /// including the null terminator.
72 fn pthread_setname_np(
74 thread: Scalar<Provenance>,
75 name: Scalar<Provenance>,
77 ) -> InterpResult<'tcx, Scalar<Provenance>> {
78 let this = self.eval_context_mut();
80 let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap();
81 let name = name.to_pointer(this)?;
83 let name = this.read_c_str(name)?.to_owned();
85 // Comparing with `>=` to account for null terminator.
86 if name.len() >= max_name_len {
87 return this.eval_libc("ERANGE");
90 this.set_thread_name(thread, name);
92 Ok(Scalar::from_u32(0))
95 fn pthread_getname_np(
97 thread: Scalar<Provenance>,
98 name_out: Scalar<Provenance>,
99 len: Scalar<Provenance>,
100 ) -> InterpResult<'tcx, Scalar<Provenance>> {
101 let this = self.eval_context_mut();
103 let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap();
104 let name_out = name_out.to_pointer(this)?;
105 let len = len.to_machine_usize(this)?;
107 let name = this.get_thread_name(thread).to_owned();
108 let (success, _written) = this.write_c_str(&name, name_out, len)?;
110 if success { Ok(Scalar::from_u32(0)) } else { this.eval_libc("ERANGE") }
113 fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
114 let this = self.eval_context_mut();
116 this.yield_active_thread();