// black metal kernel — episode 06 of 08
// kernel programming in rust — zero-cost abstractions — no gc — no mercy
// 06 — the black mutex: bounding mutability safely
interior mutability in rust breaks the strict mutable borrowing rules by tunneling through a shared reference (`&T`). in kernel context, it is indispensable for sharing state like framebuffers and thread allocators across multiple cores. true interior mutability is built upon `UnsafeCell`—the only core primitive that legally opts out of standard immutability invariants.
our `BlackMutex` wraps an `UnsafeCell` alongside the `BlackSpinlock` from our foundation. we utilize the RAII (Resource Acquisition Is Initialization) pattern to guarantee release upon scope exit. access is rigidly bound by a `BlackMutexGuard`, avoiding dangling locks during mid-function panics or early returns.
use core::cell::UnsafeCell; use core::ops::{Deref, DerefMut}; pub struct BlackMutex<T> { black_lock: crate::sync::BlackSpinlock, black_data: UnsafeCell<T>, } unsafe impl<T: Send> Sync for BlackMutex<T> {} unsafe impl<T: Send> Send for BlackMutex<T> {} impl<T> BlackMutex<T> { pub const fn black_new(black_val: T) -> Self { Self { black_lock: crate::sync::BlackSpinlock::black_new(), black_data: UnsafeCell::new(black_val), } } pub fn black_lock(&self) -> BlackMutexGuard<'_, T> { self.black_lock.black_acquire(); BlackMutexGuard { black_mutex: self, } } } pub struct BlackMutexGuard<'a, T> { black_mutex: &'a BlackMutex<T>, } impl<T> Deref for BlackMutexGuard<'_, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.black_mutex.black_data.get() } } } impl<T> DerefMut for BlackMutexGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.black_mutex.black_data.get() } } } impl<T> Drop for BlackMutexGuard<'_, T> { fn drop(&mut self) { self.black_mutex.black_lock.black_release(); } }
// 06 / 08 — black_ptr owns its truth — BLACK0X80