Skip to content

Commit c1fd526

Browse files
committed
zephyr-core: k_poll and k_poll_signal
1 parent 0582896 commit c1fd526

File tree

4 files changed

+251
-3
lines changed

4 files changed

+251
-3
lines changed

rust/zephyr-core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub mod kobj;
88
pub mod memdomain;
99
pub mod mempool;
1010
pub mod mutex;
11+
pub mod poll;
12+
mod poll_signal;
1113
pub mod semaphore;
1214
pub mod thread;
1315
mod time;

rust/zephyr-core/src/poll.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use libc::{c_int, c_void};
2+
use zephyr_sys::raw::{
3+
_poll_types_bits__POLL_TYPE_SEM_AVAILABLE, _poll_types_bits__POLL_TYPE_SIGNAL, k_poll_event,
4+
k_poll_modes_K_POLL_MODE_NOTIFY_ONLY, K_POLL_TYPE_IGNORE,
5+
};
6+
7+
use crate::kobj::*;
8+
use crate::semaphore::KSem;
9+
use crate::time::DurationMs;
10+
use crate::NegErr;
11+
12+
pub use crate::poll_signal::*;
13+
14+
pub type KPollEvent = k_poll_event;
15+
16+
pub unsafe trait PollableKobj: KObj {
17+
const POLL_TYPE: u32;
18+
}
19+
20+
unsafe impl PollableKobj for KSem {
21+
const POLL_TYPE: u32 = 1 << (_poll_types_bits__POLL_TYPE_SEM_AVAILABLE - 1);
22+
}
23+
24+
unsafe impl PollableKobj for KPollSignal {
25+
const POLL_TYPE: u32 = 1 << (_poll_types_bits__POLL_TYPE_SIGNAL - 1);
26+
}
27+
28+
#[repr(u32)]
29+
pub enum PollMode {
30+
NotifyOnly = k_poll_modes_K_POLL_MODE_NOTIFY_ONLY,
31+
}
32+
33+
pub trait PollEventFuncs {
34+
fn new() -> Self;
35+
36+
fn init<'e, 'o: 'e, O: PollableKobj>(&'e mut self, kobj: &'o O, mode: PollMode);
37+
}
38+
39+
impl PollEventFuncs for KPollEvent {
40+
fn new() -> Self {
41+
unsafe {
42+
let mut event = core::mem::uninitialized();
43+
zephyr_sys::raw::k_poll_event_init(
44+
&mut event,
45+
K_POLL_TYPE_IGNORE,
46+
0,
47+
1 as *const c_void as *mut c_void, // Must not be null, but won't be touched by the kernel because type is IGNORE
48+
);
49+
event
50+
}
51+
}
52+
53+
fn init<'e, 'o: 'e, O: PollableKobj>(&'e mut self, kobj: &'o O, mode: PollMode) {
54+
unsafe {
55+
zephyr_sys::raw::k_poll_event_init(
56+
self,
57+
O::POLL_TYPE,
58+
mode as c_int,
59+
kobj.as_void_ptr(),
60+
)
61+
}
62+
}
63+
}
64+
65+
pub trait PollSyscalls {
66+
fn k_poll(events: &mut [KPollEvent], timeout: DurationMs) -> c_int;
67+
}
68+
69+
macro_rules! trait_impl {
70+
($context:ident, $context_struct:path) => {
71+
impl PollSyscalls for $context_struct {
72+
fn k_poll(events: &mut [KPollEvent], timeout: DurationMs) -> c_int {
73+
unsafe {
74+
zephyr_sys::syscalls::$context::k_poll(
75+
events.as_mut_ptr(),
76+
events.len() as c_int,
77+
timeout.into(),
78+
)
79+
}
80+
}
81+
}
82+
};
83+
}
84+
85+
trait_impl!(kernel, crate::context::Kernel);
86+
trait_impl!(user, crate::context::User);
87+
trait_impl!(any, crate::context::Any);
88+
89+
#[derive(Clone, Copy, Debug)]
90+
pub enum PollError {
91+
Canceled,
92+
}
93+
94+
pub trait PollEventsFuncs {
95+
fn poll<C: PollSyscalls>(&mut self) -> Result<(), PollError>;
96+
/// Returns true if events are ready, false if timeout.
97+
fn poll_timeout<C: PollSyscalls>(&mut self, timeout: DurationMs) -> Result<bool, PollError>;
98+
}
99+
100+
impl PollEventsFuncs for [KPollEvent] {
101+
fn poll<C: PollSyscalls>(&mut self) -> Result<(), PollError> {
102+
match C::k_poll(self, zephyr_sys::raw::K_FOREVER.into()).neg_err() {
103+
Ok(_) => Ok(()),
104+
Err(zephyr_sys::raw::EINTR) => Err(PollError::Canceled),
105+
Err(zephyr_sys::raw::ENOMEM) => panic!("k_poll OOM"),
106+
Err(e) => panic!("k_poll error {}", e),
107+
}
108+
}
109+
110+
fn poll_timeout<C: PollSyscalls>(&mut self, timeout: DurationMs) -> Result<bool, PollError> {
111+
match C::k_poll(self, timeout).neg_err() {
112+
Ok(_) => Ok(true),
113+
Err(zephyr_sys::raw::EAGAIN) => Ok(false),
114+
Err(zephyr_sys::raw::EINTR) => Err(PollError::Canceled),
115+
Err(zephyr_sys::raw::ENOMEM) => panic!("k_poll OOM"),
116+
Err(e) => panic!("k_poll error {}", e),
117+
}
118+
}
119+
}

