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}