Files
Elyz/kernel/docs/events.md
2026-07-06 00:25:49 +03:00

86 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Очередь отзыва (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`.