@@ -16,8 +16,6 @@ use core::fmt;
16
16
#[ cfg( CONFIG_RUST_ALLOC ) ]
17
17
use core:: future:: Future ;
18
18
#[ cfg( CONFIG_RUST_ALLOC ) ]
19
- use core:: mem;
20
- #[ cfg( CONFIG_RUST_ALLOC ) ]
21
19
use core:: pin:: Pin ;
22
20
#[ cfg( CONFIG_RUST_ALLOC ) ]
23
21
use core:: task:: { Context , Poll } ;
@@ -27,22 +25,19 @@ use zephyr_sys::ETIMEDOUT;
27
25
28
26
#[ cfg( CONFIG_RUST_ALLOC ) ]
29
27
use crate :: kio:: ContextExt ;
28
+ use crate :: object:: { ObjectInit , ZephyrObject } ;
30
29
#[ cfg( CONFIG_RUST_ALLOC ) ]
31
30
use crate :: time:: NoWait ;
32
31
use crate :: {
33
32
error:: { to_result_void, Result } ,
34
- object:: { Fixed , StaticKernelObject , Wrapped } ,
35
33
raw:: { k_sem, k_sem_count_get, k_sem_give, k_sem_init, k_sem_reset, k_sem_take} ,
36
34
time:: Timeout ,
37
35
} ;
38
36
39
37
pub use crate :: raw:: K_SEM_MAX_LIMIT ;
40
38
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 > ) ;
46
41
47
42
/// By nature, Semaphores are both Sync and Send. Safety is handled by the underlying Zephyr
48
43
/// implementation (which is why Clone is also implemented).
@@ -55,13 +50,27 @@ impl Semaphore {
55
50
/// Create a new dynamically allocated Semaphore. This semaphore can only be used from system
56
51
/// threads. The arguments are as described in [the
57
52
/// 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.
58
56
#[ 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
+
61
66
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;
63
70
}
64
- Ok ( Semaphore { item } )
71
+
72
+ // to_result_void(k_sem_init(item.get(), initial_count, limit))?;
73
+ Semaphore ( this)
65
74
}
66
75
67
76
/// Take a semaphore.
@@ -74,7 +83,7 @@ impl Semaphore {
74
83
T : Into < Timeout > ,
75
84
{
76
85
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 ) } ;
78
87
to_result_void ( ret)
79
88
}
80
89
@@ -98,7 +107,7 @@ impl Semaphore {
98
107
/// This routine gives to the semaphore, unless the semaphore is already at its maximum
99
108
/// permitted count.
100
109
pub fn give ( & self ) {
101
- unsafe { k_sem_give ( self . item . get ( ) ) }
110
+ unsafe { k_sem_give ( self . 0 . get ( ) ) }
102
111
}
103
112
104
113
/// Resets a semaphor's count to zero.
@@ -108,14 +117,32 @@ impl Semaphore {
108
117
///
109
118
/// [`take`]: Self::take
110
119
pub fn reset ( & self ) {
111
- unsafe { k_sem_reset ( self . item . get ( ) ) }
120
+ unsafe { k_sem_reset ( self . 0 . get ( ) ) }
112
121
}
113
122
114
123
/// Get a semaphore's count.
115
124
///
116
125
/// Returns the current count.
117
126
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
+ }
119
146
}
120
147
}
121
148
@@ -153,36 +180,6 @@ impl<'a> Future for SemTake<'a> {
153
180
}
154
181
}
155
182
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
-
186
183
impl fmt:: Debug for Semaphore {
187
184
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
188
185
write ! ( f, "sys::Semaphore" )
0 commit comments