feat(kernel): per-process budgets (pages, endpoints, notifs, regions) carved from creator, returned on death; init owns pool
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
pub mod abi;
|
||||
mod board;
|
||||
mod budget;
|
||||
mod captree;
|
||||
pub mod interrupt;
|
||||
mod memory;
|
||||
@@ -33,11 +34,12 @@ pub use syscall::{SyscallOutcome, SyscallResult};
|
||||
mod tests;
|
||||
|
||||
use domain::{
|
||||
capability::{Capability, CapabilityTable},
|
||||
budget::{Budget, Limits},
|
||||
capability::Capability,
|
||||
endpoint::EndpointTable,
|
||||
error::KernelError,
|
||||
irq::IrqRoutingTable,
|
||||
memory::{RegionTable, frame::FrameTable, quota::Quota},
|
||||
memory::{RegionTable, frame::FrameTable},
|
||||
notification::NotificationTable,
|
||||
process::{MAX_PROCESSES, ProcessTable},
|
||||
resource::Resource,
|
||||
@@ -61,7 +63,9 @@ pub struct Kernel<P: Platform> {
|
||||
endpoints: EndpointTable,
|
||||
scheduler: MultiCoreScheduler,
|
||||
frames: FrameTable,
|
||||
quotas: [Quota; MAX_PROCESSES],
|
||||
budgets: [Budget; MAX_PROCESSES],
|
||||
/// Whose budget each process was carved from (see budget.rs).
|
||||
parents: [Option<ProcessId>; MAX_PROCESSES],
|
||||
regions: RegionTable,
|
||||
irqs: IrqRoutingTable,
|
||||
notifications: NotificationTable,
|
||||
@@ -85,7 +89,8 @@ impl<P: Platform> Kernel<P> {
|
||||
endpoints: EndpointTable::new(),
|
||||
scheduler: MultiCoreScheduler::new(num_cores),
|
||||
frames: FrameTable::new(pool_base, pool_pages),
|
||||
quotas: [Quota::default(); MAX_PROCESSES],
|
||||
budgets: [Budget::EMPTY; MAX_PROCESSES],
|
||||
parents: [None; MAX_PROCESSES],
|
||||
regions: RegionTable::new(),
|
||||
irqs: IrqRoutingTable::new(),
|
||||
notifications: NotificationTable::new(),
|
||||
@@ -118,7 +123,8 @@ impl<P: Platform> Kernel<P> {
|
||||
addr_of_mut!((*slot).endpoints).write(EndpointTable::new());
|
||||
addr_of_mut!((*slot).scheduler).write(MultiCoreScheduler::new(num_cores));
|
||||
addr_of_mut!((*slot).frames).write(FrameTable::new(pool_base, pool_pages));
|
||||
addr_of_mut!((*slot).quotas).write([Quota::default(); MAX_PROCESSES]);
|
||||
addr_of_mut!((*slot).budgets).write([Budget::EMPTY; MAX_PROCESSES]);
|
||||
addr_of_mut!((*slot).parents).write([None; MAX_PROCESSES]);
|
||||
addr_of_mut!((*slot).regions).write(RegionTable::new());
|
||||
addr_of_mut!((*slot).irqs).write(IrqRoutingTable::new());
|
||||
addr_of_mut!((*slot).notifications).write(NotificationTable::new());
|
||||
@@ -135,11 +141,14 @@ impl<P: Platform> Kernel<P> {
|
||||
priority: Priority,
|
||||
time_slice: TimeSlice,
|
||||
) -> Result<(ProcessId, ThreadId), KernelError> {
|
||||
let pid = self.processes.create(CapabilityTable::new(), None)?;
|
||||
if let Err(e) = self.create_address_space(pid) {
|
||||
let _ = self.processes.destroy(pid);
|
||||
return Err(e);
|
||||
}
|
||||
// Init holds every frame and every kernel object to start with.
|
||||
let everything = Limits {
|
||||
pages: self.frames.free_count(),
|
||||
endpoints: domain::endpoint::MAX_ENDPOINTS,
|
||||
notifications: domain::notification::MAX_NOTIFICATIONS,
|
||||
regions: domain::memory::MAX_REGIONS,
|
||||
};
|
||||
let pid = self.new_process(None, everything)?;
|
||||
let tid = self.threads.spawn(pid, priority, time_slice, None)?;
|
||||
self.processes.get_mut(pid)?.add_thread(tid)?;
|
||||
|
||||
@@ -211,13 +220,13 @@ impl<P: Platform> Kernel<P> {
|
||||
self.scheduler.next(core)
|
||||
}
|
||||
|
||||
pub fn create_process_internal(&mut self) -> Option<ProcessId> {
|
||||
let pid = self.processes.create(CapabilityTable::new(), None).ok()?;
|
||||
if self.create_address_space(pid).is_err() {
|
||||
let _ = self.processes.destroy(pid);
|
||||
return None;
|
||||
}
|
||||
Some(pid)
|
||||
/// A process for boot code to load, its `limits` carved from `parent`.
|
||||
pub fn create_process_internal(
|
||||
&mut self,
|
||||
parent: ProcessId,
|
||||
limits: Limits,
|
||||
) -> Option<ProcessId> {
|
||||
self.new_process(Some(parent), limits).ok()
|
||||
}
|
||||
|
||||
pub fn spawn_thread_internal(&mut self, pid: ProcessId) -> Option<ThreadId> {
|
||||
@@ -237,7 +246,11 @@ impl<P: Platform> Kernel<P> {
|
||||
owner: ProcessId,
|
||||
) -> Result<types::id::EndpointId, KernelError> {
|
||||
self.processes.get(owner)?;
|
||||
self.endpoints.create(owner).ok_or(KernelError::NoFreeSlot)
|
||||
self.charge_object(owner, budget::ENDPOINTS)?;
|
||||
self.endpoints
|
||||
.create(owner)
|
||||
.ok_or(KernelError::NoFreeSlot)
|
||||
.inspect_err(|_| self.uncharge_object(owner, budget::ENDPOINTS))
|
||||
}
|
||||
|
||||
pub fn grant_capability(
|
||||
|
||||
Reference in New Issue
Block a user