use super::*;
impl CpuLocal {
pub(crate) fn current(&self) -> Option<ThreadId> {
self.remote
.lock_run_queue(RunQueueGuardSource::OwnerCurrentThreadObservation)
.current_thread()
}
pub(crate) fn current_core(&self) -> Option<Arc<ThreadCore>> {
self.remote
.lock_run_queue(RunQueueGuardSource::OwnerCurrentCoreObservation)
.current_core()
}
pub(crate) fn runnable_count(&self) -> usize {
self.remote
.lock_run_queue(RunQueueGuardSource::OwnerRunnableObservation)
.nr_running()
}
pub(crate) fn idle_pull_eligible(&self) -> bool {
let run_queue = self
.remote
.lock_run_queue(RunQueueGuardSource::OwnerRunnableObservation);
run_queue.current_thread() == run_queue.idle() && run_queue.nr_running() == 0
}
pub(crate) fn is_quiescent_for_offline(&self) -> bool {
let run_queue = self.remote.lock_run_queue(RunQueueGuardSource::Lifecycle);
let deadlines = self
.remote
.read_deadline_base(DeadlineBaseGuardSource::Lifecycle);
(run_queue.current_thread().is_none() || run_queue.current_thread() == run_queue.idle())
&& run_queue.nr_running() == 0
&& run_queue.deadline_members_are_empty()
&& deadlines.queue.is_empty()
&& deadlines.expired_count == 0
&& !deadlines.has_claimed_task_expiration()
&& !deadlines.softirq_activated
&& self.dispatch.switch_handoff.is_none()
&& self.remote.is_quiescent_for_offline()
}
pub(crate) fn request_reschedule(&self, kind: RescheduleKind) {
self.remote.request_reschedule(kind);
}
pub(crate) fn request_scheduler_work(&self) {
self.remote.request_scheduler_work();
}
pub(crate) fn arm_idle_pull(self: Pin<&mut Self>) {
self.dispatch_state_mut().arm_idle_pull();
}
pub(crate) const fn idle_pull_pending(&self) -> bool {
self.dispatch.idle_pull_pending()
}
pub(crate) fn take_idle_pull_pending(self: Pin<&mut Self>) -> bool {
self.dispatch_state_mut().take_idle_pull_pending()
}
pub(crate) fn defer_scheduler_work(&self) {
self.remote.defer_scheduler_work();
}
pub(crate) fn needs_reschedule(&self) -> bool {
self.remote.needs_reschedule()
}
pub(crate) fn scheduler_request_pending(&self, scope: SchedulerRequestScope) -> bool {
self.remote.scheduler_request_pending(scope)
}
pub(crate) fn promote_lazy_reschedule(&self) -> bool {
self.remote.promote_lazy_reschedule()
}
pub(crate) const fn batch_limit(&self) -> usize {
self.drain.batch_limit()
}
pub(crate) unsafe fn scheduler_current_lifecycle_state(&self) -> Option<ThreadState> {
unsafe { self.remote.lock_run_queue_irq_disabled() }
.current_core_ref()
.map(ThreadCore::state)
}
pub(crate) unsafe fn scheduler_current_address_space(
&self,
thread: ThreadId,
) -> Result<crate::runtime::resource::AddressSpaceHandle, TaskError> {
let run_queue = unsafe { self.remote.lock_run_queue_irq_disabled() };
let current = run_queue.current().ok_or(TaskError::NoRunnableThread)?;
if current.thread() != thread {
return Err(TaskError::InvalidRuntimeHandle);
}
Ok(current.address_space())
}
pub(crate) unsafe fn install_idle_bootstrap(
self: Pin<&mut Self>,
system: &TaskSystem,
idle: ThreadId,
core: Arc<ThreadCore>,
active: ActiveSchedulingState,
metadata: RqTaskMetadata,
rt_quota_exempt: bool,
) {
debug_assert_eq!(idle, core.id());
let fields = unsafe { self.get_unchecked_mut() };
let mut transaction = unsafe { OwnerRqTxn::begin_bootstrap(system, &fields.remote) };
transaction.install_idle(Arc::clone(&core), active, metadata, rt_quota_exempt);
core.sched().placement().install_idle(fields.owner);
transaction.commit_bootstrap();
fields.remote.publish_idle_thread(idle);
}
pub(crate) fn install_switch_handoff(
self: Pin<&mut Self>,
prepared: SwitchHandoff,
) -> Result<(), TaskError> {
let handoff = &mut self.dispatch_state_mut().switch_handoff;
if handoff.is_some() {
return Err(TaskError::InvalidConfiguration);
}
*handoff = Some(prepared);
Ok(())
}
pub(crate) fn take_switch_handoff(self: Pin<&mut Self>) -> Option<SwitchHandoff> {
self.dispatch_state_mut().switch_handoff.take()
}
pub(crate) fn switch_handoff_mut(self: Pin<&mut Self>) -> Option<&mut SwitchHandoff> {
self.dispatch_state_mut().switch_handoff.as_mut()
}
pub(crate) fn clear_switch_handoff(self: Pin<&mut Self>) -> Result<(), TaskError> {
let handoff = &mut self.dispatch_state_mut().switch_handoff;
if handoff.is_none() {
return Err(TaskError::InvalidConfiguration);
}
*handoff = None;
Ok(())
}
pub(crate) fn switch_handoff(&self) -> Option<&SwitchHandoff> {
self.dispatch.switch_handoff.as_ref()
}
pub(crate) fn defer_park_preemption(&self, request: SchedulerRequestClaim) {
self.remote.defer_park_preemption(request);
}
pub(crate) fn finish_park_preemption(&self, resume_running: bool) {
self.remote.finish_park_preemption(resume_running);
}
pub(crate) fn restore_claimed_park_preemption(&self, request: SchedulerRequestClaim) {
self.remote.restore_claimed_park_preemption(request);
}
pub(crate) fn dispatch_state_mut(
self: Pin<&mut Self>,
) -> &mut dispatch_state::OwnerDispatchState {
&mut unsafe { self.get_unchecked_mut() }.dispatch
}
pub(crate) fn lock_run_queue(
&self,
source: RunQueueGuardSource,
) -> IrqTicketGuard<'_, CpuRunQueueState> {
self.remote.lock_run_queue(source)
}
pub(crate) fn drain_state_mut(self: Pin<&mut Self>) -> &mut drain_state::OwnerDrainScratch {
&mut unsafe { self.get_unchecked_mut() }.drain
}
pub(crate) const fn drain_state(&self) -> &drain_state::OwnerDrainScratch {
&self.drain
}
pub(crate) fn balance_request_node(&self) -> Pin<&'static InboxNode> {
self.remote.balance_request_node()
}
pub(crate) const fn idle_pull_visited(&self) -> &CpuSet {
self.dispatch.idle_pull_visited()
}
pub(crate) fn mark_idle_pull_source(self: Pin<&mut Self>, source: CpuId) {
self.dispatch_state_mut().mark_idle_pull_source(source);
}
pub(crate) fn reset_idle_pull_scan(self: Pin<&mut Self>) {
self.dispatch_state_mut().reset_idle_pull_scan();
}
}