// SPDX-License-Identifier: MIT OR Apache-2.0 // // Copyright (c) 2018-2019 Andre Richter //! Synchronization primitives. use crate::interface; use core::cell::UnsafeCell; //-------------------------------------------------------------------------------------------------- // Arch-public //-------------------------------------------------------------------------------------------------- /// A pseudo-lock for teaching purposes. /// /// Used to introduce [interior mutability]. /// /// In contrast to a real Mutex implementation, does not protect against concurrent access to the /// contained data. This part is preserved for later lessons. /// /// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is /// executing single-threaded, aka only running on a single core with interrupts disabled. /// /// [interior mutability]: https://doc.rust-lang.org/std/cell/index.html pub struct NullLock { data: UnsafeCell, } unsafe impl Send for NullLock {} unsafe impl Sync for NullLock {} impl NullLock { pub const fn new(data: T) -> NullLock { NullLock { data: UnsafeCell::new(data), } } } //-------------------------------------------------------------------------------------------------- // OS interface implementations //-------------------------------------------------------------------------------------------------- impl interface::sync::Mutex for &NullLock { type Data = T; fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { // In a real lock, there would be code encapsulating this line that ensures that this // mutable reference will ever only be given out once at a time. f(unsafe { &mut *self.data.get() }) } }