Struct miri::ThreadManager

source ·
pub struct ThreadManager<'mir, 'tcx> {
    active_thread: ThreadId,
    threads: IndexVec<ThreadId, Thread<'mir, 'tcx>>,
    pub(crate) sync: SynchronizationState<'mir, 'tcx>,
    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<'mir, 'tcx>

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§

source§

impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx>

source

pub(crate) fn init( ecx: &mut MiriInterpCx<'mir, 'tcx>, on_main_stack_empty: StackEmptyCallback<'mir, 'tcx> )

source

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.

source

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.

source

pub fn active_thread_stack( &self ) -> &[Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>]

Borrow the stack of the active thread.

source

fn active_thread_stack_mut( &mut self ) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>>

Mutably borrow the stack of the active thread.

source

pub fn all_stacks( &self ) -> impl Iterator<Item = &[Frame<'mir, 'tcx, Provenance, FrameExtra<'tcx>>]>

source

fn create_thread( &mut self, on_stack_empty: StackEmptyCallback<'mir, 'tcx> ) -> ThreadId

Create a new thread and returns its id.

source

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.

source

pub fn get_active_thread_id(&self) -> ThreadId

Get the id of the currently active thread.

source

pub fn get_total_thread_count(&self) -> usize

Get the total number of threads that were ever spawn by this program.

source

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.)

source

fn has_terminated(&self, thread_id: ThreadId) -> bool

Has the given thread terminated?

source

fn have_all_terminated(&self) -> bool

Have all threads terminated?

source

fn enable_thread(&mut self, thread_id: ThreadId)

Enable the thread for execution. The thread must be terminated.

source

pub fn active_thread_mut(&mut self) -> &mut Thread<'mir, 'tcx>

Get a mutable borrow of the currently active thread.

source

pub fn active_thread_ref(&self) -> &Thread<'mir, 'tcx>

Get a shared borrow of the currently active thread.

source

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.

source

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.

source

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

source

pub fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec<u8>)

Set the name of the given thread.

source

pub fn get_thread_name(&self, thread: ThreadId) -> Option<&[u8]>

Get the name of the given thread.

source

pub fn get_thread_display_name(&self, thread: ThreadId) -> String

source

fn block_thread(&mut self, thread: ThreadId)

Put the thread into the blocked state.

source

fn unblock_thread(&mut self, thread: ThreadId)

Put the blocked thread into the enabled state.

source

fn yield_active_thread(&mut self)

Change the active thread to some enabled thread.

source

fn register_timeout_callback( &mut self, thread: ThreadId, call_time: Time, callback: Box<dyn MachineCallback<'mir, '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.

source

fn unregister_timeout_callback_if_exists(&mut self, thread: ThreadId)

Unregister the callback for the thread.

source

fn get_ready_callback( &mut self, clock: &Clock ) -> Option<(ThreadId, Box<dyn MachineCallback<'mir, 'tcx> + 'tcx>)>

Get a callback that is ready to be called.

source

fn thread_terminated( &mut self, data_race: Option<&mut GlobalState>, current_span: Span ) -> 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.

source

fn schedule(&mut self, clock: &Clock) -> 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§

source§

impl<'mir, 'tcx> Debug for ThreadManager<'mir, 'tcx>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl VisitProvenance for ThreadManager<'_, '_>

source§

fn visit_provenance(&self, visit: &mut VisitWith<'_>)

Auto Trait Implementations§

§

impl<'mir, 'tcx> !DynSend for ThreadManager<'mir, 'tcx>

§

impl<'mir, 'tcx> !DynSync for ThreadManager<'mir, 'tcx>

§

impl<'mir, 'tcx> !Freeze for ThreadManager<'mir, 'tcx>

§

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>

§

impl<'mir, 'tcx> !UnwindSafe for ThreadManager<'mir, 'tcx>

Blanket Implementations§

source§

impl<T> Aligned for T

source§

const ALIGN: Alignment = _

Alignment of Self.
source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, R> CollectAndApply<T, R> for T

source§

fn collect_and_apply<I, F>(iter: I, f: F) -> R
where I: Iterator<Item = T>, F: FnOnce(&[T]) -> R,

Equivalent to f(&iter.collect::<Vec<_>>()).

§

type Output = R

§

impl<T> Filterable for T

§

fn filterable( self, filter_name: &'static str ) -> RequestFilterDataProvider<T, fn(_: DataRequest<'_>) -> bool>

Creates a filterable data provider with the given name for debugging. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<P> IntoQueryParam<P> for P

source§

impl<T> MaybeResult<T> for T

§

type Error = !

source§

fn from(_: Result<T, <T as MaybeResult<T>>::Error>) -> T

source§

fn to_result(self) -> Result<T, <T as MaybeResult<T>>::Error>

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<'tcx, T> ToPredicate<'tcx, T> for T

source§

fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

source§

impl<Tcx, T> Value<Tcx> for T
where Tcx: DepContext,

source§

default fn from_cycle_error( tcx: Tcx, cycle_error: &CycleError, _guar: ErrorGuaranteed ) -> T

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<'a, T> Captures<'a> for T
where T: ?Sized,

source§

impl<'a, T> Captures<'a> for T
where T: ?Sized,

§

impl<T> ErasedDestructor for T
where T: 'static,

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: 232 bytes