use crate::{
runtime::context::{
RuntimeIrqGuard, runtime_current_cpu_mut, runtime_task_system, validate_task_context,
},
thread::{TaskError, current::current_thread_id},
};
pub use crate::{
runtime::service::reclaim::notify_address_space_reclaim, thread::spec::ThreadResources,
};
#[doc(hidden)]
pub fn current_address_space_handle()
-> Result<crate::runtime::resource::AddressSpaceHandle, TaskError> {
let current = current_thread_id()?;
let mut irq = RuntimeIrqGuard::enter();
let cpu = runtime_current_cpu_mut(&mut irq)?;
unsafe { cpu.scheduler_current_address_space(current) }
}
pub fn replace_current_address_space(
address_space: &mut crate::runtime::resource::AddressSpaceToken,
) -> Result<crate::runtime::resource::AddressSpaceToken, TaskError> {
validate_task_context()?;
let mut irq = RuntimeIrqGuard::enter();
let mut cpu = runtime_current_cpu_mut(&mut irq)?;
runtime_task_system()?.replace_current_address_space(cpu.as_mut(), address_space)
}
pub fn detach_current_address_space()
-> Result<crate::runtime::resource::AddressSpaceToken, TaskError> {
validate_task_context()?;
let mut irq = RuntimeIrqGuard::enter();
let mut cpu = runtime_current_cpu_mut(&mut irq)?;
runtime_task_system()?.detach_current_address_space(cpu.as_mut())
}
pub fn release_address_space_token(
address_space: crate::runtime::resource::AddressSpaceToken,
) -> Result<(), TaskError> {
validate_task_context()?;
runtime_task_system()?.release_address_space_token(address_space);
Ok(())
}
use crate::runtime::handle::opaque_handle;
opaque_handle!(
ExecutionContextHandle,
"runtime::resource"
);
opaque_handle!(
StackHandle,
"runtime::resource"
);
opaque_handle!(
TlsHandle,
"runtime::resource"
);
opaque_handle!(
AddressSpaceHandle,
"runtime::resource"
);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(transparent)]
pub struct AddressSpaceMembarrierId(usize);
impl AddressSpaceMembarrierId {
pub const NONE: Self = Self(0);
pub const unsafe fn from_raw(raw: usize) -> Self {
Self(raw)
}
pub const fn is_none(self) -> bool {
self.0 == 0
}
pub const fn into_raw(self) -> usize {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum MembarrierRegistration {
GlobalExpedited = 1,
PrivateExpedited = 2,
}
impl MembarrierRegistration {
pub const fn requested_bit(self) -> u32 {
self as u32
}
pub const fn ready_bit(self) -> u32 {
(self as u32) << 16
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum MembarrierRegistrationPhase {
Begin = 0,
Complete = 1,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct AddressSpaceMembarrierState {
identity: AddressSpaceMembarrierId,
bits: u32,
}
impl AddressSpaceMembarrierState {
pub const NONE: Self = Self {
identity: AddressSpaceMembarrierId::NONE,
bits: 0,
};
pub const unsafe fn new(identity: AddressSpaceMembarrierId, bits: u32) -> Self {
Self { identity, bits }
}
pub const fn identity(self) -> AddressSpaceMembarrierId {
self.identity
}
pub const fn requested(self, registration: MembarrierRegistration) -> bool {
self.bits & registration.requested_bit() != 0
}
pub const fn ready(self, registration: MembarrierRegistration) -> bool {
self.bits & registration.ready_bit() != 0
}
pub const fn any_requested(self) -> bool {
self.bits
& (MembarrierRegistration::GlobalExpedited.requested_bit()
| MembarrierRegistration::PrivateExpedited.requested_bit())
!= 0
}
pub const fn bits(self) -> u32 {
self.bits
}
}
pub(crate) const fn scheduled_membarrier_state(
active_mm_state: AddressSpaceMembarrierState,
task_membarrier_state: AddressSpaceMembarrierState,
) -> AddressSpaceMembarrierState {
if task_membarrier_state.identity().is_none() {
active_mm_state
} else {
task_membarrier_state
}
}
#[cfg(axtest)]
pub const fn scheduled_membarrier_state_for_test(
active_mm_state: AddressSpaceMembarrierState,
task_membarrier_state: AddressSpaceMembarrierState,
) -> AddressSpaceMembarrierState {
scheduled_membarrier_state(active_mm_state, task_membarrier_state)
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum RuntimeMembarrierAction {
MemoryBarrier = 0,
RefreshRunQueue = 1,
}
#[repr(transparent)]
#[derive(Debug, Eq, PartialEq)]
pub struct AddressSpaceToken(usize);
impl AddressSpaceToken {
pub const NONE: Self = Self(0);
pub const unsafe fn from_raw(raw: usize) -> Self {
Self(raw)
}
pub const fn handle(&self) -> AddressSpaceHandle {
unsafe { AddressSpaceHandle::from_raw(self.0) }
}
pub const fn is_none(&self) -> bool {
self.0 == 0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum AddressSpaceDestroyOutcome {
Released = 0,
Active = 1,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum AddressSpaceReclaimArmOutcome {
Ready = 0,
Armed = 1,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct StackRequest {
pub usable_size: usize,
pub alignment: usize,
pub guard_size: usize,
}
pub type KernelEntry = unsafe extern "C" fn() -> !;
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct KernelContextRequest {
pub stack: StackHandle,
pub entry: KernelEntry,
pub tls: TlsHandle,
}
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct UserContextRequest {
pub stack: StackHandle,
pub entry: KernelEntry,
pub tls: TlsHandle,
}