1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use core::alloc::{GlobalAlloc, Layout};
use core::ptr::NonNull;
use crate::kernel::{KERNEL, State};
use crate::alloc::allocator::Allocator;
use crate::{log, syscall};
use crate::sched;

pub struct Wrapper { }

impl Wrapper {
    pub(crate) const fn new() -> Self {
        Wrapper { }
    }

    pub(crate) fn alloc_handler(layout: Layout) -> *mut u8 {
        Self::with_allocator(|a| {
            match a {
                None => 0 as *mut _,
                Some(a) => {
                    match a.alloc(layout) {
                        Ok(mut addr) => unsafe { &mut addr.as_mut()[0] as *mut _ },
                        Err(_) => 0 as *mut _,
                    }
                }
            }
        })
    }

    pub(crate) fn dealloc_handler(ptr: *mut u8, layout: Layout) {
        Self::with_allocator(|a| {
            if let Some(alloc) = a {
                unsafe { alloc.dealloc(NonNull::new_unchecked(ptr), layout); }
            }
        })
    }

    fn with_allocator<F, R>(f: F) -> R
        where F: FnOnce(Option<&dyn Allocator>) -> R
    {
        match KERNEL.state() {
            // Kernel not started yet -> get allocator from process context.
            State::Startup => {
                match KERNEL.process() {
                    None => {
                        log::error!("Cannot allocate memory outside process.");
                        f(None)
                    },
                    Some(p) => {
                        f(Some(p.allocator()))
                    }
                }
            }
            // Kernel is already running -> get allocator from active thread
            State::Running => {
                sched::with_callee(|t| {
                    f(Some(t.process().allocator()))
                })
            }
        }
    }
}

unsafe impl GlobalAlloc for Wrapper {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        syscall::alloc(layout)
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        syscall::dealloc(ptr, layout)
    }
}