@@ -40,7 +40,7 @@ impl RawMutex {
40
40
fn raw_unlock ( & self ) {
41
41
compiler_fence ( Ordering :: Release ) ;
42
42
if !self . 0 . replace ( false ) {
43
- already_locked ( )
43
+ panic ! ( "Internal error: Attempt to unlock a `RawMutex` which is not locked." )
44
44
}
45
45
}
46
46
@@ -158,28 +158,37 @@ impl<T> InitOnce<T> {
158
158
/// returns `Ok`. If it returns `Err`, it will be called again in the
159
159
/// future until an attempt at initialization succeeds.
160
160
///
161
- /// Take care when sharing an `InitOnce` object between an IRQ and normal
162
- /// code. If this function is called in an IRQ when it is already currently
163
- /// being initialized by user code, this function will panic.
161
+ /// This function will disable interrupts if the contents are not already
162
+ /// initialized, which may cause audio skipping and similar issues. This
163
+ /// is generally not an issue as that will only happen once during the
164
+ /// lifetime of the program.
164
165
pub fn try_get < E > ( & self , initializer : impl FnOnce ( ) -> Result < T , E > ) -> Result < & T , E > {
165
166
unsafe {
166
167
if self . state . read ( ) != 2 {
167
- // Locks the initializer
168
- if self . state . replace ( 1 ) != 0 {
169
- panic ! ( "Attempt to initialize `InitOnce` that is already in initialization." ) ;
170
- }
171
-
172
- // Initialize the actual value.
173
- let init = match initializer ( ) {
174
- Ok ( v) => v,
175
- Err ( e) => {
176
- assert_eq ! ( self . state. replace( 0 ) , 1 ) ;
177
- return Err ( e) ;
168
+ // We can afford to disable interrupts here, because this code path
169
+ // should only be called once for each variable.
170
+ with_irqs_disabled ( || -> Result < ( ) , E > {
171
+ // Locks the initializer
172
+ if self . state . replace ( 1 ) != 0 {
173
+ panic ! ( "Attempt to initialize `InitOnce` that is already in initialization." ) ;
178
174
}
179
- } ;
180
- ptr:: write_volatile ( ( * self . value . get ( ) ) . as_mut_ptr ( ) , init) ;
181
- assert_eq ! ( self . state. replace( 2 ) , 1 ) ;
175
+
176
+ // Initialize the actual value.
177
+ let init = match initializer ( ) {
178
+ Ok ( v) => v,
179
+ Err ( e) => {
180
+ assert_eq ! ( self . state. replace( 0 ) , 1 ) ;
181
+ return Err ( e) ;
182
+ }
183
+ } ;
184
+ ptr:: write_volatile ( ( * self . value . get ( ) ) . as_mut_ptr ( ) , init) ;
185
+ compiler_fence ( Ordering :: Release ) ;
186
+ assert_eq ! ( self . state. replace( 2 ) , 1 ) ;
187
+
188
+ Ok ( ( ) )
189
+ } ) ;
182
190
}
191
+ compiler_fence ( Ordering :: Acquire ) ;
183
192
Ok ( & * ( * self . value . get ( ) ) . as_mut_ptr ( ) )
184
193
}
185
194
}
0 commit comments