1#![doc = include_str!("../../docs/sync_model.md")]
5pub mod bellringer;
6pub mod irq;
7pub mod semaphore;
8pub mod spin;
9use crate::arch::x86_64::{gdt, is_int_enabled};
10use crate::black_magic::Void;
11use crate::proc::task::Task;
12use core::cell::SyncUnsafeCell;
13use core::ops::{Deref, DerefMut};
14use core::sync::atomic::{AtomicBool, Ordering};
15pub use irq::*;
16static L2_AVAILABLE: AtomicBool = AtomicBool::new(true);
18static L2_GUARD: L2Sync<Void> = L2Sync::new(Void::new());
20
21#[inline(always)]
22#[allow(non_snake_case)]
23pub fn IS_L2_AVAILABLE() -> bool {
24 return L2_AVAILABLE.load(Ordering::Relaxed);
25}
26
27#[allow(non_snake_case)]
29#[inline(always)]
30pub fn ENTER_L2() {
31 let r = L2_AVAILABLE.compare_exchange(
32 true,
33 false,
34 Ordering::Relaxed,
35 Ordering::Relaxed,
36 );
37 debug_assert_eq!(r, Ok(true));
38}
39
40#[no_mangle]
44extern "C" fn child_entry_cleanup() {
45 unsafe { gdt::set_tss_ksp(Task::current().unwrap().get_init_kernel_sp()) };
46 LEAVE_L2();
47}
48
49#[inline(always)]
56#[allow(non_snake_case)]
57pub fn LEAVE_L2() {
58 let r = L2_AVAILABLE.compare_exchange(
59 false,
60 true,
61 Ordering::Relaxed,
62 Ordering::Relaxed,
63 );
64 debug_assert_eq!(r, Ok(false));
65}
66
67#[inline(always)]
69#[allow(non_snake_case)]
70pub fn LEAVE_L2_CLEAR_QUEUE() {
71 todo!();
72}
73
74pub struct L2Guard<'a, T: 'a> {
76 lock: &'a L2Sync<T>,
77 }
79
80impl<T> Deref for L2Guard<'_, T> {
81 type Target = T;
82 fn deref(&self) -> &T { unsafe { &*self.lock.data.get() } }
83}
84
85impl<T> DerefMut for L2Guard<'_, T> {
86 fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.lock.data.get() } }
87}
88
89impl<T> Drop for L2Guard<'_, T> {
90 fn drop(&mut self) { LEAVE_L2(); }
91}
92
93pub struct L2Sync<T> {
95 data: SyncUnsafeCell<T>,
96}
97
98impl<T> L2Sync<T> {
99 pub const fn new(data: T) -> Self {
100 Self { data: SyncUnsafeCell::new(data) }
101 }
102 pub fn lock(&self) -> L2Guard<'_, T> {
103 ENTER_L2();
104 L2Guard { lock: self }
105 }
106
107 pub unsafe fn get_ref_unguarded(&self) -> &T { &*self.data.get() }
111
112 pub unsafe fn get_ref_mut_unguarded(&self) -> &mut T {
113 &mut *self.data.get()
114 }
115}
116
117pub struct L3Sync<T> {
122 data: SyncUnsafeCell<T>,
123}
124
125impl<T> L3Sync<T> {
126 pub const fn new(data: T) -> Self {
127 Self { data: SyncUnsafeCell::new(data) }
128 }
129 pub fn l3_get_ref(&self) -> &T {
133 debug_assert!(
134 !is_int_enabled(),
135 "trying to get a ref to L3 synced object with interrupt enabled"
136 );
137 unsafe { &*self.data.get() }
138 }
139 pub fn l3_get_ref_mut(&self) -> &mut T {
142 debug_assert!(
143 !is_int_enabled(),
144 "trying to get a mut ref to L3 synced object with interrupt enabled"
145 );
146 unsafe { &mut *self.data.get() }
147 }
148 pub unsafe fn l3_get_ref_mut_unchecked(&self) -> &mut T {
150 unsafe { &mut *self.data.get() }
151 }
152}