1
1
//! An embassy executor tailored for Zephyr
2
2
3
- use core:: { marker:: PhantomData , sync :: atomic :: Ordering } ;
3
+ use core:: marker:: PhantomData ;
4
4
5
+ use crate :: sys:: sync:: Semaphore ;
6
+ use crate :: time:: Forever ;
5
7
use embassy_executor:: { raw, Spawner } ;
6
- use zephyr_sys:: { k_current_get, k_thread_resume, k_thread_suspend, k_tid_t} ;
7
-
8
- use crate :: sync:: atomic:: AtomicBool ;
9
8
10
9
/// Zephyr-thread based executor.
11
10
pub struct Executor {
12
11
inner : Option < raw:: Executor > ,
13
- id : k_tid_t ,
14
- pend : AtomicBool ,
12
+ poll_needed : Semaphore ,
15
13
not_send : PhantomData < * mut ( ) > ,
16
14
}
17
15
18
16
impl Executor {
19
17
/// Create a new Executor.
20
18
pub fn new ( ) -> Self {
21
- let id = unsafe { k_current_get ( ) } ;
22
-
23
19
Self {
24
20
inner : None ,
25
- pend : AtomicBool :: new ( false ) ,
26
- id,
21
+ poll_needed : Semaphore :: new ( 0 , 1 ) ,
27
22
not_send : PhantomData ,
28
23
}
29
24
}
@@ -36,17 +31,13 @@ impl Executor {
36
31
init ( inner. spawner ( ) ) ;
37
32
38
33
loop {
34
+ let _ = self . poll_needed . take ( Forever ) ;
39
35
unsafe {
40
36
// The raw executor's poll only runs things that were queued _before_ this poll
41
37
// itself is actually run. This means, specifically, that if the polled execution
42
38
// causes this, or other threads to enqueue, this will return without running them.
43
- // `__pender` _will_ be called, but it isn't "sticky" like `wfe/sev` are. To
44
- // simulate this, we will use the 'pend' atomic to count
39
+ // `__pender` _will_ be called, so the next time around the semaphore will be taken.
45
40
inner. poll ( ) ;
46
- if !self . pend . swap ( false , Ordering :: SeqCst ) {
47
- // printkln!("_suspend");
48
- k_thread_suspend ( k_current_get ( ) ) ;
49
- }
50
41
}
51
42
}
52
43
}
@@ -61,20 +52,7 @@ impl Default for Executor {
61
52
#[ export_name = "__pender" ]
62
53
fn __pender ( context : * mut ( ) ) {
63
54
unsafe {
64
- let myself = k_current_get ( ) ;
65
-
66
55
let this = context as * const Executor ;
67
- let other = ( * this) . id ;
68
-
69
- // If the other is a different thread, resume it.
70
- if other != myself {
71
- // printkln!("_resume");
72
- k_thread_resume ( other) ;
73
- }
74
- // Otherwise, we need to make sure our own next suspend doesn't happen.
75
- // We need to also prevent a suspend from happening in the case where the only running
76
- // thread causes other work to become pending. The resume below will do nothing, as we
77
- // are just running.
78
- ( * this) . pend . store ( true , Ordering :: SeqCst ) ;
56
+ ( * this) . poll_needed . give ( ) ;
79
57
}
80
58
}
0 commit comments