fix: bugs
This commit is contained in:
173
kernel/docs/pmactor.md
Normal file
173
kernel/docs/pmactor.md
Normal 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()` (вызов на глобальном роутере).
|
||||
Reference in New Issue
Block a user