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

173
kernel/docs/pmactor.md Normal file
View File

@@ -0,0 +1,173 @@
# Акторы физической памяти (PMActor) и маршрутизатор (PM Router)
---
## Формат сообщений
Вся коммуникация использует упаковку в `u64`:
```
[8b opcode | 16b channel_id | 20b arg1 | 20b arg2]
```
Константы: `OPCODE_SHIFT = 56`, `CHAN_SHIFT = 40`, `ARG1_SHIFT = 20`
Маски: `CHAN_MASK = 0x0000_FFFF`, `ARG_MASK = 0x000F_FFFF`
---
## PMActor
**Файл**: `src/mem/pm_manages.rs`
Распределённый актор физической памяти. Каждый актор владеет фиксрованным диапазоном и управляет им через BuddyAllocator.
### PMRequest
```rust
pub enum PMRequest {
Allocate { size_pages: usize, token_sig: u32, channel_id: u16 },
Free { local_frame_idx: usize, order: usize },
Carve { offset_pages: usize, size_pages: usize, channel_id: u16 },
None, // sentinel (не может быть отправлен)
}
```
Методы: `pack() -> u64`, `unpack(val: u64) -> Self`.
### PMResult
```rust
pub enum PMResult {
Allocated { cap: Capability, order: usize },
OutOfMemory { size_pages: usize },
Carved { cap: Capability },
Freed { pages_returned: usize },
}
```
### PMResponse
```rust
pub struct PMResponse {
pub channel_id: u16,
pub result: PMResult,
}
```
### PMActorQueue — Lock-free MPSC
Кольцевой буфер на 1024 слота (`AtomicU64`) с cache-line padding.
- `send(req)` — CAS loop на `tail` (multi-producer). Отклоняет None.
- `pop()` — single-consumer. `Acquire`/`Release` ordering.
### PMActor
```rust
pub struct PMActor {
actor_id: u64,
root_untyped: Capability,
managed_range: (PhysAddr, PhysAddr), // [start, end)
queue: PMActorQueue,
buddy: BuddyAllocator,
}
```
#### `new(actor_id, root_cap, start, size_bytes) -> Self`
Конструктор.
#### `submit_request(req) -> Result<(), &str>`
Thread-safe: пушит в `queue`.
#### `process_messages(&mut self) -> Vec<PMResponse>`
Дренирует очередь, обрабатывает каждый запрос через приватные методы.
**Только из контекста актора** (`&mut self` гарантирует single consumer).
#### Приватные обработчики
**`handle_allocate(size_pages, token_sig, channel_id) -> Option<PMResponse>`**
1. `buddy.alloc_pages(size_pages)``(local_idx, order)`
2. Строит сильную дочернюю Capability с уникальным `token_sig`
3. Возвращает `Allocated { cap, order }`
4. При неудаче: `OutOfMemory` (планируется ballooning)
**`handle_free(local_frame_idx, order) -> Option<PMResponse>`**
1. Валидация границ
2. `buddy.free(local_frame_idx, order)`
3. Возвращает None (маршрутизация не нужна)
**`handle_carve(offset_pages, size_pages, channel_id) -> Option<PMResponse>`**
1. Валидация диапазона
2. Возвращает `Carved { cap }`
3. Не взаимодействует с buddy
---
## PMRouter
**Файл**: `src/mem/pm_router.rs`
Глобальная ткань маршрутизации: 65536 lock-free каналов.
### Константы
- `CHANNEL_COUNT = 65536`
- Состояния: `STATE_FREE = 0`, `STATE_PENDING = 1`, `STATE_READY = 2`
### Channel — `#[repr(align(64))]`
```rust
struct Channel {
state: AtomicU8,
next_free: AtomicU16,
result: UnsafeCell<Option<PMResult>>,
}
```
### PMRouter
```rust
pub struct PMRouter {
channels: Box<[Channel]>, // 65536 каналов
free_head: AtomicU16, // голова free list (0 = sentinel)
}
```
### GlobalRouter
```rust
static ROUTER: GlobalRouter; // синглтон
```
### `init()`
1. Создаёт Vec из 65536 каналов, соединённых в linked list (каждый `next_free` указывает на следующий)
2. Преобразует в `Box<[Channel]>`
3. Сохраняет в `ROUTER.inner`, устанавливает `is_ready`
### `alloc_channel() -> Option<u16>`
CAS-цикл на `free_head`: извлекает голову списка, устанавливает `state = PENDING`.
### `route_responses(responses: Vec<PMResponse>)`
Для каждого PMResponse с ненулевым `channel_id`: сохраняет `result` в канале, устанавливает `state = READY`.
### `wait_for_response(id: u16) -> PMResult`
Spin-wait до `state == READY`. Забирает результат, пушит канал обратно в freelist, возвращает результат.
### `request_and_wait(actor, req_builder) -> PMResult`
Convenience: аллоцирует канал, строит запрос с channel_id, отправляет актору, ждёт ответ. (process_messages должен быть вызван внешне.)
### `dispatch(responses: Vec<PMResponse>)`
Точка входа для маршрутизации ответов через `PMActor::route_responses()` (вызов на глобальном роутере).