1use core::alloc::Layout;
4use core::mem::{align_of, size_of};
5
6#[unsafe(no_mangle)]
7#[linkage = "weak"]
8static __AX_TASK_EXT_SIZE: usize = 0;
9
10#[unsafe(no_mangle)]
11#[linkage = "weak"]
12static __AX_TASK_EXT_ALIGN: usize = 0;
13
14#[unsafe(no_mangle)]
15#[linkage = "weak"]
16fn __ax_task_ext_drop(_data: *mut u8) {}
17
18pub(crate) struct AxTaskExt {
20    ptr: *mut u8,
21}
22
23impl AxTaskExt {
24    pub fn size() -> usize {
26        unsafe extern "C" {
27            static __AX_TASK_EXT_SIZE: usize;
28        }
29        unsafe { __AX_TASK_EXT_SIZE }
30    }
31
32    pub fn align() -> usize {
34        unsafe extern "C" {
35            static __AX_TASK_EXT_ALIGN: usize;
36        }
37        unsafe { __AX_TASK_EXT_ALIGN }
38    }
39
40    pub const fn empty() -> Self {
43        Self {
44            ptr: core::ptr::null_mut(),
45        }
46    }
47
48    pub const fn is_empty(&self) -> bool {
50        self.ptr.is_null()
51    }
52
53    pub unsafe fn uninited() -> Self {
56        let size = Self::size();
57        let align = Self::align();
58        let ptr = if size == 0 {
59            core::ptr::null_mut()
60        } else {
61            let layout = Layout::from_size_align(size, align).unwrap();
62            unsafe { alloc::alloc::alloc(layout) }
63        };
64        Self { ptr }
65    }
66
67    pub const fn as_ptr(&self) -> *mut u8 {
69        self.ptr
70    }
71
72    pub fn write<T: Sized>(&mut self, data: T) -> Option<&mut T> {
81        let data_size = size_of::<T>();
82        let data_align = align_of::<T>();
83        if data_size != Self::size() {
84            panic!("size mismatch: {} != {}", data_size, Self::size());
85        }
86        if data_align != Self::align() {
87            panic!("align mismatch: {} != {}", data_align, Self::align());
88        }
89
90        if self.ptr.is_null() {
91            *self = unsafe { Self::uninited() };
92        }
93        if data_size > 0 {
94            let ptr = self.ptr as *mut T;
95            assert!(!ptr.is_null());
96            unsafe {
97                ptr.write(data);
98                Some(&mut *ptr)
99            }
100        } else {
101            None
102        }
103    }
104}
105
106impl Drop for AxTaskExt {
107    fn drop(&mut self) {
108        if !self.ptr.is_null() {
109            unsafe extern "C" {
110                fn __ax_task_ext_drop(data: *mut u8);
111            }
112            unsafe { __ax_task_ext_drop(self.ptr) };
113
114            let layout = Layout::from_size_align(Self::size(), Self::align()).unwrap();
115            unsafe { alloc::alloc::dealloc(self.ptr, layout) };
116        }
117    }
118}
119
120pub trait TaskExtRef<T: Sized> {
125    fn task_ext(&self) -> &T;
127}
128
129pub trait TaskExtMut<T: Sized> {
134    fn task_ext_mut(&mut self) -> &mut T;
136}
137
138#[macro_export]
168macro_rules! def_task_ext {
169    ($task_ext_struct:ty) => {
170        #[unsafe(no_mangle)]
171        static __AX_TASK_EXT_SIZE: usize = ::core::mem::size_of::<$task_ext_struct>();
172
173        #[unsafe(no_mangle)]
174        static __AX_TASK_EXT_ALIGN: usize = ::core::mem::align_of::<$task_ext_struct>();
175
176        #[unsafe(no_mangle)]
177        fn __ax_task_ext_drop(data: *mut u8) {
178            unsafe { core::ptr::drop_in_place(data as *mut $task_ext_struct) };
179        }
180
181        impl $crate::TaskExtRef<$task_ext_struct> for $crate::TaskInner {
182            fn task_ext(&self) -> &$task_ext_struct {
183                unsafe {
184                    let ptr = self.task_ext_ptr() as *const $task_ext_struct;
185                    assert!(!ptr.is_null());
186                    &*ptr
187                }
188            }
189        }
190
191        impl $crate::TaskExtMut<$task_ext_struct> for $crate::TaskInner {
192            fn task_ext_mut(&mut self) -> &mut $task_ext_struct {
193                unsafe {
194                    let ptr = self.task_ext_ptr() as *mut $task_ext_struct;
195                    assert!(!ptr.is_null());
196                    &mut *ptr
197                }
198            }
199        }
200    };
201}