use super::super::thread_sched::DeadlineActivity;
use crate::{
runtime::switch::{RuntimeSwitchPlan, ThreadRuntimeBinding},
sched::{CpuId, SchedulePolicy},
thread::{SwitchReason, ThreadCore, ThreadExtensionView, ThreadId},
};
#[derive(Debug)]
pub struct ScheduleDecision {
pub(super) previous: Option<ThreadId>,
pub(super) next: ThreadId,
pub(super) runtime_switch_plan: Option<RuntimeSwitchPlan>,
pub(super) switch_reason: SwitchReason,
pub(super) timestamp_ns: u64,
}
#[derive(Debug)]
pub enum YieldOutcome {
Unchanged,
Switch(ScheduleDecision),
}
impl YieldOutcome {
pub(crate) const fn decision_mut(&mut self) -> Option<&mut ScheduleDecision> {
match self {
Self::Unchanged => None,
Self::Switch(decision) => Some(decision),
}
}
}
#[doc(hidden)]
pub struct SwitchInCompletion {
thread: Option<ThreadId>,
policy: Option<SchedulePolicy>,
extension: Option<ThreadExtensionView>,
charged_runtime_ns: u64,
trace_wake: Option<fn()>,
}
impl SwitchInCompletion {
pub(crate) const NONE: Self = Self {
thread: None,
policy: None,
extension: None,
charged_runtime_ns: 0,
trace_wake: None,
};
pub(crate) fn for_core(
core: &ThreadCore,
policy: SchedulePolicy,
charged_runtime_ns: u64,
) -> Self {
Self {
thread: Some(core.id()),
policy: Some(policy),
extension: core.extension_view(),
charged_runtime_ns,
trace_wake: None,
}
}
pub(crate) fn with_trace_wake(mut self, wake: Option<fn()>) -> Self {
self.trace_wake = wake;
self
}
#[doc(hidden)]
pub fn finish(self) {
if let (Some(thread), Some(policy), Some(extension)) =
(self.thread, self.policy, self.extension)
{
unsafe {
(extension.ops().on_switch_in)(
extension.data(),
thread,
policy,
self.charged_runtime_ns,
)
};
}
if let Some(wake) = self.trace_wake {
wake();
}
}
}
#[derive(Debug)]
pub enum SchedulerOutcome {
Quiescent,
ParkingDeferred,
OwnerWorkPending,
Decision(ScheduleDecision),
}
impl SchedulerOutcome {
pub const fn decision(&self) -> Option<&ScheduleDecision> {
match self {
Self::Decision(decision) => Some(decision),
Self::Quiescent | Self::ParkingDeferred | Self::OwnerWorkPending => None,
}
}
pub(crate) const fn decision_mut(&mut self) -> Option<&mut ScheduleDecision> {
match self {
Self::Decision(decision) => Some(decision),
Self::Quiescent | Self::ParkingDeferred | Self::OwnerWorkPending => None,
}
}
pub const fn parking_deferred(&self) -> bool {
matches!(self, Self::ParkingDeferred)
}
pub const fn owner_work_pending(&self) -> bool {
matches!(self, Self::OwnerWorkPending)
}
}
impl ScheduleDecision {
pub const fn previous(&self) -> Option<ThreadId> {
self.previous
}
pub const fn next(&self) -> ThreadId {
self.next
}
pub const fn switch_reason(&self) -> SwitchReason {
self.switch_reason
}
pub const fn timestamp_ns(&self) -> u64 {
self.timestamp_ns
}
pub fn requires_context_switch(&self) -> bool {
self.previous() != Some(self.next())
}
pub(crate) fn take_runtime_switch_plan(&mut self) -> Option<RuntimeSwitchPlan> {
self.runtime_switch_plan.take()
}
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct SwitchEndpoint {
thread: ThreadId,
binding: ThreadRuntimeBinding,
address_space_identity: crate::runtime::resource::AddressSpaceMembarrierId,
}
impl SwitchEndpoint {
pub(crate) const fn new(
thread: ThreadId,
binding: ThreadRuntimeBinding,
address_space_identity: crate::runtime::resource::AddressSpaceMembarrierId,
) -> Self {
Self {
thread,
binding,
address_space_identity,
}
}
pub(crate) const fn thread(self) -> ThreadId {
self.thread
}
pub(crate) const fn binding(self) -> ThreadRuntimeBinding {
self.binding
}
pub(crate) const fn address_space_identity(
self,
) -> crate::runtime::resource::AddressSpaceMembarrierId {
self.address_space_identity
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ChargeOutcome {
pub(super) slice_expired: bool,
pub(super) deadline_overrun: bool,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DeadlineRuntimeSnapshot {
pub(super) remaining_runtime_ns: u64,
pub(super) overruns: u64,
pub(super) pi_boosted: bool,
pub(super) donor: Option<ThreadId>,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct DeadlineActivitySnapshot {
pub(super) activity: DeadlineActivity,
pub(super) bandwidth_cpu: Option<CpuId>,
pub(super) zero_lag_ns: Option<u64>,
}
impl DeadlineActivitySnapshot {
pub const fn activity(self) -> DeadlineActivity {
self.activity
}
pub const fn bandwidth_cpu(self) -> Option<CpuId> {
self.bandwidth_cpu
}
pub const fn zero_lag_ns(self) -> Option<u64> {
self.zero_lag_ns
}
}
impl DeadlineRuntimeSnapshot {
pub const fn remaining_runtime_ns(self) -> u64 {
self.remaining_runtime_ns
}
pub const fn overruns(self) -> u64 {
self.overruns
}
pub const fn pi_boosted(self) -> bool {
self.pi_boosted
}
pub const fn donor(self) -> Option<ThreadId> {
self.donor
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct OwnerControlDrain {
pub(super) drained: usize,
pub(super) pending: bool,
}
impl OwnerControlDrain {
pub const fn drained(self) -> usize {
self.drained
}
pub const fn pending(self) -> bool {
self.pending
}
}
impl ChargeOutcome {
pub const fn slice_expired(self) -> bool {
self.slice_expired
}
pub const fn deadline_overrun(self) -> bool {
self.deadline_overrun
}
}