1use core::sync::atomic::{AtomicU64, Ordering};
4
5use crate::{
6 runtime::{
7 lock::{RawTicketGuard, RawTicketLock},
8 sync::{
9 PI_MUTEX_WAIT_STORAGE_WORDS, PiMutexCoreView, PiMutexRaw, PiMutexRef,
10 PiMutexStateError, PiTaskId, PiWaitStateError,
11 },
12 },
13 thread::{PiWaitTree, TaskError, ThreadId},
14};
15
16impl From<ThreadId> for PiTaskId {
17 fn from(thread: ThreadId) -> Self {
18 Self::new(thread.as_u64()).expect("scheduler thread identity must fit the PI owner word")
19 }
20}
21
22impl From<PiTaskId> for ThreadId {
23 fn from(thread: PiTaskId) -> Self {
24 let raw = thread.get();
25 Self::from_parts(raw as u32, (raw >> 32) as u32)
26 }
27}
28
29impl From<PiMutexStateError> for TaskError {
30 fn from(error: PiMutexStateError) -> Self {
31 match error {
32 PiMutexStateError::WaiterOwnsLock => {
33 Self::InvalidPiWaitState(PiWaitStateError::WaiterOwnsLock)
34 }
35 PiMutexStateError::InvalidState => Self::InvalidPiState,
36 }
37 }
38}
39
40#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46pub(crate) struct PiWaitRegistration {
47 pub(crate) lock: PiMutexRaw,
48 pub(crate) key: crate::thread::PiWaitKey,
49 pub(crate) generation: u64,
50}
51
52#[derive(Debug)]
53pub(crate) struct PiMutexWaiters {
54 pub(crate) waiters: PiWaitTree,
55}
56
57impl PiMutexWaiters {
58 const fn new() -> Self {
59 Self {
60 waiters: PiWaitTree::new(),
61 }
62 }
63}
64
65pub(crate) struct PiMutexWaitHandle {
67 state: RawTicketLock<PiMutexWaiters>,
68}
69
70impl PiMutexWaitHandle {
71 fn new() -> Self {
72 Self {
73 state: RawTicketLock::new(PiMutexWaiters::new()),
74 }
75 }
76}
77
78impl Drop for PiMutexWaitHandle {
79 fn drop(&mut self) {
80 assert!(
81 self.state.lock().waiters.is_empty(),
82 "a PI mutex cannot be destroyed with live scheduler waiters"
83 );
84 }
85}
86
87pub(crate) fn lock_pi_mutex_waiters(lock: PiMutexRef<'_>) -> RawTicketGuard<'_, PiMutexWaiters> {
88 ensure_pi_mutex_wait_handle(lock.core()).state.lock()
89}
90
91pub(crate) unsafe fn lock_raw_pi_mutex_waiters(
92 lock: PiMutexRaw,
93) -> RawTicketGuard<'static, PiMutexWaiters> {
94 installed_pi_mutex_wait_handle(unsafe {
95 lock.core()
97 })
98 .state
99 .lock()
100}
101
102pub(crate) unsafe fn try_lock_raw_pi_mutex_waiters(
103 lock: PiMutexRaw,
104) -> Option<RawTicketGuard<'static, PiMutexWaiters>> {
105 installed_pi_mutex_wait_handle(unsafe {
106 lock.core()
108 })
109 .state
110 .try_lock()
111}
112
113pub(crate) unsafe fn drop_pi_mutex_wait_handle(wait_handle: *mut ()) {
114 let wait_handle = wait_handle.cast::<PiMutexWaitHandle>();
115 unsafe { wait_handle.drop_in_place() };
118}
119
120fn ensure_pi_mutex_wait_handle<'lock>(core: PiMutexCoreView<'lock>) -> &'lock PiMutexWaitHandle {
121 const _: () = assert!(
122 core::mem::size_of::<PiMutexWaitHandle>()
123 <= PI_MUTEX_WAIT_STORAGE_WORDS * core::mem::size_of::<usize>()
124 );
125 const _: () =
126 assert!(core::mem::align_of::<PiMutexWaitHandle>() <= core::mem::align_of::<usize>());
127
128 unsafe {
129 core.wait_storage().get_or_init(PiMutexWaitHandle::new)
132 }
133}
134
135fn installed_pi_mutex_wait_handle<'lock>(core: PiMutexCoreView<'lock>) -> &'lock PiMutexWaitHandle {
136 unsafe {
137 core.wait_storage()
140 .get::<PiMutexWaitHandle>()
141 .expect("registered PI mutex has no scheduler wait handle")
142 }
143}
144
145#[derive(Debug)]
147pub(crate) struct PiWaitState {
148 generation: AtomicU64,
149 top_generation: AtomicU64,
150 granted_generation: AtomicU64,
151}
152
153impl PiWaitState {
154 pub(crate) const fn new() -> Self {
155 Self {
156 generation: AtomicU64::new(0),
157 top_generation: AtomicU64::new(0),
158 granted_generation: AtomicU64::new(0),
159 }
160 }
161
162 pub(crate) fn begin(&self) -> Result<u64, TaskError> {
163 self.top_generation.store(0, Ordering::Relaxed);
164 self.granted_generation.store(0, Ordering::Relaxed);
165 self.generation
166 .try_update(Ordering::AcqRel, Ordering::Acquire, |generation| {
167 generation.checked_add(1)
168 })
169 .map(|generation| generation + 1)
170 .map_err(|_| TaskError::InvalidPiState)
171 }
172
173 pub(crate) fn mark_top(&self, generation: u64) -> Result<(), TaskError> {
174 if self.generation.load(Ordering::Acquire) != generation
175 || self.granted_generation.load(Ordering::Acquire) == generation
176 {
177 return Err(TaskError::InvalidPiState);
178 }
179 self.top_generation.store(generation, Ordering::Release);
180 Ok(())
181 }
182
183 pub(crate) fn clear_top(&self, generation: u64) {
184 let _ = self.top_generation.compare_exchange(
185 generation,
186 0,
187 Ordering::AcqRel,
188 Ordering::Acquire,
189 );
190 }
191
192 pub(crate) fn grant(&self, generation: u64) -> Result<(), TaskError> {
193 if self.generation.load(Ordering::Acquire) != generation {
194 return Err(TaskError::InvalidPiState);
195 }
196 self.clear_top(generation);
197 self.granted_generation.store(generation, Ordering::Release);
198 Ok(())
199 }
200
201 pub(crate) fn can_grant(&self, generation: u64) -> bool {
202 self.generation.load(Ordering::Acquire) == generation
203 && self.granted_generation.load(Ordering::Acquire) != generation
204 }
205
206 pub(crate) fn is_granted(&self, generation: u64) -> bool {
207 self.granted_generation.load(Ordering::Acquire) == generation
208 }
209
210 pub(crate) fn is_top(&self, generation: u64) -> bool {
211 self.top_generation.load(Ordering::Acquire) == generation
212 }
213}