1#![allow(dead_code)]
17
18use core::alloc::{GlobalAlloc, Layout};
19use core::ptr::{null_mut, NonNull};
20use core::sync::atomic::{AtomicBool, Ordering};
21use rlsf::Tlsf;
22
23type TheTlsf = Tlsf<'static, u32, u16, 25, 16>;
28
29struct TlsfHeap {
31 tlsf: TheTlsf,
32 total: usize,
33 used: usize,
34}
35
36impl TlsfHeap {
37 const fn empty() -> Self {
39 Self {
40 tlsf: Tlsf::new(),
41 total: 0,
42 used: 0,
43 }
44 }
45
46 unsafe fn init(&mut self, start: usize, size: usize) {
51 self.total = size;
52 self.used = 0;
53 let slice = core::ptr::slice_from_raw_parts_mut(start as *mut u8, size);
54 if let Some(nn) = NonNull::new(slice) {
55 self.tlsf.insert_free_block_ptr(nn);
56 }
57 }
58
59 unsafe fn alloc(&mut self, layout: Layout) -> *mut u8 {
60 match self.tlsf.allocate(layout) {
61 Some(p) => {
62 self.used = self.used.saturating_add(layout.size());
63 p.as_ptr()
64 }
65 None => {
66 crate::println!(
67 "[ALLOC FAIL] size={} align={} used={} total={}",
68 layout.size(),
69 layout.align(),
70 self.used,
71 self.total
72 );
73 null_mut()
74 }
75 }
76 }
77
78 unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
79 self.tlsf.deallocate(ptr, layout.align());
81 self.used = self.used.saturating_sub(layout.size());
82 }
83
84 fn free_space(&self) -> usize {
85 self.total.saturating_sub(self.used)
86 }
87}
88
89#[global_allocator]
91static ALLOCATOR: Locked<TlsfHeap> = Locked::new(TlsfHeap::empty());
92
93pub const KERNEL_HEAP_SIZE: usize = 512 * 1024 * 1024;
105
106static mut TOTAL_HEAP_SIZE: usize = 0;
108
109pub fn init(start: usize, size: usize) {
111 unsafe {
112 TOTAL_HEAP_SIZE = size;
113 ALLOCATOR.lock().init(start, size);
114 }
115}
116
117pub fn get_heap_stats() -> (usize, usize) {
121 let total = unsafe { TOTAL_HEAP_SIZE };
122 let free = ALLOCATOR.lock().free_space();
123 (total.saturating_sub(free), total)
124}
125
126pub fn check_heap_integrity() -> bool {
131 false
132}
133
134pub fn force_release_lock(cid: i16) {
137 unsafe {
138 ALLOCATOR.force_release_if_core(cid);
139 }
140}
141
142unsafe impl GlobalAlloc for Locked<TlsfHeap> {
143 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
144 self.lock().alloc(layout)
145 }
146
147 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
148 if let Some(nn) = NonNull::new(ptr) {
149 self.lock().dealloc(nn, layout);
150 }
151 }
152}
153
154pub struct Locked<A> {
161 inner: spin::Mutex<A>,
162 holder: core::sync::atomic::AtomicI16,
164}
165
166impl<A> Locked<A> {
167 pub const fn new(inner: A) -> Self {
169 Self {
170 inner: spin::Mutex::new(inner),
171 holder: core::sync::atomic::AtomicI16::new(-1),
172 }
173 }
174
175 pub fn lock(&self) -> LockedGuard<'_, A> {
189 let guard = self.inner.lock();
190 self.holder.store(
191 crate::kernel::scheduler::core_id() as i16,
192 Ordering::Relaxed,
193 );
194 LockedGuard {
195 guard: Some(guard),
196 holder: &self.holder,
197 }
198 }
199
200 pub unsafe fn force_release_if_core(&self, cid: i16) {
207 if self.holder.load(Ordering::Relaxed) == cid {
208 self.holder.store(-1, Ordering::Relaxed);
209 self.inner.force_unlock();
210 }
211 }
212}
213
214pub struct LockedGuard<'a, A> {
215 guard: Option<spin::MutexGuard<'a, A>>,
216 holder: &'a core::sync::atomic::AtomicI16,
217}
218
219impl<'a, A> Drop for LockedGuard<'a, A> {
220 fn drop(&mut self) {
221 self.holder.store(-1, Ordering::Relaxed);
222 self.guard.take(); }
224}
225
226impl<'a, A> core::ops::Deref for LockedGuard<'a, A> {
227 type Target = A;
228 fn deref(&self) -> &A {
229 match self.guard.as_ref() {
230 Some(g) => g,
231 None => loop {
232 core::hint::spin_loop();
233 },
234 }
235 }
236}
237
238impl<'a, A> core::ops::DerefMut for LockedGuard<'a, A> {
239 fn deref_mut(&mut self) -> &mut A {
240 match self.guard.as_mut() {
241 Some(g) => g,
242 None => loop {
243 core::hint::spin_loop();
244 },
245 }
246 }
247}
248
249mod spin {
254 use super::*;
255
256 pub struct Mutex<T> {
257 lock: AtomicBool,
258 data: core::cell::UnsafeCell<T>,
259 }
260
261 unsafe impl<T: Send> Sync for Mutex<T> {}
262 unsafe impl<T: Send> Send for Mutex<T> {}
263
264 pub struct MutexGuard<'a, T> {
265 mutex: &'a Mutex<T>,
266 interrupt_state: bool,
267 }
268
269 impl<T> Mutex<T> {
270 pub const fn new(value: T) -> Self {
271 Self {
272 lock: AtomicBool::new(false),
273 data: core::cell::UnsafeCell::new(value),
274 }
275 }
276
277 pub fn lock(&self) -> MutexGuard<'_, T> {
278 let irq_enabled = is_interrupt_enabled();
279 if irq_enabled {
280 disable_interrupts();
281 }
282
283 while self
284 .lock
285 .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed)
286 .is_err()
287 {
288 core::hint::spin_loop();
289 }
290
291 MutexGuard {
292 mutex: self,
293 interrupt_state: irq_enabled,
294 }
295 }
296
297 pub unsafe fn force_unlock(&self) {
303 self.lock.store(false, Ordering::Release);
304 }
305 }
306
307 impl<'a, T> core::ops::Deref for MutexGuard<'a, T> {
308 type Target = T;
309 fn deref(&self) -> &Self::Target {
310 unsafe { &*self.mutex.data.get() }
311 }
312 }
313
314 impl<'a, T> core::ops::DerefMut for MutexGuard<'a, T> {
315 fn deref_mut(&mut self) -> &mut Self::Target {
316 unsafe { &mut *self.mutex.data.get() }
317 }
318 }
319
320 impl<'a, T> Drop for MutexGuard<'a, T> {
321 fn drop(&mut self) {
322 self.mutex.lock.store(false, Ordering::Release);
323 if self.interrupt_state {
324 enable_interrupts();
325 }
326 }
327 }
328
329 pub(super) fn is_interrupt_enabled() -> bool {
330 let daif: u64;
331 unsafe {
332 core::arch::asm!("mrs {}, daif", out(reg) daif);
333 }
334 (daif & (1 << 7)) == 0
335 }
336
337 pub(super) fn disable_interrupts() {
338 unsafe {
339 core::arch::asm!("msr daifset, #2", options(nomem, nostack));
340 }
341 }
342
343 pub(super) fn enable_interrupts() {
344 unsafe {
345 core::arch::asm!("msr daifclr, #2", options(nomem, nostack));
346 }
347 }
348}