# Очередь отзыва (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` 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`.