xwrust/xwos/thd.rs
1//! XWOS RUST:线程
2//! ========
3//!
4//! XWOS的线程分为 **分离态** 或 **连接态** :
5//!
6//! + **分离态(detached)** :分离态的线程退出后由操作系统自动回收其内存资源;
7//! + **连接态(joinable)** :连接态的线程退出后需要被其他线程 `join()` ,之后才会被操作系统回收内存资源。
8//!
9//! XWOS RUST的线程分为 **动态线程** 与 **静态线程** 。无论哪种线程创建时,都是 **连接态(joinable)** 的。
10//! 线程创建后,将返回线程的 **Handle** 。如果未将线程的 **Handle** 绑定到变量上,线程将自动转变为 **分离态(detached)** 。
11//!
12//!
13//! # 动态线程
14//!
15//! **动态线程** 是指通过动态内存分配器创建的线程。
16//!
17//! 动态线程的对象结构体、栈、线程闭包等资源都是通过内存申请的接口动态创建的。
18//!
19//! XWOS RUST的动态线程库是仿照 [`std::thread`] 来编写的。
20//!
21//! ```rust
22//! use xwrust::xwos::thd;
23//!
24//! thd::spawn(|_| {
25//! // 线程代码;
26//! });
27//! ```
28//!
29//! 在上述代码中,[`spawn()`] 方法会返回 [`DThdHandle`] ,但由于 [`DThdHandle`] 没有被绑定到任何变量名上,
30//! 其生命周期结束后的 [`drop()`] 方法会自动将动态线程转变为 **分离态(detached)** 。此线程运行结束后,其资源会被系统自动回收。
31//!
32//!
33//! 动态线程也可以是 **可连接的(joinable)** ,可以将返回的 [`DThdHandle`] 绑定在变量上。
34//! 然后通过 [`DThdHandle::join()`] 方法等待线程运行结束。
35//!
36//! ```rust
37//! use xwrust::xwos::thd;
38//!
39//! let res = thd::spawn(|_| {
40//! // 线程代码;
41//! // 返回值
42//! });
43//! match res {
44//! Ok(handler) => {
45//! match handler.join() {
46//! Ok(r) => {
47//! // `r` 是线程闭包的返回值。
48//! },
49//! Err(e) => {
50//! // `join()` 失败时的错误码可通过 `e.state()` 获取。
51//! // `e` 是 `DThdHandle<R>` ,重新被返回。
52//! },
53//! };
54//! },
55//! Err(rc) => {
56//! // `rc` 是 `spawn()` 失败时的错误码。
57//! },
58//! };
59//! ```
60//!
61//! [`DThdHandle::join()`] 方法会返回 [`Result<R, Self>`] , `R` 是返回值的类型,并放在 [`Ok()`] 中,
62//! 方法调用失败时,会将 [`DThdHandle`] 放在 [`Err()`] 中重新返回。此时,用户可以通过 [`DThdHandle::state()`] 获取失败原因,
63//! 并且在合适的时机重新调用方法 [`DThdHandle::join()`] 。
64//!
65//!
66//! ## 动态线程的线程函数
67//!
68//! 动态线程可以使用 [`FnOnce()`] 闭包作为线程函数。其原型是: `FnOnce(Arc<DThdElement>) -> R` ,
69//! 动态线程函数运行时,参数是动态线程的元素 [`DThdElement`] ,返回值为泛型 `R` 。
70//!
71//!
72//! ## 动态线程的工厂模式
73//!
74//! 可以通过线程工厂 [`DThdBuilder`] 设置线程属性后,再创建动态线程:
75//!
76//! ```rust
77//! use xwrust::xwos::thd;
78//!
79//! let builder = thd::DThdBuilder::new()
80//! .name("foo".into()) // 设置线程的名称
81//! .stack_size(8 * 1024) // 设置线程栈大小
82//! .privileged(true); // 设置系统权限
83//!
84//! builder.spawn(|_| {
85//! // 线程代码;
86//! // 返回值
87//! });
88//! ```
89//!
90//! #### 线程的名称
91//!
92//! 线程工厂可以通过 [`DThdBuilder::name()`] 为线程指定一个字符串名字。可以为空,默认为 `"anon"` 。
93//!
94//! #### 线程的栈大小
95//!
96//! 线程工厂可以通过 [`DThdBuilder::stack_size()`] 为线程指定栈内存大小,默认为XWOS的内核配置 `XWMMCFG_STACK_SIZE_MIN` 。
97//!
98//! #### 线程的系统权限
99//!
100//! 某些SOC内部的寄存器,只有拥有系统权限的线程才可以访问。线程工厂可以通过 [`DThdBuilder::privileged()`] 为线程指定是否具有系统特权,默认为拥有系统权限。
101//!
102//!
103//! ## 动态线程的元素
104//!
105//! 动态线程的元素 [`DThdElement`] 是存放与线程相关的信息的内存空间。
106//! 动态线程工厂 [`DThdBuilder`] 中设置的信息会被转移到 [`DThdElement`] 中。
107//! 动态线程运行时, `Arc<DThdElement>` 作为参数被传递到闭包内。以 [`Arc<T>`] 进行封装是因为要将其放在堆上。
108//!
109//!
110//! ## 动态线程的句柄
111//!
112//! 静态线程的句柄 [`DThdHandle`] 功能类似于 [`std::thread::JoinHandle`] ,可用于控制动态子线程的退出。
113//!
114//! #### 中断动态线程的阻塞态和睡眠态
115//!
116//! 方法 [`DThdHandle::intr()`] 可用于中断线程的 **阻塞态** 和 **睡眠态** 。
117//! 阻塞和睡眠的方法将以返回值 **负** 的 [`EINTR`] 退出。错误码 [`EINTR`] 会被转换为各个可阻塞线程的操作系统对象的错误码:
118//!
119//! + [`MutexError::Interrupt`]
120//! + [`SemError::Interrupt`]
121//! + [`CondError::Interrupt`]
122//! + [`FlgError::Interrupt`]
123//! + [`BrError::Interrupt`]
124//! + [`SelError::Interrupt`]
125//!
126//! 方法 [`DThdHandle::intr()`] 是基于 [`ThdD::intr()`] 实现的,调用后者与前者在功能上没有区别。
127//! 动态线程自身的 [`ThdD`] 可通过 [`cthd::i()`] 获取。
128//!
129//! #### 通知动态线程退出
130//!
131//! 方法 [`DThdHandle::quit()`] 可用于父线程通知动态子线程退出。此方法不会等待动态子线程退出。
132//!
133//! 方法 [`DThdHandle::quit()`] 会为动态子线程设置 **退出状态** ,并中断 **阻塞状态** 和 **睡眠状态** 。
134//! 阻塞和睡眠的方法将以返回值负的 [`EINTR`] 退出。错误码 [`EINTR`] 会被转换为各个可阻塞线程的操作系统对象的错误码:
135//!
136//! + [`MutexError::Interrupt`]
137//! + [`SemError::Interrupt`]
138//! + [`CondError::Interrupt`]
139//! + [`FlgError::Interrupt`]
140//! + [`BrError::Interrupt`]
141//! + [`SelError::Interrupt`]
142//!
143//! 但是,当动态子线程的 **阻塞状态** 是不可被中断的,方法 [`DThdHandle::quit()`] 只会为动态子线程设置 **退出状态** ,不会发生中断。
144//!
145//! 动态子线程可以通过 [`cthd::shld_stop()`] 判断是否被设置了 **退出状态** ,可以作为结束线程循环的条件。
146//!
147//! 方法 [`DThdHandle::quit()`] 是基于 [`ThdD::quit()`] 实现的,调用后者与前者在功能上没有区别。
148//! 动态线程自身的 [`ThdD`] 可通过 [`cthd::i()`] 获取。
149//!
150//! #### 等待动态线程退出
151//!
152//! 当父线程需要等待动态子线程退出,并捕获其返回值时,需要使用方法 [`DThdHandle::join()`] 。
153//!
154//! + 如果动态子线程还在运行,此方法会阻塞父线程直到动态子线程退出。
155//! + 如果动态子线程已经提前运行至退出,此方法可立即返回动态子线程的返回值。
156//!
157//! 此方法会消费 [`DThdHandle`] :
158//!
159//! + 如果此方法执行成功,会消费掉 [`DThdHandle`] ,并将动态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`DThdHandle`] 的生命周期也应该结束;
160//! + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`DThdHandle`] ,用户可通过 [`DThdHandle::state()`] 方法获取失败的原因,并且在合适的重新调用 [`DThdHandle::join()`] 方法。
161//!
162//! #### 通知并等待动态线程退出
163//!
164//! 方法 [`DThdHandle::stop()`] 等价于 [`DThdHandle::quit()`] + [`DThdHandle::join()`]
165//!
166//!
167//! ## 动态线程的示例
168//!
169//! [XWOS/xwam/xwrust-example/xwrust_example_dthd](https://gitee.com/xwos/XWOS/blob/main/xwam/xwrust-example/xwrust_example_dthd/src/lib.rs)
170//!
171//!
172//! ## 对比 [`std::thread`]
173//!
174//! #### 闭包原型不同
175//!
176//! + [`std::thread`] 的闭包原型是 `FnOnce() -> R` 。
177//! + `xwrust::xwos::thd` 的闭包原型是 `FnOnce(Arc<DThdElement>) -> R` 。
178//! + 【举例】 [`std::thread`] 通过 `thread::current()` 获取线程自己的`handle`,然后获取线程的名称:
179//!
180//! ```rust
181//! use std::thread;
182//!
183//! let handler = thread::DThdBuilder::new()
184//! .name("named thread".into())
185//! .spawn(|| {
186//! let handle = thread::current();
187//! assert_eq!(handle.name(), Some("named thread"));
188//! }).unwrap();
189//!
190//! handler.join().unwrap();
191//! ```
192//!
193//! + 【举例】 `xwrust::xwos::thd` 通过闭包参数 [`ele.name()`] 获取线程的名称:
194//!
195//! ```rust
196//! use xwrust::xwos::thd;
197//! use libc_print::std_name::println;
198//!
199//! thd::DThdBuilder::new()
200//! .name("foo".into())
201//! .spawn(|ele| {
202//! println!("Thread name: {}", ele.name());
203//! });
204//! ```
205//!
206//! 若不需要使用 `Arc<DThdElement>` ,可使用 `_` 占位。
207//!
208//! ```rust
209//! use xwrust::xwos::thd;
210//! use libc_print::std_name::println;
211//!
212//! thd::DThdBuilder::new()
213//! .name("foo".into())
214//! .spawn(|_| {
215//! // 线程闭包
216//! });
217//! ```
218//!
219//! #### **spawn()** 失败时的处理方式不同
220//!
221//! + [`std::thread`] **spawn()** 失败时,会直接 [`panic!()`] ;
222//! + XWOS是RTOS,运行环境是 `#![no_std]` , [`panic!()`] 意味着死机,因此需要处理 [`Err()`] ;
223//!
224//! ```rust
225//! use xwrust::xwos::thd;
226//!
227//! match thd::DThdBuilder::new()
228//! .name("child".into())
229//! .spawn(|ele| {
230//! // 子线程闭包
231//! }) {
232//! Ok(h) => { // 新建子线程成功
233//! },
234//! Err(rc) => { // 新建子线程失败
235//! },
236//! };
237//! ```
238//!
239//! #### 子线程 [`panic!()`] 的处理方式不同
240//!
241//! + [`std::thread`] 可捕获子线程的 [`panic!()`] 。
242//! + `xwrust::xwos::thd` 的子线程 [`panic!()`] 后会导致整个系统 **halt** 。
243//! 目前 `#![no_std]` 环境的 **unwind** 支持还不完善,暂时无法实现类似于 [`std::thread`] 的捕获机制。
244//!
245//!
246//! # 静态线程
247//!
248//! **静态线程** 是指 **不** 通过动态内存分配器创建的线程,所需内存全部由编译器在编译链接阶段分配。
249//! 设计 **静态线程** 的目的是为了避免使用动态内存分配。在功能安全的场合,动态内存分配是禁止使用的。
250//!
251//! 因为无法确定线程会运行多长时间,只能将 **静态线程** 定义为 **静态生命周期** 的全局变量。
252//!
253//!
254//! ```rust
255//! use xwrust::xwos::thd::*;
256//!
257//! static STHD: SThd<1024, &str> = SThd::new("SThd", true);
258//! pub fn xwrust_example_sthd() {
259//! let h = STHD.run(|sthd| { // 子线程
260//! // 线程功能
261//! "OK" // 返回值
262//! });
263//! let res = h.join();
264//! match res {
265//! Ok(r) => {
266//! // `r` 是线程的返回值。
267//! },
268//! Err(e) => {
269//! h = e;
270//! // `join()` 失败时的错误码可通过 `e.state()` 获取。
271//! // `e` 是 `SThdHandle` ,重新被返回。
272//! },
273//! };
274//!
275//! }
276//! ```
277//!
278//! 静态线程可以是 **可连接的(joinable)** 。当另一线程通过 [`SThd::run()`] 启动静态线程后,
279//! 可将返回的 [`SThdHandle`] 绑定在变量上,然后通过 [`SThdHandle::join()`] 方法等待静态线程运行结束并获取返回值。
280//!
281//!
282//! 当 [`SThdHandle`] 生命周期结束前, [`SThdHandle::join()`] 未被调用过,其 [`drop()`] 方法会将静态线程自动变成 **分离的(detached)** 。
283//!
284//!
285//! ## 静态线程的线程函数
286//!
287//! 定义RUST闭包时,实际上会生成一个隐藏的结构体,隐藏结构体中包括捕获的外部变量以及闭包函数。
288//! 闭包其实是这个隐藏结构体类型的变量,并且是在栈上建立的,其生命周期只限于函数局部。
289//! 因此,不能将闭包直接转移到静态线程的线程函数内部。
290//!
291//! 如何延长闭包生命周期?RUST语言的常用技巧是借助于 [`Box<T>`] 或 [`Arc<T>`] 将其放入堆中。
292//! 但若使用了 [`Box<T>`] 或 [`Arc<T>`] 就违背了 **不使用动态内存分配** 的初衷。
293//!
294//! 综上,静态线程的线程函数只能是 **普通函数** 或 **不捕获任何环境的闭包** 。
295//!
296//!
297//! 静态线程只能访问 **静态生命周期的全局变量** 。
298//! 其原型是 `fn(&Self) -> R` 。其中 `&Self` 是指向静态线程自身的引用, `R` 是泛型返回值。
299//!
300//!
301//! ## 静态线程的句柄
302//!
303//! 静态线程的句柄 [`SThdHandle`] 由方法 [`SThd::run()`] 返回,功能类似于 [`std::thread::JoinHandle`] ,可用于控制静态子线程的退出。
304//!
305//! #### 中断静态线程的阻塞态和睡眠态
306//!
307//! 方法 [`SThdHandle::intr()`] 可用于中断线程的 **阻塞态** 和 **睡眠态** 。
308//! 阻塞和睡眠的方法将以返回值 **负** 的 [`EINTR`] 退出。错误码 [`EINTR`] 会被转换为各个可阻塞线程的操作系统对象的错误码:
309//!
310//! + [`MutexError::Interrupt`]
311//! + [`SemError::Interrupt`]
312//! + [`CondError::Interrupt`]
313//! + [`FlgError::Interrupt`]
314//! + [`BrError::Interrupt`]
315//! + [`SelError::Interrupt`]
316//!
317//! 方法 [`SThdHandle::intr()`] 是基于 [`ThdD::intr()`] 实现的,调用后者与前者在功能上没有区别。
318//! 动态线程自身的 [`ThdD`] 可通过 [`cthd::i()`] 获取。
319//!
320//! #### 通知动态线程退出
321//!
322//! 方法 [`SThdHandle::quit()`] 可用于父线程通知静态子线程退出。此方法不会等待静态子线程退出。
323//!
324//! 方法 [`SThdHandle::quit()`] 是基于 [`SThd::quit()`] 实现的,调用后者与前者在功能上没有区别。后者可以由静态现在自己调用,自己通知自己退出。
325//!
326//! 方法 [`ThdD::quit()`] 也可达到同样的效果。静态态线程自身的 [`ThdD`] 可通过 [`cthd::i()`] 获取。
327//!
328//!
329//! 通知静态线程退出的方法会为静态子线程设置 **退出状态** ,并中断 **阻塞状态** 和 **睡眠状态** 。
330//! 阻塞和睡眠的方法将以返回值负的 [`EINTR`] 退出。错误码 [`EINTR`] 会被转换为各个可阻塞线程的操作系统对象的错误码:
331//!
332//! + [`MutexError::Interrupt`]
333//! + [`SemError::Interrupt`]
334//! + [`CondError::Interrupt`]
335//! + [`FlgError::Interrupt`]
336//! + [`BrError::Interrupt`]
337//! + [`SelError::Interrupt`]
338//!
339//! 但是,当静态子线程的 **阻塞状态** 是不可被中断的,方法 [`SThdHandle::quit()`] 只会为静态子线程设置 **退出状态** ,不会发生中断。
340//!
341//! 静态子线程可以通过 [`cthd::shld_stop()`] 判断是否被设置了 **退出状态** ,可以作为结束线程循环的条件。
342//!
343//! #### 等待动态线程退出
344//!
345//! 当父线程需要等待静态子线程退出,并捕获其返回值,需要使用方法 [`SThdHandle::join()`] 。
346//!
347//! + 如果静态子线程还在运行,此方法会阻塞父线程直到静态子线程退出。父线程的阻塞状态可被中断;
348//! + 如果静态子线程已经提前运行至退出,此方法可立即返回静态子线程的返回值。
349//!
350//! 此方法会消费 [`SThdHandle`] :
351//!
352//! + 如果此方法执行成功,会消费掉 [`SThdHandle`] ,并将静态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`SThdHandle`] 的生命周期也应该结束;
353//! + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`SThdHandle`] ,用户可通过 [`SThdHandle::state()`] 方法获取失败的原因,
354//! 并且在合适的时机重新调用 [`SThdHandle::join()`] 方法。
355//!
356//! #### 通知并等待动态线程退出
357//!
358//! 方法 [`SThdHandle::stop()`] 等价于 [`SThdHandle::quit()`] + [`SThdHandle::join()`]
359//!
360//!
361//! ## 静态线程的示例
362//!
363//! [XWOS/xwam/xwrust-example/xwrust_example_sthd](https://gitee.com/xwos/XWOS/blob/main/xwam/xwrust-example/xwrust_example_sthd/src/lib.rs)
364//!
365//!
366//! # 只可在线程自身函数内部调用的方法
367//!
368//! XWOS RUST有一组方法,只会对调用线程自身起作用,被实现在 [`xwrust::xwos::cthd`] 。命名中的 **c** 是 **current** 的意思。
369//!
370//!
371//! [`drop()`]: <https://doc.rust-lang.org/core/ops/trait.Drop.html#tymethod.drop>
372//! [`std::thread`]: <https://doc.rust-lang.org/std/thread/index.html>
373//! [`std::thread::JoinHandle`]: <https://doc.rust-lang.org/std/thread/struct.JoinHandle.html>
374//! [`panic!()`]: <https://doc.rust-lang.org/std/macro.panic.html>
375//! [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
376//! [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
377//! [`FnOnce()`]: <https://doc.rust-lang.org/core/ops/trait.FnOnce.html>
378//! [`ele.name()`]: DThdElement::name
379//! [`EINTR`]: crate::errno::EINTR
380//! [`MutexError::Interrupt`]: crate::xwos::lock::mtx::MutexError::Interrupt
381//! [`SemError::Interrupt`]: crate::xwos::sync::sem::SemError::Interrupt
382//! [`CondError::Interrupt`]: crate::xwos::sync::cond::CondError::Interrupt
383//! [`FlgError::Interrupt`]: crate::xwos::sync::flg::FlgError::Interrupt
384//! [`BrError::Interrupt`]: crate::xwos::sync::br::BrError::Interrupt
385//! [`SelError::Interrupt`]: crate::xwos::sync::sel::SelError::Interrupt
386//! [`cthd::i()`]: crate::xwos::cthd::i
387//! [`cthd::shld_stop()`]: crate::xwos::cthd::shld_stop
388//! [`xwrust::xwos::cthd`]: crate::xwos::cthd
389//! [`Box<T>`]: <https://doc.rust-lang.org/alloc/boxed/struct.Box.html>
390//! [`Arc<T>`]: <https://doc.rust-lang.org/alloc/sync/struct.Arc.html>
391
392extern crate core;
393use core::ffi::*;
394use core::option::Option;
395use core::result::Result;
396use core::cell::UnsafeCell;
397use core::ptr;
398use core::mem;
399use core::str;
400use core::fmt;
401
402extern crate alloc;
403use alloc::boxed::Box;
404use alloc::string::String;
405use alloc::sync::Arc;
406
407use crate::types::*;
408
409extern "C" {
410 fn xwrustffi_thd_stack_size_default() -> XwSz;
411 fn xwrustffi_thd_attr_init(attr: *mut ThdAttr);
412 fn xwrustffi_thd_create(thd: *mut *mut c_void, tik: *mut XwSq,
413 attr: *mut ThdAttr,
414 mainfunc: extern "C" fn(*mut c_void) -> XwEr,
415 arg: *mut c_void) -> XwEr;
416 fn xwrustffi_thd_init(thd: *mut c_void, tik: *mut XwSq,
417 attr: *const ThdAttr,
418 mainfunc: extern "C" fn(*mut c_void) -> XwEr,
419 arg: *mut c_void) -> XwEr;
420 fn xwrustffi_thd_acquire(thd: *mut c_void, tik: XwSq) -> XwEr;
421 fn xwrustffi_thd_release(thd: *mut c_void, tik: XwSq) -> XwEr;
422 fn xwrustffi_thd_intr(thd: *mut c_void, tik: XwSq) -> XwEr;
423 fn xwrustffi_thd_quit(thd: *mut c_void, tik: XwSq) -> XwEr;
424 fn xwrustffi_thd_join(thd: *mut c_void, tik: XwSq, trc: *mut XwEr) -> XwEr;
425 fn xwrustffi_thd_stop(thd: *mut c_void, tik: XwSq, trc: *mut XwEr) -> XwEr;
426 fn xwrustffi_thd_detach(thd: *mut c_void, tik: XwSq) -> XwEr;
427 fn xwrustffi_thd_migrate(thd: *mut c_void, tik: XwSq, cpuid: XwId) -> XwEr;
428}
429
430/// XWOS线程的属性
431///
432/// 完全等价于C语言头文件 `xwos/osal/thd.h` 中的 `struct xwos_thd_attr`
433#[repr(C)]
434pub(crate) struct ThdAttr {
435 /// 线程的名字
436 pub(crate) name: *const c_char,
437 /// 线程栈的首地址
438 pub(crate) stack: *mut XwStk,
439 /// 线程栈的大小,以字节(byte)为单位
440 pub(crate) stack_size: XwSz,
441 /// 栈内存警戒线位置
442 pub(crate) stack_guard_size: XwSz,
443 /// 优先级
444 pub(crate) priority: XwPr,
445 /// 是否为分离态
446 pub(crate) detached: bool,
447 /// 是否为特权线程
448 pub(crate) privileged: bool,
449}
450
451/// XWOS的线程对象描述符
452///
453/// 用于调用XWOS-CAPI
454pub struct ThdD {
455 /// XWOS线程对象的指针
456 pub thd: *mut c_void,
457 /// XWOS线程对象的标签
458 pub tik: XwSq,
459}
460
461unsafe impl Send for ThdD {}
462unsafe impl Sync for ThdD {}
463
464impl ThdD {
465 unsafe fn new(attr: &mut ThdAttr, func: Box<dyn FnOnce()>) -> Result<ThdD, XwEr> {
466 let boxboxfunc = Box::new(func);
467 let rawboxfunc = Box::into_raw(boxboxfunc);
468 let mut thd: *mut c_void = ptr::null_mut();
469 let mut tik: XwSq = 0;
470 let rc = xwrustffi_thd_create(&mut thd, &mut tik, attr,
471 ThdD::xwrust_dthd_entry, rawboxfunc as *mut _);
472 return if rc < 0 {
473 drop(Box::from_raw(rawboxfunc)); // 创建失败,需要释放f
474 Err(rc)
475 } else {
476 Ok(ThdD {thd: thd, tik: tik})
477 };
478 }
479
480 extern "C" fn xwrust_dthd_entry(main: *mut c_void) -> XwEr {
481 unsafe {
482 let func = Box::from_raw(main as *mut Box<dyn FnOnce()>);
483 func();
484 }
485 0
486 }
487
488 /// 中断线程的阻塞态和睡眠态
489 pub fn intr(&self) -> XwEr {
490 unsafe {
491 xwrustffi_thd_intr(self.thd, self.tik)
492 }
493 }
494
495 /// 通知线程退出
496 pub fn quit(&self) -> XwEr {
497 unsafe {
498 xwrustffi_thd_quit(self.thd, self.tik)
499 }
500 }
501
502 fn join(&mut self) ->XwEr {
503 unsafe {
504 xwrustffi_thd_join(self.thd, self.tik, ptr::null_mut())
505 }
506 }
507
508 fn stop(&mut self) -> XwEr {
509 unsafe {
510 xwrustffi_thd_stop(self.thd, self.tik, ptr::null_mut())
511 }
512 }
513
514 fn detach(&mut self) -> XwEr {
515 unsafe {
516 xwrustffi_thd_detach(self.thd, self.tik)
517 }
518 }
519
520 /// 将线程迁移到目标CPU
521 ///
522 /// # 参数说明
523 ///
524 /// + cpuid: 目标CPU的ID
525 pub fn migrate(&self, cpuid: XwId) -> XwEr {
526 unsafe {
527 xwrustffi_thd_migrate(self.thd, self.tik, cpuid)
528 }
529 }
530}
531
532impl fmt::Debug for ThdD {
533 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
534 f.debug_struct("ThdD")
535 .field("thd", &self.thd)
536 .field("tik", &self.tik)
537 .finish()
538 }
539}
540
541/// 线程的 `join()/stop()` 状态
542#[derive(Debug)]
543pub enum ThdJoinState {
544 /// 已经被连接
545 Joined,
546 /// 可被连接的
547 Joinable,
548 /// 连接错误
549 JoinErr(XwEr),
550}
551
552
553////////////////////////////////////////////////////////////////////////////////
554// 动态线程
555////////////////////////////////////////////////////////////////////////////////
556
557/// 动态线程的工厂模式结构体,可用于配置新线程的属性
558///
559/// + [`name`] 设置线程的名字
560/// + [`stack_size`] 设置线程的栈大小
561/// + [`privileged`] 设置线程的系统权限
562///
563/// [`spawn`] 方法将获取构建器的所有权,并使用给定的配置创建线程,返回 [`Result`] 。
564///
565/// [`thd::spawn`] 独立的函数,并使用默认配置的 `DThdBuilder`创建线程,返回 [`Result`] 。
566///
567///
568/// # 示例
569///
570/// ```rust
571/// use xwrust::xwos::thd;
572///
573/// let builder = thd::DThdBuilder::new();
574///
575/// builder.spawn(|_| {
576/// // 线程代码;
577/// // 返回值
578/// });
579/// ```
580///
581/// [`name`]: DThdBuilder::name
582/// [`stack_size`]: DThdBuilder::stack_size
583/// [`privileged`]: DThdBuilder::privileged
584/// [`spawn`]: DThdBuilder::spawn
585/// [`thd::spawn`]: spawn
586/// [`Result`]: <https://doc.rust-lang.org/core/result/enum.Result.html>
587pub struct DThdBuilder {
588 /// 线程的名字
589 name: Option<String>,
590 /// 线程栈的大小,以字节(byte)为单位
591 stack_size: Option<XwSz>,
592 /// 是否为特权线程
593 privileged: Option<bool>,
594}
595
596impl DThdBuilder {
597 /// 新建用于创建动态线程的工厂
598 ///
599 /// # 示例
600 ///
601 /// ```rust
602 /// use xwrust::xwos::thd;
603 ///
604 /// let builder = thd::DThdBuilder::new()
605 /// .name("foo".into()) // 设置线程的名称
606 /// .stack_size(8 * 1024) // 设置线程栈大小
607 /// .privileged(true); // 设置系统权限
608 ///
609 /// builder.spawn(|_| {
610 /// // 线程代码;
611 /// // 返回值
612 /// });
613 /// ```
614 pub fn new() -> DThdBuilder {
615 DThdBuilder {
616 name: None,
617 stack_size: None,
618 privileged: None,
619 }
620 }
621
622 /// 设置动态线程的名称
623 ///
624 /// # 示例
625 ///
626 /// ```rust
627 /// use xwrust::xwos::thd;
628 /// use libc_print::std_name::println;
629 ///
630 /// let builder = thd::DThdBuilder::new()
631 /// .name("foo".into()); // 设置线程的名称
632 ///
633 /// builder.spawn(|ele| {
634 /// println!("My name is {}.", ele.name().unwrap());
635 /// // 线程代码;
636 /// // 返回值
637 /// });
638 /// ```
639 pub fn name(mut self, name: String) -> DThdBuilder {
640 self.name = Some(name);
641 self
642 }
643
644 /// 设置动态线程栈的大小
645 ///
646 /// # 示例
647 ///
648 /// ```rust
649 /// use xwrust::xwos::thd;
650 ///
651 /// let builder = thd::DThdBuilder::new()
652 /// .stack_size(8 * 1024); // 设置线程栈大小
653 ///
654 /// builder.spawn(|_| {
655 /// // 线程代码;
656 /// // 返回值
657 /// });
658 /// ```
659 pub fn stack_size(mut self, size: XwSz) -> DThdBuilder {
660 self.stack_size = Some(size);
661 self
662 }
663
664 /// 设置动态线程栈的系统权限
665 ///
666 /// # 示例
667 ///
668 /// ```rust
669 /// use xwrust::xwos::thd;
670 ///
671 /// let builder = thd::DThdBuilder::new()
672 /// .privileged(true); // 设置系统权限
673 ///
674 /// builder.spawn(|_| {
675 /// // 线程代码;
676 /// // 返回值
677 /// });
678 /// ```
679 pub fn privileged(mut self, privileged: bool) -> DThdBuilder {
680 self.privileged = Some(privileged);
681 self
682 }
683
684 /// 消费 `DThdBuilder` ,并新建一个动态线程
685 ///
686 /// + 创建线程成功,返回一个包含 [`DThdHandle`] 的 [`Result`] ;
687 /// + 创建线程失败,返回一个包含 [`XwEr`] 的 [`Result`] , [`XwEr`] 指示错误的原因。
688 ///
689 /// 方法的签名:
690 ///
691 /// + [`'static`] 约束是因为新建的线程可能比调用者的生命周期更长,因此线程的闭包和返回值的生命周期限定为静态生命周期;
692 /// + [`Send`] 约束是因为闭包和返回值需要在线程之间进行转移。并且被移动到 [`Send`] 约束的闭包的变量也必须是 [`Send`] 的,否则编译器会报错。
693 /// RUSTC是通过 [`Send`] 约束来区分闭包是不是另一线程的代码的。
694 ///
695 /// # 参数说明
696 ///
697 /// + f: 线程的闭包
698 ///
699 /// # 示例
700 ///
701 /// ```rust
702 /// use xwrust::xwos::thd;
703 ///
704 /// let builder = thd::DThdBuilder::new()
705 /// .name("foo".into()) // 设置线程的名称
706 /// .stack_size(8 * 1024) // 设置线程栈大小
707 /// .privileged(true); // 设置系统权限
708 /// match builder.spawn(|_| {
709 /// // 线程代码;
710 /// // 返回值
711 /// }) {
712 /// Ok(handler) => {
713 /// match handler.join() {
714 /// Ok(r) => {
715 /// // r 是线程闭包的返回值。
716 /// },
717 /// Err(e) => {
718 /// // `join()` 失败的错误码可通过 `e.state()` 获取。
719 /// // `e` 是 `DThdHandle<R>` ,重新被返回。
720 /// },
721 /// };
722 /// },
723 /// Err(rc) => {
724 /// // `rc` 是 `spawn()` 失败时的错误码。
725 /// }
726 /// };
727 /// ```
728 /// [`Result`]: <https://doc.rust-lang.org/core/result/enum.Result.html>
729 /// [`'static`]: <https://doc.rust-lang.org/std/keyword.static.html>
730 /// [`Send`]: <https://doc.rust-lang.org/core/marker/trait.Send.html>
731 pub fn spawn<F, R>(self, f: F) -> Result<DThdHandle<R>, XwEr>
732 where
733 F: FnOnce(Arc<DThdElement>) -> R,
734 F: Send + 'static,
735 R: Send + 'static,
736 {
737 unsafe { self.spawn_unchecked(f) }
738 }
739
740 /// 消费 `DThdBuilder` ,并产生一个新的动态线程
741 ///
742 /// + 创建线程成功,返回一个包含 [`DThdHandle`] 的 [`Result`] ;
743 /// + 创建线程失败,返回一个包含 [`XwEr`] 的 [`Result`] , [`XwEr`] 指示错误的原因。
744 ///
745 /// 此方法只要求闭包 `F` 和 返回值 `R` 的生命周期一样长,然后不做其他限制,因此是 `unsafe` 的。
746 ///
747 /// # 参数说明
748 ///
749 /// + f: 线程的闭包
750 ///
751 /// # 示例
752 ///
753 /// ```rust
754 /// use xwrust::xwos::thd;
755 ///
756 /// let builder = thd::DThdBuilder::new()
757 /// .name("foo".into()) // 设置线程的名称
758 /// .stack_size(8 * 1024) // 设置线程栈大小
759 /// .privileged(true); // 设置系统权限
760 /// match unsafe { builder.spawn_unchecked(|_| {
761 /// // 线程代码;
762 /// // 返回值
763 /// })} {
764 /// Ok(handler) => {
765 /// match handler.join() {
766 /// Ok(r) => {
767 /// // r 是线程闭包的返回值。
768 /// },
769 /// Err(e) => {
770 /// // join() 失败时的错误码可通过 e.state() 获取。
771 /// // e 是 DThdHandle<R> ,重新被返回。
772 /// },
773 /// };
774 /// },
775 /// Err(rc) => {
776 /// // rc 是 spawn() 失败时的错误码。
777 /// }
778 /// };
779 /// ```
780 /// [`Result`]: <https://doc.rust-lang.org/core/result/enum.Result.html>
781 pub unsafe fn spawn_unchecked<'a, F, R>(self, f: F) -> Result<DThdHandle<R>, XwEr>
782 where
783 F: FnOnce(Arc<DThdElement>) -> R,
784 F: Send + 'a,
785 R: Send + 'a,
786 {
787 Ok(DThdHandle{inner: self.spawn_unchecked_(f)?})
788 }
789
790 unsafe fn spawn_unchecked_<'a, F, R>(self, f: F) -> Result<DThdHandleInner<R>, XwEr>
791 where
792 F: FnOnce(Arc<DThdElement>) -> R,
793 F: Send + 'a,
794 R: Send + 'a,
795 {
796 let mut attr: ThdAttr = mem::zeroed();
797 xwrustffi_thd_attr_init(&mut attr);
798 let name = self.name.unwrap_or("anon".into());
799 attr.stack_size = self.stack_size.unwrap_or(xwrustffi_thd_stack_size_default());
800 attr.privileged = self.privileged.unwrap_or(true);
801 let element: Arc<DThdElement> =
802 Arc::new(DThdElement::new(name, attr.stack_size, attr.privileged));
803 let thd_element = element.clone();
804
805 let retval: Arc<DThdReturnValue<R>> =
806 Arc::new(DThdReturnValue { result: UnsafeCell::new(None) });
807 let thd_retval = retval.clone();
808
809 let main = move || {
810 let result = f(thd_element);
811 *thd_retval.result.get() = Some(result);
812 };
813
814 Ok(DThdHandleInner {
815 thdd: ThdD::new(&mut attr,
816 mem::transmute::<Box<dyn FnOnce() + 'a>, Box<dyn FnOnce() + 'static>>(Box::new(main)))?,
817 state: ThdJoinState::Joinable,
818 element: element,
819 rv: retval,
820 })
821 }
822}
823
824/// 新建一个动态线程
825///
826/// + 创建线程成功,返回一个包含 [`DThdHandle`] 的 [`Result`] ;
827/// + 创建线程失败,返回一个包含 [`XwEr`] 的 [`Result`] , [`XwEr`] 指示错误的原因。
828///
829/// 此方法使用默认的线程工厂创建线程。
830///
831/// 当 [`DThdHandle`] 被 [`drop()`] 时,新建的线程会变成 **detached(分离的)** 。此时,新建的线程不能再被 [`join()`] 。
832///
833/// 方法的签名:
834///
835/// + [`'static`] 约束是因为新建的线程可能比调用者的生命周期更长,因此线程的闭包和返回值的生命周期限定为静态生命周期;
836/// + [`Send`] 约束是因为闭包和返回值需要在线程之间进行转移。并且被移动到 [`Send`] 约束的闭包的变量也必须是 [`Send`] 的,否则编译器会报错。
837/// RUSTC是通过 [`Send`] 约束来区分闭包是不是另一线程的代码的。
838///
839/// # 参数说明
840///
841/// + f: 线程的闭包
842///
843/// # 示例
844///
845/// ```rust
846/// use xwrust::xwos::thd;
847///
848/// match thd::spawn(|_| {
849/// // 线程代码;
850/// // 返回值
851/// }) {
852/// Ok(handler) => {
853/// match handler.join() {
854/// Ok(r) => {
855/// // r 是线程闭包的返回值。
856/// },
857/// Err(e) => {
858/// // join() 失败时的错误码可通过 e.state() 获取。
859/// // e 是 DThdHandle<R> ,重新被返回。
860/// },
861/// };
862/// },
863/// Err(rc) => {
864/// // rc 是 spawn() 失败时的错误码。
865/// },
866/// };
867/// ```
868/// [`Result`]: <https://doc.rust-lang.org/core/result/enum.Result.html>
869/// [`drop()`]: <https://doc.rust-lang.org/core/ops/trait.Drop.html#tymethod.drop>
870/// [`join()`]: DThdHandle::join
871/// [`'static`]: <https://doc.rust-lang.org/std/keyword.static.html>
872/// [`Send`]: <https://doc.rust-lang.org/core/marker/trait.Send.html>
873pub fn spawn<F, R>(f: F) -> Result<DThdHandle<R>, XwEr>
874where
875 F: FnOnce(Arc<DThdElement>) -> R,
876 F: Send + 'static,
877 R: Send + 'static,
878{
879 DThdBuilder::new().spawn(f)
880}
881
882/// 动态线程的元素
883///
884/// 动态线程的元素中的数据需跨线程共享,因此在定义时需要使用 [`Arc`] 进行封装。
885///
886/// [`Arc`]: <https://doc.rust-lang.org/alloc/sync/struct.Arc.html>
887pub struct DThdElement {
888 /// 线程的名字
889 name: String,
890 /// 线程栈的大小,以字节(byte)为单位
891 stack_size: XwSz,
892 /// 是否为特权线程
893 privileged: bool,
894}
895
896impl DThdElement {
897 pub(crate) fn new(name: String,
898 stack_size: XwSz,
899 privileged: bool) -> DThdElement {
900 DThdElement {
901 name,
902 stack_size,
903 privileged
904 }
905 }
906
907 /// 返回动态线程名字的引用
908 ///
909 /// # 示例
910 ///
911 /// ```rust
912 /// use xwrust::xwos::thd;
913 /// use libc_print::std_name::println;
914 ///
915 /// let handler = thd::DThdBuilder::new()
916 /// .name("foo".into())
917 /// .spawn(|ele| {
918 /// println!("Thread name: {}", ele.name());
919 /// });
920 /// ```
921 pub fn name(&self) -> &str {
922 &self.name
923 }
924
925 /// 返回动态线程的栈大小
926 ///
927 /// # 示例
928 ///
929 /// ```rust
930 /// use xwrust::xwos::thd;
931 /// use libc_print::std_name::println;
932 ///
933 /// let handler = thd::DThdBuilder::new()
934 /// .spawn(|ele| {
935 /// println!("Thread stack size: {}", ele.stack_size()); // 将返回默认线程大小
936 /// });
937 /// ```
938 pub fn stack_size(&self) -> XwSz {
939 self.stack_size
940 }
941
942 /// 返回动态线程是否具有特权
943 ///
944 /// # 示例
945 ///
946 /// ```rust
947 /// use xwrust::xwos::thd;
948 /// use libc_print::std_name::println;
949 ///
950 /// let handler = thd::DThdBuilder::new()
951 /// .privileged(true);
952 /// .spawn(|ele| {
953 /// println!("Thread is privileged: {} .", ele.privileged());
954 /// });
955 /// ```
956 pub fn privileged(&self) -> bool {
957 self.privileged
958 }
959}
960
961impl fmt::Debug for DThdElement {
962 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
963 f.debug_struct("DThdElement")
964 .field("name", &self.name)
965 .finish()
966 }
967}
968
969/// 动态线程的返回值
970///
971/// 动态线程的返回值中的数据需跨线程共享,因此在定义时需要使用 [`Arc`] 进行封装。
972///
973/// [`Arc`]: <https://doc.rust-lang.org/alloc/sync/struct.Arc.html>
974struct DThdReturnValue<R> {
975 result: UnsafeCell<Option<R>>,
976}
977
978unsafe impl<R: Sync> Sync for DThdReturnValue<R> {}
979
980
981struct DThdHandleInner<R> {
982 /// XWOS线程的描述符
983 thdd: ThdD,
984 /// 线程的 `join()/stop()` 状态
985 state: ThdJoinState,
986 /// 线程的元素
987 element: Arc<DThdElement>,
988 /// 线程的返回值
989 rv: Arc<DThdReturnValue<R>>,
990}
991
992impl<R> DThdHandleInner<R> {
993 fn intr(&self) -> XwEr {
994 self.thdd.intr()
995 }
996
997 fn quit(&self) -> XwEr {
998 self.thdd.quit()
999 }
1000
1001 fn join(mut self) -> Result<R, Self> {
1002 let rc = self.thdd.join();
1003 if rc == 0 {
1004 self.state = ThdJoinState::Joined;
1005 Ok(Arc::get_mut(&mut self.rv).unwrap().result.get_mut().take().unwrap())
1006 } else {
1007 self.state = ThdJoinState::JoinErr(rc);
1008 Err(self)
1009 }
1010 }
1011
1012 fn stop(mut self) -> Result<R, Self> {
1013 let rc = self.thdd.stop();
1014 if rc == 0 {
1015 self.state = ThdJoinState::Joined;
1016 Ok(Arc::get_mut(&mut self.rv).unwrap().result.get_mut().take().unwrap())
1017 } else {
1018 self.state = ThdJoinState::JoinErr(rc);
1019 Err(self)
1020 }
1021 }
1022}
1023
1024impl<R> Drop for DThdHandleInner<R> {
1025 fn drop(&mut self) {
1026 match self.state {
1027 ThdJoinState::Joined => {
1028 },
1029 _ => {
1030 self.thdd.detach();
1031 },
1032 };
1033 }
1034}
1035
1036impl<R> fmt::Debug for DThdHandleInner<R> {
1037 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1038 f.debug_struct("DThdHandleInner")
1039 .field("thdd", &self.thdd)
1040 .field("state", &self.state)
1041 .field("element", &self.element)
1042 .finish_non_exhaustive()
1043 }
1044}
1045
1046/// 动态线程的句柄
1047pub struct DThdHandle<R> {
1048 inner: DThdHandleInner<R>
1049}
1050
1051unsafe impl<R> Send for DThdHandle<R> {}
1052unsafe impl<R> Sync for DThdHandle<R> {}
1053
1054impl<R> DThdHandle<R> {
1055 /// 返回XWOS的线程对象描述符
1056 ///
1057 /// 线程对象描述符用于与C语言交互。
1058 pub fn thdd(&self) -> &ThdD {
1059 &self.inner.thdd
1060 }
1061
1062 /// 返回线程的元素
1063 pub fn element(&self) -> &DThdElement {
1064 &self.inner.element
1065 }
1066
1067 /// 中断线程的阻塞态和睡眠态
1068 ///
1069 /// 此方法用于中断线程的 **阻塞态** 和 **睡眠态** 。
1070 ///
1071 /// # 上下文
1072 ///
1073 /// + 线程、中断、中断底半部、空闲任务
1074 pub fn intr(&self) -> XwEr {
1075 self.inner.intr()
1076 }
1077
1078 /// 通知动态线程退出
1079 ///
1080 /// 此方法用于向线程设置 **退出状态** 。
1081 ///
1082 /// 调用此方法的线程不会等待被设置 **退出状态** 的线程退出。
1083 ///
1084 /// 此方法可被重复调用,线程的 **退出状态** 一旦被设置,不可被清除。
1085 ///
1086 /// # 上下文
1087 ///
1088 /// + 线程、中断、中断底半部、空闲任务
1089 pub fn quit(&self) -> XwEr {
1090 self.inner.quit()
1091 }
1092
1093 /// 等待动态线程运行至退出,并返回线程的返回值
1094 ///
1095 /// + 如果动态子线程还在运行,此方法会阻塞父线程直到动态子线程退出。父线程的阻塞状态可被中断;
1096 /// + 如果动态子线程已经提前运行至退出,此方法可立即返回动态子线程的返回值。
1097 ///
1098 /// 此方法会消费 [`self`] :
1099 ///
1100 /// + 如果此方法执行成功,会消费掉 [`self`] ,并将动态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`DThdHandle`] 的生命周期也应该结束;
1101 /// + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`self`] ,并可通过 [`DThdHandle::state()`] 方法获取失败的原因。
1102 ///
1103 /// # 上下文
1104 ///
1105 /// + 线程
1106 ///
1107 /// # 示例
1108 ///
1109 /// ```rust
1110 /// use xwrust::xwos::thd;
1111 ///
1112 /// match thd::spawn(|_| {
1113 /// // 线程代码;
1114 /// // 返回值
1115 /// }) {
1116 /// Ok(handler) => {
1117 /// match handler.join() {
1118 /// Ok(r) => {
1119 /// // r 是线程闭包的返回值。
1120 /// },
1121 /// Err(e) => {
1122 /// // `join()` 失败时的错误码可通过 `e.state()` 获取。
1123 /// // `e` 是 `DThdHandle<R>` ,重新被返回。
1124 /// },
1125 /// };
1126 /// },
1127 /// Err(rc) => {
1128 /// // rc 是 spawn() 失败时的错误码。
1129 /// },
1130 /// };
1131 /// ```
1132 ///
1133 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1134 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1135 pub fn join(self) -> Result<R, Self> {
1136 match self.inner.join() {
1137 Ok(r) => Ok(r),
1138 Err(e) => Err(Self{inner: e}),
1139 }
1140 }
1141
1142 /// 终止动态线程并等待线程运行至退出,并返回线程的返回值
1143 ///
1144 /// + 如果动态子线程还在运行,此方法会阻塞父线程直到动态子线程退出。父线程的阻塞状态可被中断;
1145 /// + 如果动态子线程已经提前运行至退出,此方法可立即返回动态子线程的返回值。
1146 ///
1147 /// 此方法 = [`DThdHandle::quit()`] + [`DThdHandle::join()`]
1148 ///
1149 ///
1150 /// 此方法会消费 [`self`] :
1151 ///
1152 /// + 如果此方法执行成功,会消费掉 [`self`] ,并将动态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`DThdHandle`] 的生命周期也应该结束;
1153 /// + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`self`] ,并可通过 [`DThdHandle::state()`] 方法获取失败的原因。
1154 ///
1155 /// # 上下文
1156 ///
1157 /// + 线程
1158 ///
1159 /// # 示例
1160 ///
1161 /// ```rust
1162 /// use xwrust::xwos::thd;
1163 ///
1164 /// match thd::spawn(|_| {
1165 /// // 线程代码;
1166 /// // 返回值
1167 /// }) {
1168 /// Ok(handler) => {
1169 /// match handler.stop() {
1170 /// Ok(r) => {
1171 /// // r 是线程闭包的返回值。
1172 /// },
1173 /// Err(e) => {
1174 /// // `stop()` 失败时的错误码可通过 `e.state()` 获取。
1175 /// // `e` 是 `DThdHandle<R>` ,重新被返回。
1176 /// },
1177 /// };
1178 /// },
1179 /// Err(rc) => {
1180 /// // rc 是 spawn() 失败时的错误码。
1181 /// },
1182 /// };
1183 /// ```
1184 ///
1185 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1186 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1187 pub fn stop(self) -> Result<R, Self> {
1188 match self.inner.stop() {
1189 Ok(r) => Ok(r),
1190 Err(e) => Err(Self{inner: e}),
1191 }
1192 }
1193
1194 /// 返回动态线程的 `join()/stop()` 状态
1195 pub fn state<'a>(&'a self) -> &'a ThdJoinState {
1196 &self.inner.state
1197 }
1198
1199 /// 检查关联的动态线程是否运行结束
1200 ///
1201 /// 此方法不会阻塞调用者。
1202 pub fn finished(&self) -> bool {
1203 Arc::strong_count(&self.inner.rv) == 1
1204 }
1205}
1206
1207impl<R> fmt::Debug for DThdHandle<R> {
1208 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1209 f.debug_struct("DThdHandle")
1210 .field("inner", &self.inner)
1211 .finish_non_exhaustive()
1212 }
1213}
1214
1215
1216////////////////////////////////////////////////////////////////////////////////
1217// 静态线程
1218////////////////////////////////////////////////////////////////////////////////
1219/// XWOS线程对象占用的内存大小
1220#[cfg(target_pointer_width = "32")]
1221pub const SIZEOF_XWOS_THD: usize = 280;
1222
1223/// XWOS线程占用的内存大小
1224#[cfg(target_pointer_width = "64")]
1225pub const SIZEOF_XWOS_THD: usize = 560;
1226
1227/// 用于构建线程对象的内存数组类型
1228#[repr(C)]
1229#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
1230#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
1231pub(crate) struct XwosThd
1232{
1233 pub(crate) obj: [u8; SIZEOF_XWOS_THD],
1234}
1235
1236/// 用于构建线程栈的内存数组类型
1237#[repr(C)]
1238#[cfg_attr(target_pointer_width = "32", repr(align(8)))]
1239#[cfg_attr(target_pointer_width = "64", repr(align(16)))]
1240pub(crate) struct XwosThdStack<const N: XwSz>
1241where
1242 [XwStk; N]: Sized
1243{
1244 pub(crate) stk: [XwStk; N],
1245}
1246
1247/// 静态线程对象结构体
1248///
1249/// 此结构体用于创建具有 [`'static`] 生命周期的线程对象。
1250///
1251/// [`'static`]: <https://doc.rust-lang.org/std/keyword.static.html>
1252pub struct SThd<const N: XwSz, R>
1253where
1254 [XwStk; N]: Sized,
1255 R: Send
1256{
1257 /// 线程对象
1258 pub(crate) thd: UnsafeCell<XwosThd>,
1259 /// 线程的栈
1260 pub(crate) stk: UnsafeCell<XwosThdStack<N>>,
1261 /// 线程的名字
1262 pub(crate) name: &'static str,
1263 /// 线程是否为特权线程
1264 pub(crate) privileged: UnsafeCell<bool>,
1265 /// 线程的函数
1266 pub(crate) func: UnsafeCell<Option<fn(&Self) -> R>>,
1267 /// 线程对象的标签
1268 pub(crate) tik: UnsafeCell<XwSq>,
1269 /// 线程的执行结果
1270 pub(crate) result: UnsafeCell<Option<R>>,
1271}
1272
1273impl<const N: XwSz, R> SThd<N, R>
1274where
1275 [XwStk; N]: Sized,
1276 R: Send
1277{
1278 /// 新建静态线程对象
1279 ///
1280 /// 此方法是编译期方法。
1281 ///
1282 /// # 参数说明
1283 ///
1284 /// + name: 线程的名字
1285 /// + privileged: 线程的是否具有系统特权
1286 ///
1287 /// # 示例
1288 ///
1289 /// ```rust
1290 /// use xwrust::xwos::thd::*;
1291 ///
1292 /// // 线程栈:1024 * 4; 线程返回值类型:&str;线程名字:"SThd";是否为特权线程:true;
1293 /// static STHD: SThd<1024, &str> = SThd::new("SThd", true);
1294 /// ```
1295 pub const fn new(name: &'static str, privileged: bool) -> Self {
1296 Self {
1297 thd: UnsafeCell::new(XwosThd{obj: [0; SIZEOF_XWOS_THD]}),
1298 stk: UnsafeCell::new(XwosThdStack{stk: [0; N]}),
1299 name: name,
1300 privileged: UnsafeCell::new(privileged),
1301 func: UnsafeCell::new(None),
1302 tik: UnsafeCell::new(0),
1303 result: UnsafeCell::new(None),
1304 }
1305 }
1306
1307 /// 以线程函数 `f` 启动静态线程
1308 ///
1309 /// 此方法限定了参数的 [`&'static self`] ,因此若试图在函数局部定义静态线程,
1310 /// 调用此方法时,编译器会提示错误:生命周期不够长。
1311 ///
1312 /// 此约束的目的是让用户只能在函数外部定义静态线程对象。
1313 ///
1314 ///
1315 /// # 线程函数
1316 ///
1317 /// 线程函数的原型为 `fn(&Self) -> R` ,线程运行时,系统会以静态线程自身的引用作为参数调用线程函数 `f` 。
1318 ///
1319 /// 用户可通过此引用调用线程的方法或访问线程的名字,栈大小等信息。
1320 ///
1321 /// # 返回值
1322 ///
1323 /// 此方法会返回静态线程的句柄 [`SThdHandle<'a, N, R>`] ,通过此句柄,其他线程可通知此线程退出并获取返回值。
1324 ///
1325 ///
1326 /// # 上下文
1327 ///
1328 /// + 线程、中断、中断底半部、空闲任务
1329 ///
1330 ///
1331 /// # 示例
1332 ///
1333 /// ```rust
1334 /// use xwrust::xwos::thd::*;
1335 ///
1336 /// static STHD: SThd<1024, &str> = SThd::new("SThd", true);
1337 /// pub fn xwrust_example_sthd() {
1338 /// STHD.run(|sthd| { // 子线程
1339 /// // 线程功能
1340 /// "OK" // 返回值
1341 /// });
1342 /// }
1343 /// ```
1344 pub fn run<'a>(&'static self, f: fn(&Self) -> R) -> SThdHandle<'a, N, R> {
1345 unsafe {
1346 let mut attr: ThdAttr = mem::zeroed();
1347 xwrustffi_thd_attr_init(&mut attr);
1348 attr.stack = self.stk.get() as _;
1349 attr.stack_size = N * (XwStk::BITS / 8) as XwSz;
1350 attr.privileged = *self.privileged.get();
1351 (*self.func.get()) = Some(f);
1352 xwrustffi_thd_init(self.thd.get() as _, self.tik.get(), &attr,
1353 SThd::<N, R>::xwrust_sthd_entry,
1354 self as *const Self as *mut c_void);
1355
1356 SThdHandle {
1357 sthd: UnsafeCell::new(self),
1358 state: ThdJoinState::Joinable,
1359 }
1360 }
1361 }
1362
1363 extern "C" fn xwrust_sthd_entry(arg: *mut c_void) -> XwEr {
1364 unsafe {
1365 let thd: &Self = &*(arg as *const Self);
1366 let func = (*thd.func.get()).unwrap_or_else(|| unreachable!());
1367 *(thd.result.get()) = Some(func(thd));
1368 }
1369 0
1370 }
1371
1372 /// 返回静态线程名字的引用
1373 ///
1374 /// # 上下文
1375 ///
1376 /// + 任意
1377 pub fn name(&self) -> &str {
1378 self.name
1379 }
1380
1381 /// 返回静态线程是否具有特权
1382 ///
1383 /// # 上下文
1384 ///
1385 /// + 任意
1386 pub fn privileged(&self) -> bool {
1387 unsafe {
1388 *self.privileged.get()
1389 }
1390 }
1391
1392 /// 返回静态线程的栈大小
1393 ///
1394 /// # 上下文
1395 ///
1396 /// + 任意
1397 pub const fn stack_size(&self) -> XwSz {
1398 N * (XwStk::BITS / 8) as XwSz
1399 }
1400
1401 /// 中断线程的阻塞态和睡眠态
1402 ///
1403 /// 此方法用于中断线程的 **阻塞状态** 和 **睡眠状态** 。
1404 ///
1405 /// # 上下文
1406 ///
1407 /// + 线程、中断、中断底半部、空闲任务
1408 pub fn intr(&self) -> XwEr {
1409 unsafe {
1410 xwrustffi_thd_intr(self.thd.get() as _, *self.tik.get())
1411 }
1412 }
1413
1414 /// 通知静态线程退出
1415 ///
1416 /// 此方法用于向线程设置 **退出状态** 。
1417 ///
1418 /// 调用此方法的线程不会等待被设置 **退出状态** 的线程退出。
1419 ///
1420 /// 此方法可被重复调用,线程的 **退出状态** 一旦被设置,不可被清除。
1421 ///
1422 /// # 上下文
1423 ///
1424 /// + 线程、中断、中断底半部、空闲任务
1425 pub fn quit(&self) -> XwEr {
1426 unsafe {
1427 xwrustffi_thd_quit(self.thd.get() as _, *self.tik.get())
1428 }
1429 }
1430
1431 fn join(&self) ->XwEr {
1432 unsafe {
1433 xwrustffi_thd_join(self.thd.get() as _, *self.tik.get(), ptr::null_mut())
1434 }
1435 }
1436
1437 fn stop(&self) -> XwEr {
1438 unsafe {
1439 xwrustffi_thd_stop(self.thd.get() as _, *self.tik.get(), ptr::null_mut())
1440 }
1441 }
1442
1443 fn detach(&self) -> XwEr {
1444 unsafe {
1445 xwrustffi_thd_detach(self.thd.get() as _, *self.tik.get())
1446 }
1447 }
1448
1449 /// 将线程迁移到目标CPU。
1450 pub fn migrate(&self, cpuid: XwId) -> XwEr {
1451 unsafe {
1452 xwrustffi_thd_migrate(self.thd.get() as _, *self.tik.get(), cpuid)
1453 }
1454 }
1455}
1456
1457impl<const N: XwSz, R> !Send for SThd<N, R>
1458where
1459 [XwStk; N]: Sized,
1460 R: Send
1461{}
1462
1463unsafe impl<const N: XwSz, R> Sync for SThd<N, R>
1464where
1465 [XwStk; N]: Sized,
1466 R: Send
1467{}
1468
1469/// 静态线程的句柄
1470pub struct SThdHandle<'a, const N: XwSz, R>
1471where
1472 [XwStk; N]: Sized,
1473 R: Send
1474{
1475 /// 线程的引用
1476 sthd: UnsafeCell<&'a SThd<N, R>>,
1477 /// 静态线程的 `join()/stop()` 状态
1478 state: ThdJoinState,
1479}
1480
1481unsafe impl<'a, const N: XwSz, R> Send for SThdHandle<'a, N, R>
1482where
1483 [XwStk; N]: Sized,
1484 R: Send
1485{}
1486
1487unsafe impl<'a, const N: XwSz, R> Sync for SThdHandle<'a, N, R>
1488where
1489 [XwStk; N]: Sized,
1490 R: Send
1491{}
1492
1493impl<'a, const N: XwSz, R> SThdHandle<'a, N, R>
1494where
1495 [XwStk; N]: Sized,
1496 R: Send
1497{
1498 /// 中断线程的阻塞态和睡眠态
1499 ///
1500 /// 此方法用于中断线程的 **阻塞状态** 和 **睡眠状态** 。
1501 ///
1502 /// # 上下文
1503 ///
1504 /// + 线程、中断、中断底半部、空闲任务
1505 pub fn intr(&self) -> XwEr {
1506 unsafe {
1507 (*(self.sthd.get())).intr()
1508 }
1509 }
1510
1511 /// 通知静态线程退出
1512 ///
1513 /// 此方法用于向线程设置 **退出状态** 。
1514 ///
1515 /// 调用此方法的线程不会等待被设置 **退出状态** 的线程退出。
1516 ///
1517 /// 此方法可被重复调用,线程的 **退出状态** 一旦被设置,不可被清除。
1518 ///
1519 /// # 上下文
1520 ///
1521 /// + 线程、中断、中断底半部、空闲任务
1522 pub fn quit(&self) -> XwEr {
1523 unsafe {
1524 (*(self.sthd.get())).quit()
1525 }
1526 }
1527
1528 /// 等待静态线程运行至退出,并返回线程的返回值
1529 ///
1530 /// + 如果静态子线程还在运行,此方法会阻塞父线程直到静态子线程退出。父线程的阻塞状态可被中断;
1531 /// + 如果静态子线程已经提前运行至退出,此方法可立即返回静态子线程的返回值。
1532 ///
1533 /// 此方法会消费 [`self`] :
1534 ///
1535 /// + 如果此方法执行成功,会消费掉 [`self`] ,并将静态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`SThdHandle`] 的生命周期也应该结束;
1536 /// + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`self`] ,并可通过 [`SThdHandle::state()`] 方法获取失败的原因。
1537 ///
1538 /// # 上下文
1539 ///
1540 /// + 线程
1541 ///
1542 /// # 示例
1543 ///
1544 /// ```rust
1545 /// use xwrust::xwos::thd::*;
1546 ///
1547 /// static STHD: SThd<1024, &str> = SThd::new("SThd", true);
1548 ///
1549 /// pub fn xwrust_example_sthd() {
1550 /// let mut h = STHD.run(|_| {
1551 /// // 线程功能
1552 /// "Ok" // 返回值
1553 /// });
1554 /// let res = h.join();
1555 /// match res {
1556 /// Ok(r) => {
1557 /// // `r` 是线程的返回值。
1558 /// },
1559 /// Err(e) => {
1560 /// h = e;
1561 /// // `join()` 失败时的错误码可通过 `e.state()` 获取。
1562 /// // `e` 是 `SThdHandle<'a, N, R>` ,重新被返回。
1563 /// },
1564 /// };
1565 /// }
1566 /// ```
1567 ///
1568 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1569 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1570 pub fn join(mut self) -> Result<R, Self> {
1571 unsafe {
1572 let rc = (*(self.sthd.get())).join();
1573 if rc == 0 {
1574 self.state = ThdJoinState::Joined;
1575 Ok((*(self.sthd.get_mut().result.get())).take().unwrap())
1576 } else {
1577 self.state = ThdJoinState::JoinErr(rc);
1578 Err(self)
1579 }
1580 }
1581 }
1582
1583 /// 终止静态线程并等待线程运行至退出,并返回线程的返回值
1584 ///
1585 /// + 如果静态子线程还在运行,此方法会阻塞父线程直到静态子线程退出。父线程的阻塞状态可被中断;
1586 /// + 如果静态子线程已经提前运行至退出,此方法可立即返回静态子线程的返回值。
1587 ///
1588 /// 此方法 = [`SThdHandle::quit()`] + [`SThdHandle::join()`]
1589 ///
1590 ///
1591 /// 此方法会消费 [`self`] :
1592 ///
1593 /// + 如果此方法执行成功,会消费掉 [`self`] ,并将静态子线程的返回值放在 [`Ok()`] 中返回,因为线程已经结束,其 [`SThdHandle`] 的生命周期也应该结束;
1594 /// + 如果此方法执行失败,会重新在 [`Err()`] 中返回 [`self`] ,并可通过 [`SThdHandle::state()`] 方法获取失败的原因。
1595 ///
1596 /// # 上下文
1597 ///
1598 /// + 线程
1599 ///
1600 /// # 示例
1601 ///
1602 /// ```rust
1603 /// use xwrust::xwos::thd::*;
1604 ///
1605 /// static STHD: SThd<1024, &str> = SThd::new("SThd", true);
1606 ///
1607 /// pub fn xwrust_example_sthd() {
1608 /// let mut h = STHD.run(|_| {
1609 /// // 线程代码;
1610 /// "Ok"
1611 /// });
1612 /// let res = h.stop();
1613 /// match res {
1614 /// Ok(r) => {
1615 /// // `r` 是线程的返回值。
1616 /// },
1617 /// Err(e) => {
1618 /// h = e;
1619 /// // `stop()` 失败时的错误码可通过 `e.state()` 获取。
1620 /// // `e` 是 `SThdHandle<'a, N, R>` ,重新被返回。
1621 /// },
1622 /// };
1623 /// }
1624 /// ```
1625 ///
1626 /// [`Ok()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Ok>
1627 /// [`Err()`]: <https://doc.rust-lang.org/core/result/enum.Result.html#variant.Err>
1628 pub fn stop(mut self) -> Result<R, Self> {
1629 unsafe {
1630 let rc = (*(self.sthd.get())).stop();
1631 if rc == 0 {
1632 self.state = ThdJoinState::Joined;
1633 Ok((*(self.sthd.get_mut().result.get())).take().unwrap())
1634 } else {
1635 self.state = ThdJoinState::JoinErr(rc);
1636 Err(self)
1637 }
1638 }
1639 }
1640
1641 /// 返回线程的 `join()/stop()` 状态
1642 pub fn state(&self) -> &ThdJoinState {
1643 &self.state
1644 }
1645}
1646
1647impl<'a, const N: XwSz, R>Drop for SThdHandle<'a, N, R>
1648where
1649 [XwStk; N]: Sized,
1650 R: Send
1651{
1652 fn drop(&mut self) {
1653 match self.state {
1654 ThdJoinState::Joined => {
1655 },
1656 _ => {
1657 unsafe {
1658 (*(self.sthd.get())).detach();
1659 }
1660 },
1661 };
1662 }
1663}