Skip to content

Commit 94a7332

Browse files
committed
zephyr: object: Add kboj_define support for arrays of stacks
Create a const constructor function for building the stack arrays. This requires unsafe, and can't use MaybeUninit, because the array version of this is still unsable. Just use zero initialization, and make sure the loop initializes everything. Use this function in the kobj_define macro in order to allow apps to define arrays of thread stacks, in addition to arrays of threads. Signed-off-by: David Brown <[email protected]>
1 parent e41de3a commit 94a7332

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

zephyr/src/object.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,17 @@ macro_rules! _kobj_stack {
302302
// to write a constructor for the array as a const fn, which would greatly simplify the
303303
// initialization here.
304304
($v:vis, $name: ident, $size:expr, $asize:expr) => {
305-
compile_error!("TODO: Stack initializer array");
306-
}
305+
$crate::paste! {
306+
// The actual stack itself goes into the no-init linker section. We'll use the user_name,
307+
// with _REAL appended, to indicate the real stack.
308+
#[link_section = concat!(".noinit.", stringify!($name), ".", file!(), line!())]
309+
$v static [< $name _REAL >]:
310+
[$crate::sys::thread::RealStaticThreadStack<{$crate::sys::thread::stack_len($size)}>; $asize] =
311+
unsafe { ::core::mem::zeroed() };
312+
313+
$v static $name:
314+
[$crate::_export::KStaticThreadStack; $asize] =
315+
$crate::_export::KStaticThreadStack::new_from_array(&[< $name _REAL >]);
316+
}
317+
};
307318
}

zephyr/src/sys/thread.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ extern crate alloc;
3838

3939
#[cfg(CONFIG_RUST_ALLOC)]
4040
use alloc::boxed::Box;
41-
use core::{cell::UnsafeCell, ffi::{c_int, c_void}};
41+
use core::{cell::UnsafeCell, ffi::{c_int, c_void}, mem};
4242

4343
use zephyr_sys::{
4444
k_thread,
@@ -137,6 +137,32 @@ impl StaticKernelObject<StaticThreadStack> {
137137
init: AtomicUsize::new(0),
138138
}
139139
}
140+
141+
/// Construct an array of StaticThreadStack kernel objects, based on the same sized array of the
142+
/// RealStaticThreadStack objects.
143+
///
144+
/// This is not intended to be directly called, but is used by the [`kobj_define`] macro.
145+
#[doc(hidden)]
146+
pub const fn new_from_array<const SZ: usize, const N: usize>(
147+
real: &[RealStaticThreadStack<SZ>; N],
148+
) -> [Self; N] {
149+
// Rustc currently doesn't support iterators in constant functions, but it does allow simple
150+
// looping. Since the value is not Copy, we need to use the MaybeUninit with a bit of
151+
// unsafe. This initialization is safe, as we loop through all of the entries, giving them
152+
// a value.
153+
//
154+
// In addition, MaybeUninit::uninit_array is not stable, so do this the old unsafe way.
155+
// let mut res: [MaybeUninit<Self>; N] = MaybeUninit::uninit_array();
156+
// Note that `mem::uninitialized` in addition to being deprecated, isn't const. But, since
157+
// this is a const computation, zero-filling shouldn't hurt anything.
158+
let mut res: [Self; N] = unsafe { mem::zeroed() };
159+
let mut i = 0;
160+
while i < N {
161+
res[i] = Self::new_from(&real[i]);
162+
i += 1;
163+
}
164+
res
165+
}
140166
}
141167

142168
/// A single Zephyr thread.

0 commit comments

Comments
 (0)