aloe/
sync.rs

1/*
2  ____                 __               __  __
3 / __ \__ _____ ____  / /___ ____ _    / / / /__ ___ ____
4/ /_/ / // / _ `/ _ \/ __/ // /  ' \  / /_/ (_-</ -_) __/
5\___\_\_,_/\_,_/_//_/\__/\_,_/_/_/_/  \____/___/\__/_/
6  Part of the Quantum OS Kernel
7
8Copyright 2025 Gavin Kellam
9
10Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
11associated documentation files (the "Software"), to deal in the Software without restriction,
12including without limitation the rights to use, copy, modify, merge, publish, distribute,
13sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
14furnished to do so, subject to the following conditions:
15
16The above copyright notice and this permission notice shall be included in all copies or substantial
17portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
20NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
23OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24*/
25
26use core::{
27    cell::UnsafeCell,
28    fmt::{Debug, Display},
29    ops::{Deref, DerefMut},
30    sync::atomic::{AtomicBool, Ordering},
31};
32use vera_portal::sys_client::yield_now;
33
34/// A QuantumOS Mutex with yield relax behavior.
35pub struct Mutex<T: ?Sized> {
36    lock: AtomicBool,
37    inner: UnsafeCell<T>,
38}
39
40unsafe impl<T: ?Sized> Send for Mutex<T> {}
41unsafe impl<T: ?Sized> Sync for Mutex<T> {}
42
43impl<T> Mutex<T> {
44    /// Create a new mutex lock with the provided data
45    pub const fn new(value: T) -> Self {
46        Self {
47            lock: AtomicBool::new(false),
48            inner: UnsafeCell::new(value),
49        }
50    }
51}
52
53impl<T: ?Sized> Mutex<T> {
54    /// Try to lock this mutex
55    pub fn try_lock<'a>(&'a self) -> Option<MutexGuard<'a, T>> {
56        while let Err(failed_lock) =
57            self.lock
58                .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
59        {
60            // If this lock is already set, we fail the lock
61            if failed_lock {
62                return None;
63            }
64        }
65
66        Some(MutexGuard {
67            lock: &self.lock,
68            ptr: self.inner.get(),
69        })
70    }
71
72    /// Lock this mutex
73    pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
74        loop {
75            match self.try_lock() {
76                Some(lock) => return lock,
77                None => {
78                    // TODO: In the future we should add thread parking to the scheduler
79                    yield_now();
80                }
81            }
82        }
83    }
84}
85
86/// A protected guard for the mutex
87pub struct MutexGuard<'a, T: ?Sized> {
88    lock: &'a AtomicBool,
89    ptr: *mut T,
90}
91
92impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
93    fn drop(&mut self) {
94        while let Err(failed_unlock) =
95            self.lock
96                .compare_exchange(true, false, Ordering::Release, Ordering::Relaxed)
97        {
98            assert!(
99                failed_unlock,
100                "Mutex is marked as unlocked while dropping MutexGuard"
101            );
102        }
103    }
104}
105
106impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
107    type Target = T;
108
109    fn deref(&self) -> &Self::Target {
110        unsafe { &*self.ptr }
111    }
112}
113
114impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
115    fn deref_mut(&mut self) -> &mut Self::Target {
116        unsafe { &mut *self.ptr }
117    }
118}
119
120impl<'a, T: ?Sized + Debug> Debug for MutexGuard<'a, T> {
121    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122        unsafe { &*self.ptr }.fmt(f)
123    }
124}
125
126impl<'a, T: ?Sized + Display> Display for MutexGuard<'a, T> {
127    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
128        unsafe { &*self.ptr }.fmt(f)
129    }
130}
131
132impl<T: Clone> Clone for Mutex<T> {
133    fn clone(&self) -> Self {
134        Mutex::new(self.lock().clone())
135    }
136}