rust/zephyr-core/src/poll_signal.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
use libc::{c_int, c_uint};
2+
3+
use crate::kobj::*;
4+
5+
pub use zephyr_sys::raw::k_poll_signal as KPollSignal;
6+
7+
unsafe impl KObj for KPollSignal {}
8+
9+
crate::make_static_wrapper!(k_poll_signal, zephyr_sys::raw::k_poll_signal);
10+
11+
pub trait KPollSignalSyscalls {
12+
unsafe fn k_poll_signal_init(signal: &KPollSignal);
13+
fn k_poll_signal_reset(signal: &KPollSignal);
14+
fn k_poll_signal_check(signal: &KPollSignal, signaled: &mut c_uint, result: &mut c_int);
15+
fn k_poll_signal_raise(signal: &KPollSignal, result: c_int) -> c_int;
16+
}
17+
18+
macro_rules! trait_impl {
19+
($context:ident, $context_struct:path) => {
20+
impl KPollSignalSyscalls for $context_struct {
21+
unsafe fn k_poll_signal_init(signal: &KPollSignal) {
22+
zephyr_sys::syscalls::$context::k_poll_signal_init(signal as *const _ as *mut _)
23+
}
24+
25+
fn k_poll_signal_reset(signal: &KPollSignal) {
26+
unsafe {
27+
zephyr_sys::syscalls::$context::k_poll_signal_reset(
28+
signal as *const _ as *mut _,
29+
)
30+
}
31+
}
32+
33+
fn k_poll_signal_check(
34+
signal: &KPollSignal,
35+
signaled: &mut c_uint,
36+
result: &mut c_int,
37+
) {
38+
unsafe {
39+
zephyr_sys::syscalls::$context::k_poll_signal_check(
40+
signal as *const _ as *mut _,
41+
signaled,
42+
result,
43+
)
44+
}
45+
}
46+
47+
fn k_poll_signal_raise(signal: &KPollSignal, result: c_int) -> c_int {
48+
unsafe {
49+
zephyr_sys::syscalls::$context::k_poll_signal_raise(
50+
signal as *const _ as *mut _,
51+
result,
52+
)
53+
}
54+
}
55+
}
56+
};
57+
}
58+
59+
trait_impl!(kernel, crate::context::Kernel);
60+
trait_impl!(user, crate::context::User);
61+
trait_impl!(any, crate::context::Any);
62+
63+
pub trait Signal {
64+
unsafe fn init<C: KPollSignalSyscalls>(&self);
65+
fn reset<C: KPollSignalSyscalls>(&self);
66+
fn check<C: KPollSignalSyscalls>(&self) -> Option<c_int>;
67+
fn raise<C: KPollSignalSyscalls>(&self, result: c_int);
68+
}
69+
70+
impl Signal for KPollSignal {
71+
unsafe fn init<C: KPollSignalSyscalls>(&self) {
72+
C::k_poll_signal_init(self)
73+
}
74+
75+
fn reset<C: KPollSignalSyscalls>(&self) {
76+
C::k_poll_signal_reset(self)
77+
}
78+
79+
fn check<C: KPollSignalSyscalls>(&self) -> Option<c_int> {
80+
let mut signaled = 0;
81+
let mut result = 0;
82+
C::k_poll_signal_check(self, &mut signaled, &mut result);
83+
if signaled != 0 {
84+
Some(result)
85+
} else {
86+
None
87+
}
88+
}
89+
90+
fn raise<C: KPollSignalSyscalls>(&self, result: c_int) {
91+
C::k_poll_signal_raise(self, result);
92+
}
93+
}

