use alloc::sync::Arc;
use core::marker::PhantomData;
use crate::{
runtime::{context::runtime_task_system, lock::PreemptScope, task_runtime},
sched::CpuId,
thread::{TaskError, ThreadCore, current::current_thread_core_arc},
};
#[must_use]
pub struct MigrationGuard {
current: Arc<ThreadCore>,
cpu: CpuId,
_not_send: PhantomData<*mut ()>,
}
impl MigrationGuard {
pub fn new() -> Result<Self, TaskError> {
if task_runtime::in_hard_irq() {
return Err(TaskError::UnsafeContext);
}
let _preempt = PreemptScope::enter();
let current = current_thread_core_arc()?;
let cpu = runtime_task_system()?.disable_current_migration(¤t)?;
Ok(Self {
current,
cpu,
_not_send: PhantomData,
})
}
pub const fn cpu(&self) -> CpuId {
self.cpu
}
}
impl Drop for MigrationGuard {
fn drop(&mut self) {
let _preempt = PreemptScope::enter();
runtime_task_system()
.and_then(|system| system.enable_current_migration(&self.current, self.cpu))
.expect("migration guard must release on its owning task and CPU");
}
}