From: Vytautas Astrauskas Date: Mon, 6 Apr 2020 20:44:47 +0000 (-0700) Subject: Move pthread_create and related shims to a separate file. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=1f33f04fd453a63a88cb25771466c2618b46d372;p=rust.git Move pthread_create and related shims to a separate file. --- diff --git a/src/lib.rs b/src/lib.rs index c042526be64..d8b3397c8e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,6 +42,7 @@ 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; diff --git a/src/shims/foreign_items/posix.rs b/src/shims/foreign_items/posix.rs index 878ab8896dd..7d2cb16afee 100644 --- a/src/shims/foreign_items/posix.rs +++ b/src/shims/foreign_items/posix.rs @@ -6,7 +6,6 @@ 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 @@ fn emulate_foreign_item_by_name( // 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" => { diff --git a/src/shims/mod.rs b/src/shims/mod.rs index 71ff6024ec6..118058dd32e 100644 --- a/src/shims/mod.rs +++ b/src/shims/mod.rs @@ -6,6 +6,7 @@ pub mod os_str; pub mod panic; pub mod sync; +pub mod threads; pub mod time; pub mod tls; diff --git a/src/shims/threads.rs b/src/shims/threads.rs new file mode 100644 index 00000000000..6e1087dd81d --- /dev/null +++ b/src/shims/threads.rs @@ -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) + } +} diff --git a/src/threads.rs b/src/threads.rs index 618713e3c3d..9d982359bfb 100644 --- a/src/threads.rs +++ b/src/threads.rs @@ -91,9 +91,6 @@ pub struct ThreadSet<'mir, 'tcx> { /// /// Note that this vector also contains terminated threads. threads: IndexVec>, - - /// List of threads that just terminated. TODO: Cleanup. - terminated_threads: Vec, } impl<'mir, 'tcx> Default for ThreadSet<'mir, 'tcx> { @@ -103,7 +100,6 @@ fn default() -> Self { Self { active_thread: ThreadId::new(0), threads: threads, - terminated_threads: Default::default(), } } }