@@ -39,42 +39,42 @@ pub fn uptime_get() -> i64 {
39
39
unsafe { crate :: raw:: k_uptime_get ( ) }
40
40
}
41
41
42
+ // The below implementation, based on interrupt locking has only been tested on single CPU. The
43
+ // implementation suggests it should work on SMP, and can be tested. The docs for irq_lock()
44
+ // explicitly state that it cannot be used from userspace. Unfortunately, spinlocks have
45
+ // incompatible semantics with critical sections, so to work with userspace we'd need probably a
46
+ // syscall.
47
+ #[ cfg( CONFIG_USERSPACE ) ]
48
+ compile_error ! ( "Critical-section implementation does not work with CONFIG_USERSPACE" ) ;
49
+
42
50
pub mod critical {
43
51
//! Zephyr implementation of critical sections.
44
52
//!
45
- //! Critical sections from Rust are handled with a single Zephyr spinlock. This doesn't allow
46
- //! any nesting, but neither does the `critical-section` crate.
47
- //!
48
- //! This provides the underlying critical section crate, which is useful for external crates
49
- //! that want this interface. However, it isn't a particularly hygienic interface to use. For
50
- //! something a bit nicer, please see [`sync::SpinMutex`].
51
- //!
52
- //! [`sync::SpinMutex`]: crate::sync::SpinMutex
53
+ //! The critical-section crate explicitly states that critical sections can be nested.
54
+ //! Unfortunately, Zephyr spinlocks cannot be nested. It is possible to nest different ones,
55
+ //! but the critical-section implementation API doesn't give access to the stack.
53
56
54
- use core:: { ffi:: c_int, ptr:: addr_of_mut} ;
57
+ use core:: {
58
+ ffi:: c_int,
59
+ sync:: atomic:: { fence, Ordering } ,
60
+ } ;
55
61
56
62
use critical_section:: RawRestoreState ;
57
- use zephyr_sys:: { k_spin_lock , k_spin_unlock , k_spinlock , k_spinlock_key_t } ;
63
+ use zephyr_sys:: { zr_irq_lock , zr_irq_unlock } ;
58
64
59
65
struct ZephyrCriticalSection ;
60
66
critical_section:: set_impl!( ZephyrCriticalSection ) ;
61
67
62
- // The critical section shares a single spinlock.
63
- static mut LOCK : k_spinlock = unsafe { core:: mem:: zeroed ( ) } ;
64
-
65
68
unsafe impl critical_section:: Impl for ZephyrCriticalSection {
66
69
unsafe fn acquire ( ) -> RawRestoreState {
67
- let res = k_spin_lock ( addr_of_mut ! ( LOCK ) ) ;
68
- res. key as RawRestoreState
70
+ let res = zr_irq_lock ( ) ;
71
+ fence ( Ordering :: Acquire ) ;
72
+ res as RawRestoreState
69
73
}
70
74
71
75
unsafe fn release ( token : RawRestoreState ) {
72
- k_spin_unlock (
73
- addr_of_mut ! ( LOCK ) ,
74
- k_spinlock_key_t {
75
- key : token as c_int ,
76
- } ,
77
- ) ;
76
+ fence ( Ordering :: Release ) ;
77
+ zr_irq_unlock ( token as c_int ) ;
78
78
}
79
79
}
80
80
}
0 commit comments