Skip to content

Commit b86831b

Browse files
committed
zephyr: sys: sync: Make Semaphore constructors const
Move Semaphores to the new `ZephyrObject` system, allowing the constructor to be const. Unfortunately, `Result` isn't generally useful with const, and as such, this changes the API for `Semaphore::new()` to just return the semaphore instead of a Result. Instead, if a semaphore constructor has inconsitent arguments, it will panic. Given that semaphore constructors are generally quite simple, this is a minor issue. However, it will involve removing a lot of `.unwrap()` or `.expect(...)` calls on semaphores. The samples have been changed for the API change, but mostly not changed to take advantage of the easier ways to use them. It is generally no longer necessary to put semaphores in an Arc or Rc, but just to allocate them in something like a StaticCell, and then pass them around by reference. Signed-off-by: David Brown <[email protected]>
1 parent a745ecd commit b86831b

File tree

7 files changed

+55
-65
lines changed

7 files changed

+55
-65
lines changed

samples/philosophers/src/dynsemsync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl ForkSync for SemSync {
3535
pub fn dyn_semaphore_sync() -> Vec<Arc<dyn ForkSync>> {
3636
let forks = [(); NUM_PHIL]
3737
.each_ref()
38-
.map(|()| Arc::new(Semaphore::new(1, 1).unwrap()));
38+
.map(|()| Arc::new(Semaphore::new(1, 1)));
3939

4040
(0..NUM_PHIL)
4141
.map(|_| {

samples/philosophers/src/semsync.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ extern crate alloc;
1010
use alloc::boxed::Box;
1111
use alloc::vec::Vec;
1212

13-
use zephyr::{kobj_define, sync::Arc, sys::sync::Semaphore, time::Forever};
13+
use zephyr::{sync::Arc, sys::sync::Semaphore, time::Forever};
1414

1515
use crate::{ForkSync, NUM_PHIL};
1616

1717
#[derive(Debug)]
1818
pub struct SemSync {
1919
/// The forks for this philosopher. This is a big excessive, as we really don't need all of
2020
/// them, but the ForSync code uses the index here.
21-
forks: [Arc<Semaphore>; NUM_PHIL],
21+
forks: &'static [Semaphore; NUM_PHIL],
2222
}
2323

2424
impl ForkSync for SemSync {
@@ -33,22 +33,15 @@ impl ForkSync for SemSync {
3333

3434
#[allow(dead_code)]
3535
pub fn semaphore_sync() -> Vec<Arc<dyn ForkSync>> {
36-
let forks = SEMS.each_ref().map(|m| {
37-
// Each fork starts as taken.
38-
Arc::new(m.init_once((1, 1)).unwrap())
39-
});
40-
4136
(0..NUM_PHIL)
4237
.map(|_| {
43-
let syncer = SemSync {
44-
forks: forks.clone(),
45-
};
38+
let syncer = SemSync { forks: &SEMS };
4639
let item = Box::new(syncer) as Box<dyn ForkSync>;
4740
Arc::from(item)
4841
})
4942
.collect()
5043
}
5144

52-
kobj_define! {
53-
static SEMS: [StaticSemaphore; NUM_PHIL];
54-
}
45+
// The state of const array initialization in rust as dreadful. There is array-init, which isn't
46+
// const, and there is array-const-fn-init, which, for some reason is a proc macro.
47+
static SEMS: [Semaphore; NUM_PHIL] = [const { Semaphore::new(1, 1) }; NUM_PHIL];

samples/work-philosophers/src/async_sem.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async fn local_phil() -> Stats {
4343

4444
// One fork for each philospher.
4545
let forks: Vec<_> = (0..NUM_PHIL)
46-
.map(|_| Rc::new(Semaphore::new(1, 1).unwrap()))
46+
.map(|_| Rc::new(Semaphore::new(1, 1)))
4747
.collect();
4848

4949
// Create all of the philosphers

zephyr/src/kio/sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl<T> Mutex<T> {
6262
/// Construct a new Mutex.
6363
pub fn new(t: T) -> Mutex<T> {
6464
Mutex {
65-
inner: Semaphore::new(1, 1).unwrap(),
65+
inner: Semaphore::new(1, 1),
6666
data: UnsafeCell::new(t),
6767
}
6868
}

zephyr/src/sys/sync.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ pub mod mutex;
3434
pub mod semaphore;
3535

3636
pub use mutex::{Condvar, Mutex, StaticCondvar, StaticMutex};
37-
pub use semaphore::{Semaphore, StaticSemaphore};
37+
pub use semaphore::Semaphore;

zephyr/src/sys/sync/semaphore.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use core::fmt;
1616
#[cfg(CONFIG_RUST_ALLOC)]
1717
use core::future::Future;
1818
#[cfg(CONFIG_RUST_ALLOC)]
19-
use core::mem;
20-
#[cfg(CONFIG_RUST_ALLOC)]
2119
use core::pin::Pin;
2220
#[cfg(CONFIG_RUST_ALLOC)]
2321
use core::task::{Context, Poll};
@@ -27,22 +25,19 @@ use zephyr_sys::ETIMEDOUT;
2725

2826
#[cfg(CONFIG_RUST_ALLOC)]
2927
use crate::kio::ContextExt;
28+
use crate::object::{ObjectInit, ZephyrObject};
3029
#[cfg(CONFIG_RUST_ALLOC)]
3130
use crate::time::NoWait;
3231
use crate::{
3332
error::{to_result_void, Result},
34-
object::{Fixed, StaticKernelObject, Wrapped},
3533
raw::{k_sem, k_sem_count_get, k_sem_give, k_sem_init, k_sem_reset, k_sem_take},
3634
time::Timeout,
3735
};
3836

3937
pub use crate::raw::K_SEM_MAX_LIMIT;
4038

41-
/// A zephyr `k_sem` usable from safe Rust code.
42-
pub struct Semaphore {
43-
/// The raw Zephyr `k_sem`.
44-
pub(crate) item: Fixed<k_sem>,
45-
}
39+
/// General Zephyr Semaphores
40+
pub struct Semaphore(pub(crate) ZephyrObject<k_sem>);
4641

4742
/// By nature, Semaphores are both Sync and Send. Safety is handled by the underlying Zephyr
4843
/// implementation (which is why Clone is also implemented).
@@ -55,13 +50,27 @@ impl Semaphore {
5550
/// Create a new dynamically allocated Semaphore. This semaphore can only be used from system
5651
/// threads. The arguments are as described in [the
5752
/// docs](https://docs.zephyrproject.org/latest/kernel/services/synchronization/semaphores.html).
53+
///
54+
/// Note that this API has changed, and it now doesn't return a Result, since the Result time
55+
/// generally doesn't work (in stable rust) with const.
5856
#[cfg(CONFIG_RUST_ALLOC)]
59-
pub fn new(initial_count: c_uint, limit: c_uint) -> Result<Semaphore> {
60-
let item: Fixed<k_sem> = Fixed::new(unsafe { mem::zeroed() });
57+
pub const fn new(initial_count: c_uint, limit: c_uint) -> Semaphore {
58+
// Due to delayed init, we need to replicate the object checks in the C `k_sem_init`.
59+
60+
if limit == 0 || initial_count > limit {
61+
panic!("Invalid semaphore initialization");
62+
}
63+
64+
let this = <ZephyrObject<k_sem>>::new_raw();
65+
6166
unsafe {
62-
to_result_void(k_sem_init(item.get(), initial_count, limit))?;
67+
let addr = this.get_uninit();
68+
(*addr).count = initial_count;
69+
(*addr).limit = limit;
6370
}
64-
Ok(Semaphore { item })
71+
72+
// to_result_void(k_sem_init(item.get(), initial_count, limit))?;
73+
Semaphore(this)
6574
}
6675

6776
/// Take a semaphore.
@@ -74,7 +83,7 @@ impl Semaphore {
7483
T: Into<Timeout>,
7584
{
7685
let timeout: Timeout = timeout.into();
77-
let ret = unsafe { k_sem_take(self.item.get(), timeout.0) };
86+
let ret = unsafe { k_sem_take(self.0.get(), timeout.0) };
7887
to_result_void(ret)
7988
}
8089

@@ -98,7 +107,7 @@ impl Semaphore {
98107
/// This routine gives to the semaphore, unless the semaphore is already at its maximum
99108
/// permitted count.
100109
pub fn give(&self) {
101-
unsafe { k_sem_give(self.item.get()) }
110+
unsafe { k_sem_give(self.0.get()) }
102111
}
103112

104113
/// Resets a semaphor's count to zero.
@@ -108,14 +117,32 @@ impl Semaphore {
108117
///
109118
/// [`take`]: Self::take
110119
pub fn reset(&self) {
111-
unsafe { k_sem_reset(self.item.get()) }
120+
unsafe { k_sem_reset(self.0.get()) }
112121
}
113122

114123
/// Get a semaphore's count.
115124
///
116125
/// Returns the current count.
117126
pub fn count_get(&self) -> usize {
118-
unsafe { k_sem_count_get(self.item.get()) as usize }
127+
unsafe { k_sem_count_get(self.0.get()) as usize }
128+
}
129+
}
130+
131+
impl ObjectInit<k_sem> for ZephyrObject<k_sem> {
132+
fn init(item: *mut k_sem) {
133+
// SAFEFY: Get the initial values used in new. The address may have changed, but only due
134+
// to a move.
135+
unsafe {
136+
let count = (*item).count;
137+
let limit = (*item).limit;
138+
139+
if k_sem_init(item, count, limit) != 0 {
140+
// Note that with delayed init, we cannot do anything with invalid values. We're
141+
// replicated the check in `new` above, so would only catch semantic changes in the
142+
// implementation of `k_sem_init`.
143+
unreachable!();
144+
}
145+
}
119146
}
120147
}
121148

@@ -153,36 +180,6 @@ impl<'a> Future for SemTake<'a> {
153180
}
154181
}
155182

156-
/// A static Zephyr `k_sem`.
157-
///
158-
/// This is intended to be used from within the `kobj_define!` macro. It declares a static ksem
159-
/// that will be properly registered with the Zephyr kernel object system. Call [`init_once`] to
160-
/// get the [`Semaphore`] that is represents.
161-
///
162-
/// [`init_once`]: StaticKernelObject::init_once
163-
pub type StaticSemaphore = StaticKernelObject<k_sem>;
164-
165-
unsafe impl Sync for StaticSemaphore {}
166-
167-
impl Wrapped for StaticKernelObject<k_sem> {
168-
type T = Semaphore;
169-
170-
/// The initializer for Semaphores is the initial count, and the count limit (which can be
171-
/// K_SEM_MAX_LIMIT, re-exported here.
172-
type I = (c_uint, c_uint);
173-
174-
// TODO: Thoughts about how to give parameters to the initialzation.
175-
fn get_wrapped(&self, arg: Self::I) -> Semaphore {
176-
let ptr = self.value.get();
177-
unsafe {
178-
k_sem_init(ptr, arg.0, arg.1);
179-
}
180-
Semaphore {
181-
item: Fixed::Static(ptr),
182-
}
183-
}
184-
}
185-
186183
impl fmt::Debug for Semaphore {
187184
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188185
write!(f, "sys::Semaphore")

zephyr/src/work/futures.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ impl<T> Answer<T> {
6868
pub fn new() -> Self {
6969
Self {
7070
item: Mutex::new(None),
71-
wake: Semaphore::new(0, 1).expect("Initialize semaphore"),
71+
wake: Semaphore::new(0, 1),
7272
}
7373
}
7474

@@ -307,7 +307,7 @@ impl WakeInfo {
307307
ev.get(),
308308
ZR_POLL_TYPE_SEM_AVAILABLE,
309309
k_poll_modes_K_POLL_MODE_NOTIFY_ONLY as i32,
310-
sem.item.get() as *mut c_void,
310+
sem.0.get() as *mut c_void,
311311
);
312312
}
313313
}

0 commit comments

Comments
 (0)