@@ -39,42 +39,42 @@ pub fn uptime_get() -> i64 {
3939 unsafe { crate :: raw:: k_uptime_get ( ) }
4040}
4141
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+
4250pub mod critical {
4351 //! Zephyr implementation of critical sections.
4452 //!
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.
5356
54- use core:: { ffi:: c_int, ptr:: addr_of_mut} ;
57+ use core:: {
58+ ffi:: c_int,
59+ sync:: atomic:: { fence, Ordering } ,
60+ } ;
5561
5662 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 } ;
5864
5965 struct ZephyrCriticalSection ;
6066 critical_section:: set_impl!( ZephyrCriticalSection ) ;
6167
62- // The critical section shares a single spinlock.
63- static mut LOCK : k_spinlock = unsafe { core:: mem:: zeroed ( ) } ;
64-
6568 unsafe impl critical_section:: Impl for ZephyrCriticalSection {
6669 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
6973 }
7074
7175 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 ) ;
7878 }
7979 }
8080}
0 commit comments