Skip to main content

xwrust/xwos/lock/
spinlock.rs

1//! XWOS RUST:自旋锁
2//! ========
3//!
4//! 自旋锁是多核系统中为防止多个处理器同时访问临界区而引入的一种锁。
5//! 当一个CPU获得自旋锁并访问临界区时,其他CPU只能 **自旋** 等待。
6//! 所谓 **自旋** ,是指不断循环测试锁的是否可用。
7//!
8//! 自旋锁内的操作是不可被打断的。因此,自旋锁还伴随其他操作,
9//! 例如关闭调度器的抢占,关闭中断底半部,关闭中断等。
10//!
11//! 在单核(UP)系统中,只有一个CPU,不需要自旋过程,单核系统为了软件接口与多核系统兼容,
12//! 也会实现自旋锁,这种自旋锁只需关闭抢占、中断底半部或中断。
13//!
14//! 自旋锁可用在 **任何上下文(Context)** :
15//!
16//! + 当临界区只被多个线程访问时,需使用关闭抢占的模式: [`SpinlockMode::Lock`]
17//! + 当临界区被中断底半部访问时,需使用关闭中断底半部的模式: [`SpinlockMode::LockBh`]
18//! + 当临界区被多个线程和单一中断访问时,需使用关闭全局中断的模式: [`SpinlockMode::LockCpuirq`]
19//! + 当临界区被多个中断上下文访问时,需使用保存中断全局标志并关闭全局中断的模式: [`SpinlockMode::LockCpuirqSave(None)`]
20//!
21//!
22//! # 创建
23//!
24//! XWOS RUST的自旋锁可使用 [`Spinlock::new()`] 创建:
25//!
26//! + 可以创建具有静态生命周期 [`static`] 约束的全局变量:
27//!
28//! ```rust
29//! use xwrust::xwos::lock::spinlock::*;
30//!
31//! static GLOBAL_SPINLOCK: Spinlock<u32> = Spinlock::new(0);
32//! ```
33//!
34//! + 也可以使用 [`alloc::sync::Arc`] 在heap中创建:
35//!
36//! ```rust
37//! extern crate alloc;
38//! use alloc::sync::Arc;
39//!
40//! use xwrust::xwos::lock::spinlock::*;
41//!
42//! pub fn xwrust_example_spinlock() {
43//!     let spinlock: Arc<Spinlock<u32>> = Arc::new(Spinlock::new(0));
44//! }
45//! ```
46//!
47//!
48//! # 解锁
49//!
50//! 上锁后返回的 [`SpinlockGuard`] 。 [`SpinlockGuard`] 的生命周期结束时,会自动解锁。
51//! 也可调用 [`Spinlock::unlock()`] 主动消费掉 [`SpinlockGuard`] 来解锁。
52//!
53//!
54//! # 上锁
55//!
56//! 上锁的方法 [`Spinlock::lock()`] 除了 **自旋** 等待,还会根据上锁模式增加额外操作:
57//!
58//! + 只关闭抢占的模式: [`SpinlockMode::Lock`]
59//! + 关闭中断底半部的模式: [`SpinlockMode::LockBh`]
60//! + 关闭全局中断的模式: [`SpinlockMode::LockCpuirq`]
61//! + 保存中断全局标志并关闭全局中断的模式: [`SpinlockMode::LockCpuirqSave(None)`]
62//!
63//!
64//! # 尝试上锁
65//!
66//! 尝试上锁的方法 [`Spinlock::trylock()`] 只会测试一下锁,不会 **自旋** 等待,上锁成功后还会根据上锁模式增加额外操作:
67//!
68//! + 只关闭抢占的模式: [`SpinlockMode::Lock`]
69//! + 关闭中断底半部的模式: [`SpinlockMode::LockBh`]
70//! + 关闭全局中断的模式: [`SpinlockMode::LockCpuirq`]
71//! + 保存中断全局标志并关闭全局中断的模式: [`SpinlockMode::LockCpuirqSave(None)`]
72//!
73//!
74//! # 示例
75//!
76//! [XWOS/xwam/xwrust-example/xwrust_example_spinlock](https://gitee.com/xwos/XWOS/blob/main/xwam/xwrust-example/xwrust_example_spinlock/src/lib.rs)
77//!
78//!
79//! [`SpinlockMode::LockCpuirqSave(None)`]: SpinlockMode::LockCpuirqSave
80//! [`static`]: https://doc.rust-lang.org/std/keyword.static.html
81//! [`alloc::sync::Arc`]: <https://doc.rust-lang.org/alloc/sync/struct.Arc.html>
82
83extern crate core;
84use core::cell::UnsafeCell;
85use core::result::Result;
86use core::default::Default;
87use core::option::Option;
88use core::ops::Drop;
89use core::ops::Deref;
90use core::ops::DerefMut;
91use core::ptr;
92
93use crate::types::*;
94use crate::errno::*;
95
96use crate::xwos::sync::cond::*;
97
98extern "C" {
99    fn xwrustffi_splk_init(splk: *mut XwosSplk);
100    fn xwrustffi_splk_unlock(splk: *mut XwosSplk);
101    fn xwrustffi_splk_lock(splk: *mut XwosSplk);
102    fn xwrustffi_splk_trylock(splk: *mut XwosSplk) -> XwEr;
103    fn xwrustffi_splk_unlock_cpuirq(splk: *mut XwosSplk);
104    fn xwrustffi_splk_lock_cpuirq(splk: *mut XwosSplk);
105    fn xwrustffi_splk_trylock_cpuirq(splk: *mut XwosSplk) -> XwEr;
106    fn xwrustffi_splk_unlock_cpuirqrs(splk: *mut XwosSplk, cpuirq: XwReg);
107    fn xwrustffi_splk_lock_cpuirqsv(splk: *mut XwosSplk, cpuirq: *mut XwReg);
108    fn xwrustffi_splk_trylock_cpuirqsv(splk: *mut XwosSplk, cpuirq: *mut XwReg) -> XwEr;
109    fn xwrustffi_splk_unlock_bh(splk: *mut XwosSplk);
110    fn xwrustffi_splk_lock_bh(splk: *mut XwosSplk);
111    fn xwrustffi_splk_trylock_bh(splk: *mut XwosSplk) -> XwEr;
112}
113
114/// 自旋锁的错误码
115#[derive(Debug)]
116pub enum SpinlockError {
117    /// 尝试上锁失败
118    Again(XwEr),
119    /// 未知错误
120    Unknown(XwEr),
121}
122
123impl SpinlockError {
124    /// 消费掉 `SpinlockError` 自身,返回内部的错误码。
125    pub fn unwrap(self) -> XwEr {
126        match self {
127            Self::Again(rc) => rc,
128            Self::Unknown(rc) => rc,
129        }
130    }
131}
132
133/// 自旋锁的上锁模式
134pub enum SpinlockMode {
135    /// 关闭抢占
136    Lock,
137    /// 关闭抢占、中断底半部
138    LockBh,
139    /// 关闭抢占、中断底半部和中断
140    LockCpuirq,
141    /// 关闭抢占、中断底半部和中断,并保存之前的中断标志
142    LockCpuirqSave(Option<XwReg>),
143}
144
145/// XWOS自旋锁占用的内存大小
146#[cfg(target_pointer_width = "32")]
147pub const SIZEOF_XWOS_SPLK: usize = 8;
148
149/// XWOS自旋锁占用的内存大小
150#[cfg(target_pointer_width = "64")]
151pub const SIZEOF_XWOS_SPLK: usize = 8;
152
153/// 用于构建自旋锁的内存数组类型
154#[repr(C)]
155#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
156#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
157pub(crate) struct XwosSplk {
158    pub(crate) obj: [u8; SIZEOF_XWOS_SPLK],
159}
160
161/// 用于构建自旋锁的内存数组常量
162pub(crate) const XWOS_SPLK_INITIALIZER: XwosSplk = XwosSplk {
163    obj: [0; SIZEOF_XWOS_SPLK],
164};
165
166
167/// 自旋锁结构体
168pub struct Spinlock<T: ?Sized> {
169    /// XWOS自旋锁
170    pub(crate) splk: UnsafeCell<XwosSplk>,
171    /// 上锁方式
172    pub(crate) mode: UnsafeCell<SpinlockMode>,
173    /// 用户数据
174    pub data: UnsafeCell<T>,
175}
176
177impl<T> Spinlock<T> {
178    /// 新建自旋锁
179    ///
180    /// 此方法是编译期方法,可用于新建 [`static`] 约束的全局变量。
181    ///
182    /// # 示例
183    ///
184    /// ```rust
185    /// use xwrust::xwos::lock::spinlock::*;
186    ///
187    /// static GLOBAL_SPINLOCK: Spinlock<u32>  = Spinlock::new(0);
188    /// ```
189    ///
190    /// [`static`]: https://doc.rust-lang.org/std/keyword.static.html
191    pub const fn new(t: T) -> Self {
192        Self {
193            splk: UnsafeCell::new(XWOS_SPLK_INITIALIZER),
194            mode: UnsafeCell::new(SpinlockMode::Lock),
195            data: UnsafeCell::new(t),
196        }
197    }
198}
199
200impl<T: ?Sized> Spinlock<T> {
201    /// 获取自旋锁,若线程无法获取自旋锁,就阻塞等待,直到能获得锁为止
202    ///
203    /// + 若成功获取自旋锁,将返回 **RAII Guard** : [`SpinlockGuard`] ,用于提供 **Scoped Lock** 机制。
204    ///   + [`SpinlockGuard`] 中包含 [`Spinlock`] 的引用, 当 [`SpinlockGuard`] 生命周期结束时,会在 [`drop()`] 方法中自动解锁自旋锁。
205    /// + 若失败,将返回错误码 [`SpinlockError`] 。
206    ///
207    /// # 参数说明
208    ///
209    /// + mode: 锁模式
210    ///   + [`SpinlockMode::Lock`] 关闭抢占
211    ///   + [`SpinlockMode::LockBh`] 关闭抢占、中断底半部
212    ///   + [`SpinlockMode::LockCpuirq`] 关闭抢占、中断底半部和中断
213    ///   + [`SpinlockMode::LockCpuirqSave(None)`] 关闭抢占、中断底半部和中断,并保存之前的中断标志
214    ///
215    /// # 示例
216    ///
217    /// ```rust
218    /// use xwrust::xwos::lock::spinlock::*;
219    /// static GLOBAL_SPINLOCK: Spinlock<u32> = Spinlock::new(0);
220    ///
221    /// pub fn xwrust_example_spinlock() {
222    ///     // ...省略...
223    ///     let mut guard = GLOBAL_SPINLOCK.lock();
224    ///     *guard = 1; // 访问共享变量
225    ///     drop(guard); // 解锁
226    /// }
227    /// ```
228    ///
229    /// [`SpinlockMode::LockCpuirqSave(None)`]: SpinlockMode::LockCpuirqSave
230    /// [`drop()`]: https://doc.rust-lang.org/std/mem/fn.drop.html
231    pub fn lock(&self, mode: SpinlockMode) -> SpinlockGuard<'_, T> {
232        unsafe {
233            match mode {
234                SpinlockMode::Lock => {
235                    xwrustffi_splk_lock(self.splk.get());
236                    *self.mode.get() = SpinlockMode::Lock;
237                },
238                SpinlockMode::LockCpuirq => {
239                    xwrustffi_splk_lock_cpuirq(self.splk.get());
240                    *self.mode.get() = SpinlockMode::LockCpuirq;
241                },
242                SpinlockMode::LockCpuirqSave(_) => {
243                    let mut cpuirq: XwReg = 0;
244                    xwrustffi_splk_lock_cpuirqsv(self.splk.get(), &mut cpuirq);
245                    *self.mode.get() = SpinlockMode::LockCpuirqSave(Some(cpuirq));
246                },
247                SpinlockMode::LockBh => {
248                    xwrustffi_splk_lock_bh(self.splk.get());
249                    *self.mode.get() = SpinlockMode::LockBh;
250                },
251            }
252            SpinlockGuard::new(self)
253        }
254    }
255
256    /// 尝试获取自旋锁,若线程无法获取自旋锁,立即返回错误
257    ///
258    /// + 若成功获取自旋锁,将返回 **RAII Guard** : [`SpinlockGuard`] ,用于提供 **Scoped Lock** 机制。
259    ///   + [`SpinlockGuard`] 中包含 [`Spinlock`] 的引用, 当 [`SpinlockGuard`] 生命周期结束时,会在 [`drop()`] 方法中自动解锁自旋锁。
260    /// + 若失败,将返回错误码 [`SpinlockError`] 。
261    ///
262    /// # 参数说明
263    ///
264    /// + mode: 锁模式
265    ///   + [`SpinlockMode::Lock`] 关闭抢占
266    ///   + [`SpinlockMode::LockBh`] 关闭抢占、中断底半部
267    ///   + [`SpinlockMode::LockCpuirq`] 关闭抢占、中断底半部和中断
268    ///   + [`SpinlockMode::LockCpuirqSave(None)`] 关闭抢占、中断底半部和中断,并保存之前的中断标志
269    ///
270    /// # 错误码
271    ///
272    /// + [`SpinlockError::Again`] 尝试获取锁失败
273    ///
274    /// # 示例
275    /// ```rust
276    /// use xwrust::xwos::lock::spinlock::*;
277    /// static GLOBAL_SPINLOCK: Spinlock<u32> = Spinlock::new(0);
278    ///
279    /// pub fn xwrust_example_spinlock() {
280    ///     // ...省略...
281    ///     match GLOBAL_SPINLOCK.trylock() {
282    ///         Ok(mut guard) => { // 上锁成功
283    ///             *guard = 1; // 访问共享变量
284    ///         } // guard 生命周期结束,自动解锁
285    ///         Err(e) => {
286    ///             // 上锁失败
287    ///         }
288    ///     }
289    /// }
290    /// ```
291    ///
292    /// [`SpinlockMode::LockCpuirqSave(None)`]: SpinlockMode::LockCpuirqSave
293    /// [`drop()`]: https://doc.rust-lang.org/std/mem/fn.drop.html
294    pub fn trylock(&self, mode: SpinlockMode) -> Result<SpinlockGuard<'_, T>, SpinlockError> {
295        unsafe {
296            let rc: XwEr;
297            match mode {
298                SpinlockMode::Lock => {
299                    rc = xwrustffi_splk_trylock(self.splk.get());
300                    if 0 == rc {
301                        *self.mode.get() = SpinlockMode::Lock;
302                        Ok(SpinlockGuard::new(self))
303                    } else if -EAGAIN == rc {
304                        Err(SpinlockError::Again(rc))
305                    } else {
306                        Err(SpinlockError::Unknown(rc))
307                    }
308                },
309                SpinlockMode::LockCpuirq => {
310                    rc = xwrustffi_splk_trylock_cpuirq(self.splk.get());
311                    if 0 == rc {
312                        *self.mode.get() = SpinlockMode::LockCpuirq;
313                        Ok(SpinlockGuard::new(self))
314                    } else if -EAGAIN == rc {
315                        Err(SpinlockError::Again(rc))
316                    } else {
317                        Err(SpinlockError::Unknown(rc))
318                    }
319                },
320                SpinlockMode::LockCpuirqSave(_) => {
321                    let mut cpuirq: XwReg = 0;
322                    rc = xwrustffi_splk_trylock_cpuirqsv(self.splk.get(), &mut cpuirq);
323                    if 0 == rc {
324                        *self.mode.get() = SpinlockMode::LockCpuirqSave(Some(cpuirq));
325                        Ok(SpinlockGuard::new(self))
326                    } else if -EAGAIN == rc {
327                        Err(SpinlockError::Again(rc))
328                    } else {
329                        Err(SpinlockError::Unknown(rc))
330                    }
331                },
332                SpinlockMode::LockBh => {
333                    rc = xwrustffi_splk_trylock_bh(self.splk.get());
334                    if 0 == rc {
335                        *self.mode.get() = SpinlockMode::LockBh;
336                        Ok(SpinlockGuard::new(self))
337                    } else if -EAGAIN == rc {
338                        Err(SpinlockError::Again(rc))
339                    } else {
340                        Err(SpinlockError::Unknown(rc))
341                    }
342                },
343            }
344        }
345    }
346
347    /// 解锁自旋锁,并释放 [`SpinlockGuard`]
348    ///
349    /// # 示例
350    ///
351    /// ```rust
352    /// use xwrust::xwos::lock::spinlock::*;
353    /// static GLOBAL_SPINLOCK: Spinlock<u32> = Spinlock::new(0);
354    ///
355    /// pub fn xwrust_example_spinlock() {
356    ///     // ...省略...
357    ///     let mut guard = GLOBAL_SPINLOCK.lock();
358    ///     *guard = 1; // 访问共享变量
359    ///     Spinlock::unlock(guard); // 主动解锁
360    /// }
361    /// ```
362    ///
363    /// [`drop()`]: https://doc.rust-lang.org/std/mem/fn.drop.html
364    pub fn unlock(guard: SpinlockGuard<'_, T>) {
365        drop(guard)
366    }
367}
368
369unsafe impl<T: ?Sized + Send> Send for Spinlock<T> {}
370unsafe impl<T: ?Sized + Send> Sync for Spinlock<T> {}
371
372impl<T> From<T> for Spinlock<T> {
373    /// 从数据新建自旋锁
374    ///
375    /// 此方法会将数据所有权转移到自旋锁的内部
376    ///
377    /// 等价于 [`Spinlock::new`]
378    fn from(t: T) -> Self {
379        Spinlock::new(t)
380    }
381}
382
383impl<T: ?Sized + Default> Default for Spinlock<T> {
384    fn default() -> Spinlock<T> {
385        Spinlock::new(Default::default())
386    }
387}
388
389impl<T: ?Sized> Drop for Spinlock<T> {
390    fn drop(&mut self) {
391    }
392}
393
394/// 自旋锁的RAII Guard
395///
396/// **RAII Guard** 用于提供 **Scoped Lock** 机制。
397///
398/// + [`SpinlockGuard`] 中包含 [`Spinlock`] 的引用, 当 [`SpinlockGuard`] 生命周期结束时,会在 [`drop()`] 方法中自动解锁自旋锁。
399/// + [`SpinlockGuard`] 不可在线程之间转移所有权,因为其 [`drop()`] 方法包含解锁的语义,上锁和解锁必须在同一线程;
400/// + [`SpinlockGuard`] 虽然可以在多线程中传递引用( [`Sync`] 约束),但其实现中没有 **unlock()** 方法,意味着其他线程即便拿到引用也不能解锁。
401///
402/// [`drop()`]: https://doc.rust-lang.org/std/mem/fn.drop.html
403/// [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Send.html
404pub struct SpinlockGuard<'a, T: ?Sized + 'a> {
405    /// 自旋锁的引用
406    lock: &'a Spinlock<T>,
407}
408
409impl<T: ?Sized> !Send for SpinlockGuard<'_, T> {}
410unsafe impl<T: ?Sized + Sync> Sync for SpinlockGuard<'_, T> {}
411
412impl<'a, T: ?Sized> SpinlockGuard<'a, T> {
413    fn new(lock: &'a Spinlock<T>) -> SpinlockGuard<'a, T> {
414        SpinlockGuard { lock: lock }
415    }
416
417    fn lock(&self) {
418        unsafe {
419            xwrustffi_splk_lock(self.lock.splk.get());
420        }
421    }
422
423    fn unlock(&self) {
424        unsafe {
425            xwrustffi_splk_unlock(self.lock.splk.get());
426        }
427    }
428
429    /// 阻塞当前线程,直到被条件量唤醒
430    ///
431    /// 此方法会消费自旋锁的守卫(Guard),并当线程阻塞时,在条件量内部释放自旋锁。
432    /// 当条件成立,线程被唤醒,会在条件量内部上锁自旋锁,并重新返回自旋锁的守卫(Guard)。
433    ///
434    /// + 当返回自旋锁的守卫 [`SpinlockGuard`] 时,自旋锁已经被重新上锁;
435    /// + 当返回 [`Err`] 时,自旋锁未被上锁。
436    ///
437    /// # 参数说明
438    ///
439    /// + cond: 条件量的引用
440    ///
441    /// # 错误码
442    ///
443    /// + [`CondError::NotInit`] 条件量未被初始化
444    /// + [`CondError::Interrupt`] 等待被中断
445    /// + [`CondError::NotThreadContext`] 不在线程上下文中
446    ///
447    /// # 示例
448    ///
449    /// ```rust
450    /// use xwrust::xwos::thd;
451    /// use xwrust::xwos::lock::spinlock::*;
452    /// use xwrust::xwos::sync::cond::*;
453    /// extern crate alloc;
454    /// use alloc::sync::Arc;
455    ///
456    /// pub fn xwrust_example_spinlock() {
457    ///     let pair = Arc::new((Spinlock::new(true), Cond::new()));
458    ///     pair.1.init();
459    ///     let pair_c = pair.clone();
460    ///
461    ///     thd::Builder::new()
462    ///         .name("child".into())
463    ///         .spawn(move |_| { // 子线程闭包
464    ///             cthd::sleep(xwtm::ms(500));
465    ///             let (lock, cvar) = &*pair_c;
466    ///             let mut guard = lock_child.lock();
467    ///             *guard = false; // 设置共享数据
468    ///             drop(guard); // 先解锁再触发条件可提高效率
469    ///             cvar.broadcast();
470    ///         });
471    ///     let (lock, cvar) = &*pair;
472    ///     {
473    ///         let mut guard = lock.lock();
474    ///         while *guard {
475    ///             match guard.wait(cvar) {
476    ///                 Ok(g) => { // 唤醒
477    ///                     guard = g; // 重新捕获守卫
478    ///                 },
479    ///                 Err(e) => { // 等待条件量失败
480    ///                     break;
481    ///                 },
482    ///             }
483    ///         }
484    ///     }
485    /// }
486    /// ```
487    ///
488    /// [`Err`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
489    pub fn wait(self, cond: &Cond) -> Result<SpinlockGuard<'a, T>, CondError> {
490        unsafe {
491            let mut rc = xwrustffi_cond_acquire(cond.cond.get(), *cond.tik.get());
492            if rc == 0 {
493                let mut lkst = 0;
494                rc = xwrustffi_cond_wait(cond.cond.get(),
495                                         self.lock.splk.get() as _, XWOS_LK_SPLK, ptr::null_mut(),
496                                         &mut lkst);
497                xwrustffi_cond_put(cond.cond.get());
498                if 0 == rc {
499                    Ok(self)
500                } else {
501                    if XWOS_LKST_LOCKED == lkst {
502                        drop(self);
503                    } else {
504                        self.lock();
505                        drop(self);
506                    }
507                    if -EINTR == rc {
508                        Err(CondError::Interrupt(rc))
509                    } else if -ENOTTHDCTX == rc {
510                        Err(CondError::NotThreadContext(rc))
511                    } else {
512                        Err(CondError::Unknown(rc))
513                    }
514                }
515            } else {
516                drop(self);
517                Err(CondError::NotInit(rc))
518            }
519        }
520    }
521
522    /// 限时阻塞当前线程,直到被条件量唤醒
523    ///
524    /// 此方法会消费自旋锁的守卫(Guard),并当线程阻塞时,在条件量内部释放自旋锁。
525    /// 当条件成立,线程被唤醒,会在条件量内部上锁自旋锁,并重新返回自旋锁的守卫(Guard)。
526    /// 当超时后,将返回错误。
527    ///
528    /// + 当返回自旋锁的守卫 [`SpinlockGuard`] 时,自旋锁已经被重新上锁;
529    /// + 当返回 [`Err`] 时,自旋锁未被上锁。
530    ///
531    /// # 参数说明
532    ///
533    /// + cond: 条件量的引用
534    /// + to: 期望唤醒的时间点
535    ///
536    /// # 错误码
537    ///
538    /// + [`CondError::NotInit`] 条件量未被初始化
539    /// + [`CondError::Interrupt`] 等待被中断
540    /// + [`CondError::Timedout`] 等待超时
541    /// + [`CondError::NotThreadContext`] 不在线程上下文中
542    ///
543    /// # 示例
544    ///
545    /// ```rust
546    /// use xwrust::xwos::thd;
547    /// use xwrust::xwos::lock::spinlock::*;
548    /// use xwrust::xwos::sync::cond::*;
549    /// extern crate alloc;
550    /// use alloc::sync::Arc;
551    ///
552    /// pub fn xwrust_example_spinlock() {
553    ///     let pair = Arc::new((Spinlock::new(true), Cond::new()));
554    ///     pair.1.init();
555    ///     let pair_c = pair.clone();
556    ///
557    ///     thd::Builder::new()
558    ///         .name("child".into())
559    ///         .spawn(move |_| { // 子线程闭包
560    ///             cthd::sleep(xwtm::ms(500));
561    ///             let (lock, cvar) = &*pair_c;
562    ///             let mut guard = lock_child.lock();
563    ///             *guard = false; // 设置共享数据
564    ///             drop(guard); // 先解锁再触发条件可提高效率
565    ///             cvar.broadcast();
566    ///         });
567    ///     let (lock, cvar) = &*pair;
568    ///     {
569    ///         let mut guard = lock.lock();
570    ///         while *guard {
571    ///             match guard.wait_to(cvar, xwtm::ft(xwtm::s(2))) {
572    ///                 Ok(g) => { // 唤醒
573    ///                     guard = g; // 重新捕获守卫
574    ///                 },
575    ///                 Err(e) => { // 等待条件量失败
576    ///                     break;
577    ///                 },
578    ///             }
579    ///         }
580    ///     }
581    /// }
582    /// ```
583    ///
584    /// [`Err`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
585    pub fn wait_to(self, cond: &Cond, to: XwTm) -> Result<SpinlockGuard<'a, T>, CondError> {
586        unsafe {
587            let mut rc = xwrustffi_cond_acquire(cond.cond.get(), *cond.tik.get());
588            if rc == 0 {
589                let mut lkst = 0;
590                rc = xwrustffi_cond_wait_to(cond.cond.get(),
591                                            self.lock.splk.get() as _, XWOS_LK_SPLK, ptr::null_mut(),
592                                            to, &mut lkst);
593                xwrustffi_cond_put(cond.cond.get());
594                if 0 == rc {
595                    Ok(self)
596                } else {
597                    if XWOS_LKST_LOCKED == lkst {
598                        drop(self);
599                    } else {
600                        self.lock();
601                        drop(self);
602                    }
603                    if -EINTR == rc {
604                        Err(CondError::Interrupt(rc))
605                    } else if -ETIMEDOUT == rc {
606                        Err(CondError::Timedout(rc))
607                    } else if -ENOTTHDCTX == rc {
608                        Err(CondError::NotThreadContext(rc))
609                    } else {
610                        Err(CondError::Unknown(rc))
611                    }
612                }
613            } else {
614                drop(self);
615                Err(CondError::NotInit(rc))
616            }
617        }
618    }
619
620    /// 阻塞当前线程,直到被条件量唤醒,且阻塞不可被中断
621    ///
622    /// 此方法会消费自旋锁的守卫(Guard),并当线程阻塞时,在条件量内部释放自旋锁。
623    /// 当条件成立,线程被唤醒,会在条件量内部上锁自旋锁,并重新返回自旋锁的守卫(Guard)。
624    ///
625    /// + 当返回自旋锁的守卫 [`SpinlockGuard`] 时,自旋锁已经被重新上锁;
626    /// + 当返回 [`Err`] 时,自旋锁未被上锁。
627    ///
628    /// # 参数说明
629    ///
630    /// + cond: 条件量的引用
631    ///
632    /// # 错误码
633    ///
634    /// + [`CondError::NotInit`] 条件量未被初始化
635    /// + [`CondError::NotThreadContext`] 不在线程上下文中
636    ///
637    /// # 示例
638    ///
639    /// ```rust
640    /// use xwrust::xwos::thd;
641    /// use xwrust::xwos::lock::spinlock::*;
642    /// use xwrust::xwos::sync::cond::*;
643    /// extern crate alloc;
644    /// use alloc::sync::Arc;
645    ///
646    /// pub fn xwrust_example_spinlock() {
647    ///     let pair = Arc::new((Spinlock::new(true), Cond::new()));
648    ///     pair.1.init();
649    ///     let pair_c = pair.clone();
650    ///
651    ///     thd::Builder::new()
652    ///         .name("child".into())
653    ///         .spawn(move |_| { // 子线程闭包
654    ///             cthd::sleep(xwtm::ms(500));
655    ///             let (lock, cvar) = &*pair_c;
656    ///             let mut guard = lock_child.lock();
657    ///             *guard = false; // 设置共享数据
658    ///             drop(guard); // 先解锁再触发条件可提高效率
659    ///             cvar.broadcast();
660    ///         });
661    ///     let (lock, cvar) = &*pair;
662    ///     {
663    ///         let mut guard = lock.lock();
664    ///         while *guard {
665    ///             match guard.wait_unintr(cvar) {
666    ///                 Ok(g) => { // 唤醒
667    ///                     guard = g; // 重新捕获守卫
668    ///                 },
669    ///                 Err(e) => { // 等待条件量失败
670    ///                     break;
671    ///                 },
672    ///             }
673    ///         }
674    ///     }
675    /// }
676    /// ```
677    ///
678    /// [`Err`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
679    pub fn wait_unintr(self, cond: &Cond) -> Result<SpinlockGuard<'a, T>, CondError> {
680        unsafe {
681            let mut rc = xwrustffi_cond_acquire(cond.cond.get(), *cond.tik.get());
682            if rc == 0 {
683                let mut lkst = 0;
684                rc = xwrustffi_cond_wait_unintr(cond.cond.get(),
685                                                self.lock.splk.get() as _, XWOS_LK_SPLK, ptr::null_mut(),
686                                                &mut lkst);
687                xwrustffi_cond_put(cond.cond.get());
688                if 0 == rc {
689                    Ok(self)
690                } else {
691                    if XWOS_LKST_LOCKED == lkst {
692                        drop(self);
693                    } else {
694                        self.lock();
695                        drop(self);
696                    }
697                    if -EINTR == rc {
698                        Err(CondError::Interrupt(rc))
699                    } else if -ENOTTHDCTX == rc {
700                        Err(CondError::NotThreadContext(rc))
701                    } else {
702                        Err(CondError::Unknown(rc))
703                    }
704                }
705            } else {
706                drop(self);
707                Err(CondError::NotInit(rc))
708            }
709        }
710    }
711}
712
713impl<T: ?Sized> Deref for SpinlockGuard<'_, T> {
714    type Target = T;
715
716    fn deref(&self) -> &T {
717        unsafe { &*self.lock.data.get() }
718    }
719}
720
721impl<T: ?Sized> DerefMut for SpinlockGuard<'_, T> {
722    fn deref_mut(&mut self) -> &mut T {
723        unsafe { &mut *self.lock.data.get() }
724    }
725}
726
727impl<T: ?Sized> Drop for SpinlockGuard<'_, T> {
728    fn drop(&mut self) {
729        unsafe {
730            match *self.lock.mode.get() {
731                SpinlockMode::Lock => {
732                    xwrustffi_splk_unlock(self.lock.splk.get());
733                },
734                SpinlockMode::LockCpuirq => {
735                    xwrustffi_splk_unlock_cpuirq(self.lock.splk.get());
736                },
737                SpinlockMode::LockCpuirqSave(cpuirq) => {
738                    xwrustffi_splk_unlock_cpuirqrs(self.lock.splk.get(), cpuirq.unwrap_unchecked());
739                },
740                SpinlockMode::LockBh => {
741                    xwrustffi_splk_unlock_bh(self.lock.splk.get());
742                },
743            }
744        }
745    }
746}