fix: bugs
This commit is contained in:
85
kernel/docs/events.md
Normal file
85
kernel/docs/events.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Очередь отзыва (RevocationQueue)
|
||||
|
||||
**Файл**: `src/events.rs`
|
||||
|
||||
Lock-free MPSC (Multi-Producer Single-Consumer) очередь для уведомления VMM об отзыве capability.
|
||||
|
||||
---
|
||||
|
||||
## RevocationQueue
|
||||
|
||||
```rust
|
||||
pub struct RevocationQueue {
|
||||
buffer: [AtomicU64; QUEUE_SIZE], // 1024 слота
|
||||
_pad0: [u8; 64], // cache-line padding
|
||||
head: AtomicUsize, // индекс потребителя (VMM)
|
||||
_pad1: [u8; 64], // ещё padding
|
||||
tail: AtomicUsize, // индекс производителя (CNode)
|
||||
}
|
||||
```
|
||||
|
||||
Cache-line padding (64 байта) предотвращает **false sharing** между head и tail на разных кэш-линиях.
|
||||
|
||||
### Константы
|
||||
|
||||
- `QUEUE_SIZE = 1024`
|
||||
- `QUEUE_MASK = 1023`
|
||||
|
||||
### `new() -> Self`
|
||||
|
||||
Все слоты = 0, head = 0, tail = 0.
|
||||
|
||||
### `push(token_sig: u64) -> Result<(), &'static str>`
|
||||
|
||||
1. Читает `tail` (Relaxed)
|
||||
2. CAS-цикл: пытается захватить следующий слот
|
||||
3. Если буфер полон (`tail - head == QUEUE_SIZE`): ошибка
|
||||
4. Записывает `token_sig` в `buffer[tail & QUEUE_MASK]` (Release ordering)
|
||||
5. Обновляет `tail` (Release)
|
||||
|
||||
**Производители**: CNode::revoke() — при каждом отзыве пушит token_sig.
|
||||
|
||||
### `pop() -> Option<u64>`
|
||||
|
||||
1. Читает `tail` (Acquire) и `head` (Relaxed)
|
||||
2. Если `head == tail`: буфер пуст, None
|
||||
3. Читает `buffer[head & QUEUE_MASK]` (Acquire)
|
||||
4. Обновляет `head` (Release)
|
||||
5. Возвращает token
|
||||
|
||||
**Потребитель**: VMM — `AddressSpace::process_pending_revocations()`.
|
||||
|
||||
---
|
||||
|
||||
## Глобальный экземпляр
|
||||
|
||||
```rust
|
||||
pub static MMU_REVOCATION_QUEUE: RevocationQueue = RevocationQueue::new();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Полный цикл ревокации
|
||||
|
||||
```
|
||||
CNode::revoke(slot_idx)
|
||||
→ revoke_internal(slot_idx) // рекурсивное уничтожение потомков
|
||||
→ slot = Empty
|
||||
→ MMU_REVOCATION_QUEUE.push(token_sig)
|
||||
|
||||
... позже, при page fault ...
|
||||
|
||||
rust_page_fault_handler()
|
||||
→ process_deferred_mmu_events()
|
||||
→ KERNEL_SPACE.lock()
|
||||
→ process_pending_revocations()
|
||||
→ while let Some(token) = MMU_REVOCATION_QUEUE.pop()
|
||||
→ revoke_by_token(token)
|
||||
→ unmap matching VMAs (кроме PINNED)
|
||||
→ TLB flush
|
||||
|
||||
→ KERNEL_SPACE.lock()
|
||||
→ handle_fault(fault_addr, write) // обработка исходного fault
|
||||
```
|
||||
|
||||
**Почему такая очерёдность?** Ревокации обрабатываются **до** захвата VMM для page fault, чтобы избежать deadlock'а: и revoke, и handle_fault хотят lock на `KERNEL_SPACE`.
|
||||
Reference in New Issue
Block a user