@@ -49,11 +49,16 @@ use portable_atomic::AtomicBool;
49
49
use portable_atomic_util:: Arc ;
50
50
use zephyr_sys:: {
51
51
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,
54
55
} ;
55
56
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
+ } ;
57
62
58
63
/// The WorkQueue decl args as a struct, so we can have a default, and the macro can fill in those
59
64
/// specified by the user.
@@ -348,7 +353,7 @@ pub trait SimpleAction {
348
353
/// Holds a `k_work`, along with the data associated with that work. When the work is queued, the
349
354
/// `act` method will be called on the provided `SimpleAction`.
350
355
pub struct Work < T > {
351
- work : UnsafeCell < k_work > ,
356
+ work : ZephyrObject < k_work > ,
352
357
action : T ,
353
358
}
354
359
@@ -380,12 +385,9 @@ impl<T: SimpleAction + Send> Work<T> {
380
385
where
381
386
P : SubmittablePointer < T > ,
382
387
{
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) ) } ;
389
391
390
392
this
391
393
}
@@ -453,7 +455,7 @@ impl<T: SimpleAction + Send> Work<T> {
453
455
pub trait SubmittablePointer < T > {
454
456
/// Create a new version of a pointer for this particular type. The pointer should be pinned
455
457
/// 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 ;
457
459
458
460
/// Given a raw pointer to the work_q burried within, recover the Self pointer containing our
459
461
/// data.
@@ -475,15 +477,21 @@ pub trait SubmittablePointer<T> {
475
477
}
476
478
477
479
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 } )
483
489
}
484
490
485
491
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 ( ) }
487
495
}
488
496
489
497
unsafe fn from_raw ( ptr : * const k_work ) -> Self {
@@ -530,6 +538,17 @@ impl<T: SimpleAction + Send> SubmittablePointer<T> for Pin<Arc<Work<T>>> {
530
538
}
531
539
}
532
540
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
+
533
552
/// Declare a static work queue.
534
553
///
535
554
/// This declares a static work queue (of type [`WorkQueueDecl`]). This will have a single method
0 commit comments