Struct miri::ThreadManager
source · [−]pub struct ThreadManager<'mir, 'tcx> {
active_thread: ThreadId,
threads: IndexVec<ThreadId, Thread<'mir, 'tcx>>,
pub(crate) sync: SynchronizationState,
thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), Pointer<Provenance>>>,
yield_active_thread: bool,
timeout_callbacks: FxHashMap<ThreadId, TimeoutCallbackInfo<'mir, 'tcx>>,
}
Expand description
A set of threads.
Fields
active_thread: ThreadId
Identifier of the currently active thread.
threads: IndexVec<ThreadId, Thread<'mir, 'tcx>>
Threads used in the program.
Note that this vector also contains terminated threads.
sync: SynchronizationState
This field is pub(crate) because the synchronization primitives
(crate::sync
) need a way to access it.
thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), Pointer<Provenance>>>
A mapping from a thread-local static to an allocation id of a thread specific allocation.
yield_active_thread: bool
A flag that indicates that we should change the active thread.
timeout_callbacks: FxHashMap<ThreadId, TimeoutCallbackInfo<'mir, 'tcx>>
Callbacks that are called once the specified time passes.
Implementations
sourceimpl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx>
impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx>
pub(crate) fn init(ecx: &mut MiriEvalContext<'mir, 'tcx>)
sourcefn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Provenance>>
fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Provenance>>
Check if we have an allocation for the given thread local static for the active thread.
sourcefn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Provenance>)
fn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Provenance>)
Set the pointer for the allocation of the given thread local static for the active thread.
Panics if a thread local is initialized twice for the same thread.
sourcepub fn active_thread_stack(
&self
) -> &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>]
pub fn active_thread_stack(
&self
) -> &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>]
Borrow the stack of the active thread.
sourcefn active_thread_stack_mut(
&mut self
) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>
fn active_thread_stack_mut(
&mut self
) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>
Mutably borrow the stack of the active thread.
pub fn all_stacks(
&self
) -> impl Iterator<Item = &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>]>
sourcefn create_thread(&mut self) -> ThreadId
fn create_thread(&mut self) -> ThreadId
Create a new thread and returns its id.
sourcefn set_active_thread_id(&mut self, id: ThreadId) -> ThreadId
fn set_active_thread_id(&mut self, id: ThreadId) -> ThreadId
Set an active thread and return the id of the thread that was active before.
sourcepub fn get_active_thread_id(&self) -> ThreadId
pub fn get_active_thread_id(&self) -> ThreadId
Get the id of the currently active thread.
sourcepub fn get_total_thread_count(&self) -> usize
pub fn get_total_thread_count(&self) -> usize
Get the total number of threads that were ever spawn by this program.
sourcepub fn get_live_thread_count(&self) -> usize
pub fn get_live_thread_count(&self) -> usize
Get the total of threads that are currently live, i.e., not yet terminated. (They might be blocked.)
sourcefn has_terminated(&self, thread_id: ThreadId) -> bool
fn has_terminated(&self, thread_id: ThreadId) -> bool
Has the given thread terminated?
sourcefn have_all_terminated(&self) -> bool
fn have_all_terminated(&self) -> bool
Have all threads terminated?
sourcefn enable_thread(&mut self, thread_id: ThreadId)
fn enable_thread(&mut self, thread_id: ThreadId)
Enable the thread for execution. The thread must be terminated.
sourcefn active_thread_mut(&mut self) -> &mut Thread<'mir, 'tcx>
fn active_thread_mut(&mut self) -> &mut Thread<'mir, 'tcx>
Get a mutable borrow of the currently active thread.
sourcefn active_thread_ref(&self) -> &Thread<'mir, 'tcx>
fn active_thread_ref(&self) -> &Thread<'mir, 'tcx>
Get a shared borrow of the currently active thread.
sourcefn detach_thread(
&mut self,
id: ThreadId,
allow_terminated_joined: bool
) -> InterpResult<'tcx>
fn detach_thread(
&mut self,
id: ThreadId,
allow_terminated_joined: bool
) -> InterpResult<'tcx>
Mark the thread as detached, which means that no other thread will try to join it and the thread is responsible for cleaning up.
allow_terminated_joined
allows detaching joined threads that have already terminated.
This matches Windows’s behavior for CloseHandle
.
See https://docs.microsoft.com/en-us/windows/win32/procthread/thread-handles-and-identifiers:
The handle is valid until closed, even after the thread it represents has been terminated.
sourcefn join_thread(
&mut self,
joined_thread_id: ThreadId,
data_race: Option<&mut GlobalState>
) -> InterpResult<'tcx>
fn join_thread(
&mut self,
joined_thread_id: ThreadId,
data_race: Option<&mut GlobalState>
) -> InterpResult<'tcx>
Mark that the active thread tries to join the thread with joined_thread_id
.
sourcefn join_thread_exclusive(
&mut self,
joined_thread_id: ThreadId,
data_race: Option<&mut GlobalState>
) -> InterpResult<'tcx>
fn join_thread_exclusive(
&mut self,
joined_thread_id: ThreadId,
data_race: Option<&mut GlobalState>
) -> InterpResult<'tcx>
Mark that the active thread tries to exclusively join the thread with joined_thread_id
.
If the thread is already joined by another thread, it will throw UB
sourcepub fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec<u8>)
pub fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec<u8>)
Set the name of the given thread.
sourcepub fn get_thread_name(&self, thread: ThreadId) -> &[u8]ⓘNotable traits for &[u8]impl Read for &[u8]impl Write for &mut [u8]
pub fn get_thread_name(&self, thread: ThreadId) -> &[u8]ⓘNotable traits for &[u8]impl Read for &[u8]impl Write for &mut [u8]
Get the name of the given thread.
sourcefn block_thread(&mut self, thread: ThreadId)
fn block_thread(&mut self, thread: ThreadId)
Put the thread into the blocked state.
sourcefn unblock_thread(&mut self, thread: ThreadId)
fn unblock_thread(&mut self, thread: ThreadId)
Put the blocked thread into the enabled state.
sourcefn yield_active_thread(&mut self)
fn yield_active_thread(&mut self)
Change the active thread to some enabled thread.
sourcefn register_timeout_callback(
&mut self,
thread: ThreadId,
call_time: Time,
callback: Box<dyn FnOnce(&mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx>
)
fn register_timeout_callback(
&mut self,
thread: ThreadId,
call_time: Time,
callback: Box<dyn FnOnce(&mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx>
)
Register the given callback
to be called once the call_time
passes.
The callback will be called with thread
being the active thread, and
the callback may not change the active thread.
sourcefn unregister_timeout_callback_if_exists(&mut self, thread: ThreadId)
fn unregister_timeout_callback_if_exists(&mut self, thread: ThreadId)
Unregister the callback for the thread
.
sourcefn get_ready_callback(
&mut self
) -> Option<(ThreadId, Box<dyn FnOnce(&mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx>)>
fn get_ready_callback(
&mut self
) -> Option<(ThreadId, Box<dyn FnOnce(&mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx>)>
Get a callback that is ready to be called.
sourcefn thread_terminated(
&mut self,
data_race: Option<&mut GlobalState>
) -> Vec<Pointer<Provenance>>
fn thread_terminated(
&mut self,
data_race: Option<&mut GlobalState>
) -> Vec<Pointer<Provenance>>
Wakes up threads joining on the active one and deallocates thread-local statics.
The AllocId
that can now be freed are returned.
sourcefn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction>
fn schedule(&mut self) -> InterpResult<'tcx, SchedulingAction>
Decide which action to take next and on which thread.
The currently implemented scheduling policy is the one that is commonly used in stateless model checkers such as Loom: run the active thread as long as we can and switch only when we have to (the active thread was blocked, terminated, or has explicitly asked to be preempted).
Trait Implementations
sourceimpl<'mir, 'tcx> Debug for ThreadManager<'mir, 'tcx>
impl<'mir, 'tcx> Debug for ThreadManager<'mir, 'tcx>
Auto Trait Implementations
impl<'mir, 'tcx> !RefUnwindSafe for ThreadManager<'mir, 'tcx>
impl<'mir, 'tcx> !Send for ThreadManager<'mir, 'tcx>
impl<'mir, 'tcx> !Sync for ThreadManager<'mir, 'tcx>
impl<'mir, 'tcx> Unpin for ThreadManager<'mir, 'tcx>where
'tcx: 'mir,
impl<'mir, 'tcx> !UnwindSafe for ThreadManager<'mir, 'tcx>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
const: unstable · sourcefn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<V, T> VZip<V> for Twhere
V: MultiLane<T>,
impl<V, T> VZip<V> for Twhere
V: MultiLane<T>,
fn vzip(self) -> V
Layout
Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...)
attributes. Please see the Rust Reference’s “Type Layout” chapter for details on type layout guarantees.
Size: 208 bytes