rust/zephyr-macros/src/lib.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ use proc_macro::TokenStream;
44
use proc_macro2::{Ident, Literal, TokenTree};
55
use quote::quote;
66

7-
#[proc_macro]
8-
pub fn k_mutex_define(item: TokenStream) -> TokenStream {
7+
fn get_single_arg(item: TokenStream) -> Ident {
98
let item = proc_macro2::TokenStream::from(item);
109
let arg = item.into_iter().next();
1110
let ident = if let Some(TokenTree::Ident(ident)) = arg {
1211
ident
1312
} else {
1413
panic!(
15-
"k_mutex_define takes one identifier argument. Got {:?}",
14+
"k_*_define takes one identifier argument. Got {:?}",
1615
arg
1716
);
1817
};
18+
ident
19+
}
1920

21+
#[proc_macro]
22+
pub fn k_mutex_define(item: TokenStream) -> TokenStream {
23+
let ident = get_single_arg(item);
2024
let section = Literal::string(&format!("._k_mutex.static.{}", ident));
2125
let ctor = Ident::new(&format!("_rust_mutex_init_{}", ident), ident.span());
2226
let ctor_ptr = Ident::new(&format!("_ctor_rust_mutex_init_{}", ident), ident.span());
@@ -42,6 +46,36 @@ pub fn k_mutex_define(item: TokenStream) -> TokenStream {
4246
expanded.into()
4347
}
4448

49+
#[proc_macro]
50+
pub fn k_poll_signal_define(item: TokenStream) -> TokenStream {
51+
let ident = get_single_arg(item);
52+
// Using mutex section because there is not one for poll_signal. Need to
53+
// ensure this is in kernel memory.
54+
let section = Literal::string(&format!("._k_mutex.static.{}", ident));
55+
let ctor = Ident::new(&format!("_rust_poll_signal_init_{}", ident), ident.span());
56+
let ctor_ptr = Ident::new(&format!("_ctor_rust_poll_signal_init_{}", ident), ident.span());
57+
let expanded = quote! {
58+
// The static storage for the object, itself
59+
#[link_section = #section]
60+
static #ident: zephyr::poll::global::k_poll_signal = unsafe { zephyr::poll::global::k_poll_signal::uninit() };
61+
62+
// A constructor function that calls its init
63+
#[allow(non_snake_case)]
64+
extern "C" fn #ctor() {
65+
use zephyr::poll::*;
66+
unsafe { #ident.init::<zephyr::context::Kernel>() }
67+
}
68+
69+
// Add a pointer to the constructor to .ctors table
70+
#[used]
71+
#[link_section = ".ctors"]
72+
#[allow(non_upper_case_globals)]
73+
static #ctor_ptr: extern "C" fn() = #ctor;
74+
};
75+
76+
expanded.into()
77+
}
78+
4579
fn get_sem_args(item: TokenStream) -> Option<(Ident, Literal, Literal)> {
4680
let item = proc_macro2::TokenStream::from(item);
4781
let mut iter = item.into_iter();

0 commit comments

Comments
 (0)