feat: docs & ARCH 2.2, 2.3, 2.4
This commit is contained in:
128
kernel/docs/events/introduction.md
Normal file
128
kernel/docs/events/introduction.md
Normal 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 дренирует очередь).
|
||||
Reference in New Issue
Block a user