feat: docs & ARCH 2.2, 2.3, 2.4

This commit is contained in:
Faynot
2026-07-07 16:40:41 +03:00
parent c092a81331
commit 1bfde637d0
50 changed files with 5113 additions and 1823 deletions

View File

@@ -0,0 +1,128 @@
# Очередь отзыва RevocationQueue: `events.rs`
## Концептуальная модель
**RevocationQueue** — это глобальная lock-free кольцевая очередь,
которая соединяет capability-систему (CNode) с виртуальной памятью (VMM).
### Назначение
Когда capability отзывается, VMM должна аннулировать все VMA,
связанные с этим capability. Но:
- CNode.revoke() не может напрямую обратиться к VMM (разные подсистемы,
разное время жизни блокировок).
- VMM может быть в обработке page fault'а.
- Отзыв может быть каскадным и рекурсивным.
Решение: **асинхронная очередь**.
```
CNode.revoke(token_1)
└──→ push(token_1) ───→ MMU_REVOCATION_QUEUE ──→ pop() ──→ VMM
CNode.revoke(token_2) │
│ │
└──→ push(token_2) ─────────────────────────────────────────┤
Page Fault handler │
│ │
└──→ process_pending_revocations() ←────────────────────────┘
```
## RevocationQueue — детали
```rust
pub struct RevocationQueue {
buffer: [AtomicU64; QUEUE_SIZE], // 1024 entry
_pad0: [u8; 64], // padding: кэш-линия
head: AtomicUsize, // читатель (VMM)
_pad1: [u8; 64], // padding: кэш-линия
tail: AtomicUsize, // писатели (CNode revoke)
}
```
Тот же паттерн, что и в `PMActorQueue`: разделение head и tail
по разным кэш-линиям предотвращает false sharing.
### push(token_sig)
```rust
pub fn push(&self, token_sig: u64) -> Result<(), &'static str> {
let mut tail = self.tail.load(Ordering::Relaxed);
loop {
let head = self.head.load(Ordering::Acquire);
if tail.wrapping_sub(head) >= QUEUE_SIZE {
return Err("Revocation queue overflow");
}
match self.tail.compare_exchange_weak(tail, tail+1, AcqRel, Relaxed) {
Ok(_) => {
self.buffer[tail & QUEUE_MASK].store(token_sig, Release);
return Ok(());
}
Err(actual) => tail = actual,
}
}
}
```
### pop()
```rust
pub fn pop(&self) -> Option<u64> {
let head = self.head.load(Ordering::Relaxed);
let tail = self.tail.load(Ordering::Acquire);
if head == tail { return None; }
let token = self.buffer[head & QUEUE_MASK].load(Ordering::Acquire);
self.head.store(head.wrapping_add(1), Ordering::Release);
Some(token)
}
```
## Глобальный экземпляр
```rust
pub static MMU_REVOCATION_QUEUE: RevocationQueue = RevocationQueue::new();
```
## VMM: обработка отзывов
```rust
// В interrupts.rs: rust_page_fault_handler()
let mut vmm_guard = KERNEL_SPACE.lock();
if let Some(space) = vmm_guard.as_mut() {
space.process_pending_revocations(); // ← дренирует очередь
match space.handle_fault(fault_addr, write) { ... }
}
```
```rust
// В vmm.rs: AddressSpace
pub fn process_pending_revocations(&mut self) {
let mut needs_flush = false;
while let Some(token) = MMU_REVOCATION_QUEUE.pop() {
self.do_revoke_by_token(token);
needs_flush = true;
}
if needs_flush {
tlb_flush_asid(self.asid);
}
}
```
## Почему именно так?
1. **Lock-free**: отзыв capability не блокируется VMM.
2. **Batch processing**: VMM обрабатывает сразу все накопленные отзывы
при следующем page fault, экономя TLB flush'ы.
3. **Deadlock prevention**: process_pending_revocations вызывается
**до** handle_fault, избегая циклических зависимостей между
блокировками capability и VMM.
4. **Простота**: кольцевой буфер с CAS — проверенная временем структура.
## Ограничения
- Размер: 1024 entry. Если очередь переполняется — **паника**.
Это проектный выбор: переполнение означает, что VMM не успевает
обрабатывать отзывы быстрее, чем CNode генерирует новые.
- Однопоточный pop (только page fault handler дренирует очередь).