fix: bugs

This commit is contained in:
Faynot
2026-07-06 00:25:49 +03:00
parent 1b38c7f445
commit c092a81331
23 changed files with 2502 additions and 123 deletions

View File

@@ -94,7 +94,6 @@ pub enum PMRequest {
size_pages: usize,
channel_id: u16,
},
/// Sentinel — never pushed onto the queue; result of unpack(0).
None,
}
@@ -160,30 +159,18 @@ impl PMRequest {
// Response type
/// Result returned by `PMActor::process_messages()` for each completed request.
#[derive(Debug, Clone, Copy)]
pub struct PMResponse {
/// Channel to route this response to. `0` = discard.
pub channel_id: u16,
/// The actual outcome.
pub result: PMResult,
}
/// Outcome of a single PM operation.
#[derive(Debug, Clone, Copy)]
pub enum PMResult {
/// Memory was allocated. `cap` is the strong capability to the region.
/// `order` is the buddy order — **must** be passed back to `Free`.
Allocated { cap: Capability, order: usize },
/// The actor had insufficient free pages.
/// Future: ballooning subsystem intercepts this and retries.
OutOfMemory { size_pages: usize },
/// A fixed sub-region was carved successfully.
Carved { cap: Capability },
/// Free completed (no capability issued — memory returned to buddy pool).
Freed { pages_returned: usize },
}
@@ -194,7 +181,6 @@ pub enum PMResult {
/// `pop` — exactly one consumer, no locking on the read side.
pub struct PMActorQueue {
buffer: [AtomicU64; QUEUE_SIZE],
/// Pad to separate producer-written `tail` from consumer-read `head`.
_pad0: [u8; 64],
head: AtomicUsize,
_pad1: [u8; 64],
@@ -269,15 +255,10 @@ impl PMActorQueue {
/// Only `process_messages()` ever mutates `buddy` and `queue.head`.
/// This is enforced by taking `&mut self` on `process_messages`.
pub struct PMActor {
/// Unique identity within the actor federation.
pub actor_id: u64,
/// Root strong capability over the entire managed physical range.
pub root_untyped: Capability,
/// `(inclusive_start, exclusive_end)` physical addresses.
pub managed_range: (PhysAddr, PhysAddr),
/// Inbox — producers write here, actor reads here.
queue: PMActorQueue,
/// Local buddy allocator. Only ever touched in `process_messages`.
buddy: BuddyAllocator,
}
@@ -325,10 +306,16 @@ impl PMActor {
/// `buddy` and `queue.head` are mutated — no other thread touches them.
/// The only shared state is the queue's `tail`, which is written by producers
/// via `AtomicUsize::compare_exchange_weak`, never by this path.
/// Maximum requests to process in a single `process_messages` call.
/// Prevents kernel starvation when the inbox is deep.
const MAX_MESSAGES_PER_CALL: usize = 64;
pub fn process_messages(&mut self) -> Vec<PMResponse> {
let mut responses = Vec::new();
let mut remaining = Self::MAX_MESSAGES_PER_CALL;
while let Some(req) = self.queue.pop() {
remaining -= 1;
let resp = match req {
PMRequest::Allocate { size_pages, token_sig, channel_id } => {
self.handle_allocate(size_pages, token_sig, channel_id)
@@ -342,12 +329,13 @@ impl PMActor {
PMRequest::None => continue,
};
// Only push responses that need routing.
// Free responses (channel_id == 0) are still pushed so callers can
// audit completion if needed; they may simply drop them.
if let Some(r) = resp {
responses.push(r);
}
if remaining == 0 {
break;
}
}
responses
@@ -434,9 +422,6 @@ impl PMActor {
self.buddy.free(local_frame_idx, order);
// Free never needs routing — return None to skip Vec push, or push with
// channel_id=0 for audit purposes. We skip to avoid unnecessary allocation.
// Callers that need a Free-complete signal should use a separate mechanism.
None
}
@@ -446,7 +431,6 @@ impl PMActor {
size_pages: usize,
channel_id: u16,
) -> Option<PMResponse> {
// Validate offset + size within range.
let range_pages = self.buddy.total_pages();
if offset_pages >= range_pages
|| size_pages == 0