Skip to content

Commit f936c70

Browse files
committed
zephyr: work: Replace UnsafeCell with ZephyrObject
The ZephyrObject pairs the UnsafeCell with an atomic for initialization that allows for const constructors. Signed-off-by: David Brown <[email protected]>
1 parent 930242d commit f936c70

File tree

1 file changed

+36
-17
lines changed

1 file changed

+36
-17
lines changed

zephyr/src/work.rs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,16 @@ use portable_atomic::AtomicBool;
4949
use portable_atomic_util::Arc;
5050
use zephyr_sys::{
5151
k_poll_signal, k_poll_signal_check, k_poll_signal_init, k_poll_signal_raise,
52-
k_poll_signal_reset, k_work, k_work_init, k_work_q, k_work_queue_config, k_work_queue_init,
53-
k_work_queue_start, k_work_submit, k_work_submit_to_queue, z_thread_stack_element,
52+
k_poll_signal_reset, k_work, k_work_handler_t, k_work_init, k_work_q, k_work_queue_config,
53+
k_work_queue_init, k_work_queue_start, k_work_submit, k_work_submit_to_queue,
54+
z_thread_stack_element,
5455
};
5556

56-
use crate::{error::to_result_void, object::Fixed, simpletls::SimpleTls};
57+
use crate::{
58+
error::to_result_void,
59+
object::{Fixed, ObjectInit, ZephyrObject},
60+
simpletls::SimpleTls,
61+
};
5762

5863
/// The WorkQueue decl args as a struct, so we can have a default, and the macro can fill in those
5964
/// specified by the user.
@@ -348,7 +353,7 @@ pub trait SimpleAction {
348353
/// Holds a `k_work`, along with the data associated with that work. When the work is queued, the
349354
/// `act` method will be called on the provided `SimpleAction`.
350355
pub struct Work<T> {
351-
work: UnsafeCell<k_work>,
356+
work: ZephyrObject<k_work>,
352357
action: T,
353358
}
354359

@@ -380,12 +385,9 @@ impl<T: SimpleAction + Send> Work<T> {
380385
where
381386
P: SubmittablePointer<T>,
382387
{
383-
let this: P = unsafe { SubmittablePointer::new_ptr(action) };
384-
385-
// SAFETY: Initializes the above zero-initialized struct.
386-
unsafe {
387-
k_work_init(this.get_work(), Some(P::handler));
388-
}
388+
// SAFETY: Initializes the above zero-initialized struct. Initialization once is handled by
389+
// ZephyrObject.
390+
let this: P = unsafe { SubmittablePointer::new_ptr(action, Some(P::handler)) };
389391

390392
this
391393
}
@@ -453,7 +455,7 @@ impl<T: SimpleAction + Send> Work<T> {
453455
pub trait SubmittablePointer<T> {
454456
/// Create a new version of a pointer for this particular type. The pointer should be pinned
455457
/// after this call, and can then be initialized and used by C code.
456-
unsafe fn new_ptr(action: T) -> Self;
458+
unsafe fn new_ptr(action: T, handler: k_work_handler_t) -> Self;
457459

458460
/// Given a raw pointer to the work_q burried within, recover the Self pointer containing our
459461
/// data.
@@ -475,15 +477,21 @@ pub trait SubmittablePointer<T> {
475477
}
476478

477479
impl<T: SimpleAction + Send> SubmittablePointer<T> for Pin<Arc<Work<T>>> {
478-
unsafe fn new_ptr(action: T) -> Self {
479-
Arc::pin(Work {
480-
work: unsafe { mem::zeroed() },
481-
action,
482-
})
480+
unsafe fn new_ptr(action: T, handler: k_work_handler_t) -> Self {
481+
let work = <ZephyrObject<k_work>>::new_raw();
482+
483+
unsafe {
484+
let addr = work.get_uninit();
485+
(*addr).handler = handler;
486+
}
487+
488+
Arc::pin(Work { work, action })
483489
}
484490

485491
fn get_work(&self) -> *mut k_work {
486-
self.work.get()
492+
// SAFETY: The `get` method takes care of initialization as well as ensuring that the value
493+
// is not moved since the first initialization.
494+
unsafe { self.work.get() }
487495
}
488496

489497
unsafe fn from_raw(ptr: *const k_work) -> Self {
@@ -530,6 +538,17 @@ impl<T: SimpleAction + Send> SubmittablePointer<T> for Pin<Arc<Work<T>>> {
530538
}
531539
}
532540

541+
impl ObjectInit<k_work> for ZephyrObject<k_work> {
542+
fn init(item: *mut k_work) {
543+
// SAFETY: The handler was stashed in this field when constructing. At this point, the item
544+
// will be pinned.
545+
unsafe {
546+
let handler = (*item).handler;
547+
k_work_init(item, handler);
548+
}
549+
}
550+
}
551+
533552
/// Declare a static work queue.
534553
///
535554
/// This declares a static work queue (of type [`WorkQueueDecl`]). This will have a single method

0 commit comments

Comments
 (0)