thread.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-10-10 foxglove RT-Thread Thread implementation
  9. */
  10. use crate::alloc::boxed::Box;
  11. use crate::api::*;
  12. use crate::{RTResult, RTTError};
  13. use alloc::string::String;
  14. use core::mem;
  15. use core::ffi::c_void;
  16. #[derive(Debug)]
  17. pub struct Thread(APIRawThread);
  18. impl Thread {
  19. pub fn delay(tick: usize) {
  20. let _ = thread_delay(tick);
  21. }
  22. pub fn ms_delay(ms: usize) {
  23. let _ = thread_m_delay(ms as i32);
  24. }
  25. pub fn new() -> ThreadBuilder {
  26. ThreadBuilder {
  27. th_name: "Unnamed".into(),
  28. th_stack_size: 4096,
  29. th_priority: 10,
  30. th_ticks: 10,
  31. }
  32. }
  33. pub fn r#yield() {
  34. thread_yield();
  35. }
  36. pub fn delete_thread(th: Self) {
  37. let _ = thread_delete(th.0);
  38. }
  39. pub fn delete(&self) {
  40. let _ = thread_delete(self.0);
  41. }
  42. unsafe fn spawn_inner(
  43. name: String,
  44. stack_size: u32,
  45. priority: u8,
  46. ticks: u32,
  47. func: Box<dyn FnOnce()>,
  48. ) -> Result<Self, RTTError> {
  49. let func = Box::new(func);
  50. let param = &*func as *const _ as *mut _;
  51. extern "C" fn thread_func(param: *mut c_void) {
  52. unsafe {
  53. let run = Box::from_raw(param as *mut Box<dyn FnOnce()>);
  54. run();
  55. }
  56. }
  57. let th_handle = thread_create(
  58. name.as_ref(),
  59. thread_func,
  60. param,
  61. stack_size,
  62. priority,
  63. ticks,
  64. )
  65. .ok_or(RTTError::OutOfMemory)?;
  66. let ret = match Self::_startup(th_handle) {
  67. Ok(_) => {
  68. mem::forget(func);
  69. Ok(Thread(th_handle))
  70. }
  71. Err(e) => Err(e),
  72. };
  73. return ret;
  74. }
  75. fn _startup(th: APIRawThread) -> Result<(), RTTError> {
  76. let ret = thread_startup(th);
  77. return if is_eok(ret) {
  78. Ok(())
  79. } else {
  80. Err(RTTError::ThreadStartupErr)
  81. };
  82. }
  83. pub fn spawn<F>(
  84. name: String,
  85. stack_size: u32,
  86. priority: u8,
  87. ticks: u32,
  88. func: F,
  89. ) -> RTResult<Thread>
  90. where
  91. F: FnOnce() -> () + Send + 'static,
  92. {
  93. unsafe { Self::spawn_inner(name, stack_size, priority, ticks, Box::new(func)) }
  94. }
  95. }
  96. unsafe impl Send for Thread {}
  97. pub struct ThreadBuilder {
  98. th_name: String,
  99. th_stack_size: u32,
  100. th_priority: u8,
  101. th_ticks: u32,
  102. }
  103. impl ThreadBuilder {
  104. pub fn name(&mut self, name: &str) -> &mut Self {
  105. self.th_name = name.into();
  106. self
  107. }
  108. pub fn stack_size(&mut self, stack_size: u32) -> &mut Self {
  109. self.th_stack_size = stack_size;
  110. self
  111. }
  112. pub fn priority(&mut self, priority: u8) -> &mut Self {
  113. self.th_priority = priority;
  114. self
  115. }
  116. pub fn ticks(&mut self, ticks: u32) -> &mut Self {
  117. self.th_ticks = ticks;
  118. self
  119. }
  120. pub fn start<F>(&self, func: F) -> RTResult<Thread>
  121. where
  122. F: FnOnce() -> (),
  123. F: Send + 'static,
  124. {
  125. Thread::spawn(
  126. self.th_name.clone(),
  127. self.th_stack_size,
  128. self.th_priority,
  129. self.th_ticks,
  130. func,
  131. )
  132. }
  133. }