Skip to main content

osal_rs/freertos/
thread.rs

1/***************************************************************************
2 *
3 * osal-rs
4 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
18 *
19 ***************************************************************************/
20
21//! Thread management and synchronization for FreeRTOS.
22//!
23//! This module provides a safe Rust interface for creating and managing FreeRTOS tasks.
24//! It supports thread creation with callbacks, priority management, and thread notifications.
25
26use core::ffi::c_void;
27use core::fmt::{Debug, Display, Formatter};
28use core::ops::Deref;
29use core::ptr::null_mut;
30
31use alloc::boxed::Box;
32use alloc::sync::Arc;
33
34use super::ffi::task::INVALID;
35use super::ffi::{ TaskStatus, ThreadHandle, pdPASS, pdTRUE, vTaskDelete, vTaskGetInfo, vTaskResume, vTaskSuspend, xTaskCreate, xTaskGetCurrentTaskHandle};
36use super::types::{StackType, UBaseType, BaseType, TickType};
37use super::thread::ThreadState::*;
38use crate::os::ThreadSimpleFnPtr;
39use crate::traits::{ThreadFn, ThreadParam, ThreadFnPtr, ThreadNotification, ToTick, ToPriority};
40use crate::utils::{Bytes, DoublePtr, Error, Result};
41
42const MAX_TASK_NAME_LEN: usize = 16;
43
44/// Represents the possible states of a FreeRTOS task/thread.
45///
46/// # Examples
47///
48/// ```ignore
49/// use osal_rs::os::{Thread, ThreadState};
50/// 
51/// let thread = Thread::current();
52/// let metadata = thread.metadata().unwrap();
53/// 
54/// match metadata.state {
55///     ThreadState::Running => println!("Thread is currently executing"),
56///     ThreadState::Ready => println!("Thread is ready to run"),
57///     ThreadState::Blocked => println!("Thread is waiting for an event"),
58///     ThreadState::Suspended => println!("Thread is suspended"),
59///     _ => println!("Unknown state"),
60/// }
61/// ```
62#[derive(Copy, Clone, Debug, PartialEq)]
63#[repr(u8)]
64pub enum ThreadState {
65    /// Thread is currently executing on a CPU
66    Running = 0,
67    /// Thread is ready to run but not currently executing
68    Ready = 1,
69    /// Thread is blocked waiting for an event (e.g., semaphore, queue)
70    Blocked = 2,
71    /// Thread has been explicitly suspended
72    Suspended = 3,
73    /// Thread has been deleted
74    Deleted = 4,
75    /// Invalid or unknown state
76    Invalid,
77}
78
79/// Metadata and runtime information about a thread.
80///
81/// Contains detailed information about a thread's state, priorities, stack usage,
82/// and runtime statistics.
83///
84/// # Examples
85///
86/// ```ignore
87/// use osal_rs::os::Thread;
88/// 
89/// let thread = Thread::current();
90/// let metadata = thread.metadata().unwrap();
91/// 
92/// println!("Thread: {}", metadata.name);
93/// println!("Priority: {}", metadata.priority);
94/// println!("Stack high water mark: {}", metadata.stack_high_water_mark);
95/// ```
96#[derive(Clone, Debug)]
97pub struct ThreadMetadata {
98    /// FreeRTOS task handle
99    pub thread: ThreadHandle,
100    /// Thread name
101    pub name: Bytes<MAX_TASK_NAME_LEN>,
102    /// Original stack depth allocated for this thread
103    pub stack_depth: StackType,
104    /// Thread priority
105    pub priority: UBaseType,
106    /// Unique thread number assigned by FreeRTOS
107    pub thread_number: UBaseType,
108    /// Current execution state
109    pub state: ThreadState,
110    /// Current priority (may differ from base priority due to priority inheritance)
111    pub current_priority: UBaseType,
112    /// Base priority without inheritance
113    pub base_priority: UBaseType,
114    /// Total runtime counter (requires configGENERATE_RUN_TIME_STATS)
115    pub run_time_counter: UBaseType,
116    /// Minimum remaining stack space ever recorded (lower values indicate higher stack usage)
117    pub stack_high_water_mark: StackType,
118}
119
120unsafe impl Send for ThreadMetadata {}
121unsafe impl Sync for ThreadMetadata {}
122
123/// Converts a FreeRTOS TaskStatus into ThreadMetadata.
124///
125/// This conversion extracts all relevant task information from the FreeRTOS
126/// TaskStatus structure and creates a safe Rust representation.
127impl From<(ThreadHandle,TaskStatus)> for ThreadMetadata {
128    fn from(status: (ThreadHandle, TaskStatus)) -> Self {
129        let state = match status.1.eCurrentState {
130            0 => Running,
131            1 => Ready,
132            2 => Blocked,
133            3 => Suspended,
134            4 => Deleted,
135            _ => Invalid,
136        };
137
138        ThreadMetadata {
139            thread: status.0,
140            name: Bytes::from_char_ptr(status.1.pcTaskName),
141            // Avoid dereferencing pxStackBase, which may be null or otherwise invalid.
142            // Use 0 as a safe default for unknown stack depth.
143            stack_depth: 0,
144            priority: status.1.uxBasePriority,
145            thread_number: status.1.xTaskNumber,
146            state,
147            current_priority: status.1.uxCurrentPriority,
148            base_priority: status.1.uxBasePriority,
149            run_time_counter: status.1.ulRunTimeCounter,
150            stack_high_water_mark: status.1.usStackHighWaterMark,
151        }
152    }
153}
154
155/// Provides default values for ThreadMetadata.
156///
157/// Creates a metadata instance with null/zero values, representing an
158/// invalid or uninitialized thread.
159impl Default for ThreadMetadata {
160    fn default() -> Self {
161        ThreadMetadata {
162            thread: null_mut(),
163            name: Bytes::new(),
164            stack_depth: 0,
165            priority: 0,
166            thread_number: 0,
167            state: Invalid,
168            current_priority: 0,
169            base_priority: 0,
170            run_time_counter: 0,
171            stack_high_water_mark: 0,
172        }
173    }
174}
175
176/// A FreeRTOS task/thread wrapper.
177///
178/// Provides a safe Rust interface for creating and managing FreeRTOS tasks.
179/// Threads can be created with closures or function pointers and support
180/// various synchronization primitives.
181///
182/// # Examples
183///
184/// ## Creating a simple thread
185///
186/// ```ignore
187/// use osal_rs::os::{Thread, ThreadPriority};
188/// use core::time::Duration;
189/// 
190/// let thread = Thread::new(
191///     "worker",
192///     2048,  // stack size in words
193///     ThreadPriority::Normal,
194///     || {
195///         loop {
196///             println!("Working...");
197///             Duration::from_secs(1).sleep();
198///         }
199///     }
200/// ).unwrap();
201/// 
202/// thread.start().unwrap();
203/// ```
204///
205/// ## Using thread notifications
206///
207/// ```ignore
208/// use osal_rs::os::{Thread, ThreadNotification};
209/// use core::time::Duration;
210/// 
211/// let thread = Thread::new("notified", 2048, 5, || {
212///     loop {
213///         if let Some(value) = Thread::current().wait_notification(Duration::from_secs(1)) {
214///             println!("Received notification: {}", value);
215///         }
216///     }
217/// }).unwrap();
218/// 
219/// thread.start().unwrap();
220/// thread.notify(42).unwrap();  // Send notification
221/// ```
222#[derive(Clone)]
223pub struct Thread {
224    handle: ThreadHandle,
225    name: Bytes<MAX_TASK_NAME_LEN>,
226    stack_depth: StackType,
227    priority: UBaseType,
228    callback: Option<Arc<ThreadFnPtr>>,
229    param: Option<ThreadParam>
230}
231
232unsafe impl Send for Thread {}
233unsafe impl Sync for Thread {}
234
235impl Thread {
236
237    /// Creates a new uninitialized thread.
238    ///
239    /// The thread must be started with `spawn()` or `spawn_simple()`.
240    ///
241    /// # Examples
242    ///
243    /// ```ignore
244    /// use osal_rs::os::{Thread, ThreadFn};
245    /// 
246    /// let thread = Thread::new("worker", 4096, 5);
247    /// ```
248    pub fn new(name: &str, stack_depth: StackType, priority: UBaseType) -> Self 
249    {
250        Self { 
251            handle: null_mut(), 
252            name: Bytes::from_str(name),
253            stack_depth, 
254            priority, 
255            callback: None,
256            param: None 
257        }
258    }
259
260    /// Creates a thread from an existing task handle.
261    ///
262    /// # Returns
263    ///
264    /// * `Err(Error::NullPtr)` if handle is null
265    pub fn new_with_handle(handle: ThreadHandle, name: &str, stack_depth: StackType, priority: UBaseType) -> Result<Self> {
266        if handle.is_null() {
267            return Err(Error::NullPtr);
268        }
269        Ok(Self { 
270            handle, 
271            name: Bytes::from_str(name), 
272            stack_depth, 
273            priority, 
274            callback: None,
275            param: None 
276        })
277    }
278
279    /// Creates a new thread with a priority that implements `ToPriority`.
280    ///
281    /// This is a convenience constructor that allows using various priority types.
282    ///
283    /// # Parameters
284    ///
285    /// * `name` - Thread name for debugging
286    /// * `stack_depth` - Stack size in words (not bytes)
287    /// * `priority` - Thread priority (any type implementing `ToPriority`)
288    ///
289    /// # Examples
290    ///
291    /// ```ignore
292    /// use osal_rs::os::Thread;
293    /// 
294    /// let thread = Thread::new_with_to_priority("worker", 2048, 5);
295    /// ```
296    pub fn new_with_to_priority(name: &str, stack_depth: StackType, priority: impl ToPriority) -> Self 
297    {
298        Self { 
299            handle: null_mut(), 
300            name: Bytes::from_str(name), 
301            stack_depth, 
302            priority: priority.to_priority(), 
303            callback: None,
304            param: None 
305        }
306    }
307
308    /// Creates a thread from an existing FreeRTOS task handle.
309    ///
310    /// # Parameters
311    ///
312    /// * `handle` - Valid FreeRTOS task handle
313    /// * `name` - Thread name
314    /// * `stack_depth` - Stack size
315    /// * `priority` - Thread priority
316    ///
317    /// # Returns
318    ///
319    /// * `Err(Error::NullPtr)` if handle is null
320    ///
321    /// # Examples
322    ///
323    /// ```ignore
324    /// use osal_rs::os::Thread;
325    /// 
326    /// // Get current task handle from FreeRTOS
327    /// let handle = get_task_handle();
328    /// let thread = Thread::new_with_handle_and_to_priority(handle, "existing", 2048, 5).unwrap();
329    /// ```
330    pub fn new_with_handle_and_to_priority(handle: ThreadHandle, name: &str, stack_depth: StackType, priority: impl ToPriority) -> Result<Self> {
331        if handle.is_null() {
332            return Err(Error::NullPtr);
333        }
334        Ok(Self { 
335            handle, 
336            name: Bytes::from_str(name),
337            stack_depth, 
338            priority: priority.to_priority(), 
339            callback: None,
340            param: None 
341        })
342    }
343
344    /// Retrieves metadata for a thread from its handle.
345    ///
346    /// # Parameters
347    ///
348    /// * `handle` - FreeRTOS task handle
349    ///
350    /// # Returns
351    ///
352    /// Thread metadata including state, priority, stack usage, etc.
353    ///
354    /// # Examples
355    ///
356    /// ```ignore
357    /// use osal_rs::os::Thread;
358    /// 
359    /// let handle = get_some_task_handle();
360    /// let metadata = Thread::get_metadata_from_handle(handle);
361    /// println!("Thread '{}' state: {:?}", metadata.name, metadata.state);
362    /// ```
363    pub fn get_metadata_from_handle(handle: ThreadHandle) -> ThreadMetadata {
364        let mut status = TaskStatus::default();
365        unsafe {
366            vTaskGetInfo(handle, &mut status, pdTRUE, INVALID);
367        }
368        ThreadMetadata::from((handle, status))
369    }
370
371    /// Retrieves metadata for a thread object.
372    ///
373    /// # Parameters
374    ///
375    /// * `thread` - Thread reference
376    ///
377    /// # Returns
378    ///
379    /// Thread metadata or default if handle is null
380    ///
381    /// # Examples
382    ///
383    /// ```ignore
384    /// use osal_rs::os::Thread;
385    /// 
386    /// let thread = Thread::new("worker", 2048, 5);
387    /// let metadata = Thread::get_metadata(&thread);
388    /// println!("Stack high water mark: {}", metadata.stack_high_water_mark);
389    /// ```
390    pub fn get_metadata(thread: &Thread) -> ThreadMetadata {
391        if thread.handle.is_null() {
392            return ThreadMetadata::default();
393        }
394        Self::get_metadata_from_handle(thread.handle)
395    }
396
397    /// Waits for a thread notification with a timeout that implements `ToTick`.
398    ///
399    /// Convenience method that accepts `Duration` or other tick-convertible types.
400    ///
401    /// # Parameters
402    ///
403    /// * `bits_to_clear_on_entry` - Bits to clear before waiting
404    /// * `bits_to_clear_on_exit` - Bits to clear after receiving notification
405    /// * `timeout_ticks` - Maximum time to wait (convertible to ticks)
406    ///
407    /// # Returns
408    ///
409    /// * `Ok(u32)` - Notification value received
410    /// * `Err(Error::NullPtr)` - Thread handle is null
411    /// * `Err(Error::Timeout)` - No notification received within timeout
412    ///
413    /// # Examples
414    ///
415    /// ```ignore
416    /// use osal_rs::os::{Thread, ThreadFn};
417    /// use core::time::Duration;
418    /// 
419    /// let thread = Thread::current();
420    /// match thread.wait_notification_with_to_tick(0, 0xFF, Duration::from_secs(1)) {
421    ///     Ok(value) => println!("Received: {}", value),
422    ///     Err(_) => println!("Timeout"),
423    /// }
424    /// ```
425    #[inline]
426    pub fn wait_notification_with_to_tick(&self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32 , timeout_ticks: impl ToTick) -> Result<u32> {
427        if self.handle.is_null() {
428            return Err(Error::NullPtr);
429        }
430        self.wait_notification(bits_to_clear_on_entry, bits_to_clear_on_exit, timeout_ticks.to_ticks())
431    }
432
433}
434
435/// Internal C-compatible wrapper for thread callbacks.
436///
437/// This function bridges between FreeRTOS C API and Rust closures.
438/// It unpacks the boxed thread instance, initializes the handle,
439/// and calls the user-provided callback.
440///
441/// # Safety
442///
443/// This function is marked unsafe because it:
444/// - Expects a valid pointer to a boxed Thread instance
445/// - Performs raw pointer conversions
446/// - Is called from C code (FreeRTOS)
447unsafe extern "C" fn callback_c_wrapper(param_ptr: *mut c_void) {
448    if param_ptr.is_null() {
449        return;
450    }
451
452    let mut thread_instance: Box<Thread> = unsafe { Box::from_raw(param_ptr as *mut _) };
453
454    thread_instance.as_mut().handle = unsafe { xTaskGetCurrentTaskHandle() };
455
456    let thread = *thread_instance.clone();
457
458    let param_arc: Option<ThreadParam> = thread_instance
459        .param
460        .clone();
461
462    if let Some(callback) = &thread_instance.callback.clone() {
463        let _ = callback(thread_instance, param_arc);
464    }
465
466    thread.delete();
467}
468
469/// Internal C-compatible wrapper for simple thread callbacks.
470///
471/// This function bridges between FreeRTOS C API and simple Rust closures
472/// (without parameters). It unpacks the boxed function pointer and executes it.
473///
474/// # Safety
475///
476/// This function is marked unsafe because it:
477/// - Expects a valid pointer to a boxed function pointer
478/// - Performs raw pointer conversions
479/// - Is called from C code (FreeRTOS)
480/// - Directly calls vTaskDelete after execution
481unsafe extern "C" fn simple_callback_wrapper(param_ptr: *mut c_void) {
482    if param_ptr.is_null() {
483        return;
484    }
485
486    let func: Box<Arc<ThreadSimpleFnPtr>> = unsafe { Box::from_raw(param_ptr as *mut _) };
487    func();
488
489    unsafe { vTaskDelete( xTaskGetCurrentTaskHandle()); } 
490}
491
492
493
494impl ThreadFn for Thread {
495
496    /// Spawns a new thread with a callback.
497    /// 
498    /// # Important
499    /// The callback must be `'static`, which means it cannot borrow local variables.
500    /// Use `move` in the closure to transfer ownership of any captured values:
501    /// 
502    /// ```ignore
503    /// let data = Arc::new(Mutex::new(0));
504    /// let thread = Thread::new("my_thread", 4096, 3, move |_thread, _param| {
505    ///     // Use 'move' to capture 'data' by value
506    ///     let mut guard = data.lock().unwrap();
507    ///     *guard += 1;
508    ///     Ok(Arc::new(()))
509    /// });
510    /// ``
511    fn spawn<F>(&mut self, param: Option<ThreadParam>, callback: F) -> Result<Self> 
512        where 
513        F: Fn(Box<dyn ThreadFn>, Option<ThreadParam>) -> Result<ThreadParam>,
514        F: Send + Sync + 'static {
515
516        let mut handle: ThreadHandle =  null_mut();
517
518        let func: Arc<ThreadFnPtr> = Arc::new(callback);
519        
520        self.callback = Some(func);
521        self.param = param.clone();
522
523        let boxed_thread = Box::new(self.clone());
524
525        let ret = unsafe {
526            xTaskCreate(
527                Some(super::thread::callback_c_wrapper),
528                self.name.as_cstr().as_ptr(),
529                self.stack_depth,
530                Box::into_raw(boxed_thread) as *mut _,
531                self.priority,
532                &mut handle,
533            )
534        };
535
536        if ret != pdPASS {
537            return Err(Error::OutOfMemory)
538        }
539
540        Ok(Self { 
541            handle,
542            callback: self.callback.clone(),
543            param,
544            ..self.clone()
545        })
546    }
547
548    /// Spawns a new thread with a simple closure, similar to `std::thread::spawn`.
549    /// This is the recommended way to create threads for most use cases.
550    /// 
551    /// # Example
552    /// ```ignore
553    /// let counter = Arc::new(Mutex::new(0));
554    /// let counter_clone = Arc::clone(&counter);
555    /// 
556    /// let handle = Thread::spawn_simple("worker", 4096, 3, move || {
557    ///     let mut num = counter_clone.lock().unwrap();
558    ///     *num += 1;
559    /// }).unwrap();
560    /// 
561    /// handle.join(core::ptr::null_mut());
562    /// ```
563    fn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
564    where
565        F: Fn() + Send + Sync + 'static,
566    {
567        let func: Arc<ThreadSimpleFnPtr> = Arc::new(callback);
568        let boxed_func = Box::new(func);
569        
570        let mut handle: ThreadHandle = null_mut();
571
572        let ret = unsafe {
573            xTaskCreate(
574                Some(simple_callback_wrapper),
575                self.name.as_cstr().as_ptr(),
576                self.stack_depth,
577                Box::into_raw(boxed_func) as *mut _,
578                self.priority,
579                &mut handle,
580            )
581        };
582
583        if ret != pdPASS {
584            return Err(Error::OutOfMemory);
585        }
586
587        Ok(Self {
588            handle,
589            ..self.clone()
590        })
591    }
592
593    /// Deletes the thread and frees its resources.
594    ///
595    /// # Safety
596    ///
597    /// After calling this, the thread handle becomes invalid.
598    ///
599    /// # Examples
600    ///
601    /// ```ignore
602    /// use osal_rs::os::{Thread, ThreadFn};
603    /// 
604    /// let thread = Thread::new("temp", 2048, 5);
605    /// thread.delete();
606    /// ```
607    fn delete(&self) {
608        if !self.handle.is_null() {
609            unsafe { vTaskDelete( self.handle ); } 
610        }
611    }
612
613    /// Suspends the thread execution.
614    ///
615    /// The thread remains suspended until `resume()` is called.
616    ///
617    /// # Examples
618    ///
619    /// ```ignore
620    /// use osal_rs::os::{Thread, ThreadFn};
621    /// use core::time::Duration;
622    /// 
623    /// let thread = get_some_thread();
624    /// thread.suspend();
625    /// Duration::from_secs(1).sleep();
626    /// thread.resume();
627    /// ```
628    fn suspend(&self) {
629        if !self.handle.is_null() {
630            unsafe { vTaskSuspend( self.handle ); } 
631        }
632    }
633
634    /// Resumes a previously suspended thread.
635    ///
636    /// # Examples
637    ///
638    /// ```ignore
639    /// thread.resume();
640    /// ```
641    fn resume(&self) {
642        if !self.handle.is_null() {
643            unsafe { vTaskResume( self.handle ); } 
644        }
645    }
646
647    /// Waits for the thread to complete (currently deletes the thread).
648    ///
649    /// # Returns
650    ///
651    /// Always returns `Ok(0)`
652    fn join(&self, _retval: DoublePtr) -> Result<i32> {
653        if !self.handle.is_null() {
654            unsafe { vTaskDelete( self.handle ); } 
655        }
656        Ok(0)
657    }
658
659    /// Retrieves this thread's metadata.
660    ///
661    /// # Examples
662    ///
663    /// ```ignore
664    /// use osal_rs::os::{Thread, ThreadFn};
665    /// 
666    /// let thread = Thread::current();
667    /// let meta = thread.get_metadata();
668    /// println!("Running thread: {}", meta.name);
669    /// ```
670    fn get_metadata(&self) -> ThreadMetadata {
671        let mut status = TaskStatus::default();
672        unsafe {
673            vTaskGetInfo(self.handle, &mut status, pdTRUE, INVALID);
674        }
675        ThreadMetadata::from((self.handle, status))
676    }
677
678    /// Returns a Thread object representing the currently executing thread.
679    ///
680    /// # Examples
681    ///
682    /// ```ignore
683    /// use osal_rs::os::{Thread, ThreadFn};
684    /// 
685    /// let current = Thread::get_current();
686    /// println!("Current thread: {}", current.get_metadata().name);
687    /// ```
688    fn get_current() -> Self {
689        let handle = unsafe { xTaskGetCurrentTaskHandle() };
690        let metadata = Self::get_metadata_from_handle(handle);
691        Self {
692            handle,
693            name: metadata.name.clone(),
694            stack_depth: metadata.stack_depth,
695            priority: metadata.priority,
696            callback: None,
697            param: None,
698        }
699    }
700
701    /// Sends a notification to this thread.
702    ///
703    /// # Parameters
704    ///
705    /// * `notification` - Type of notification action to perform
706    ///
707    /// # Returns
708    ///
709    /// * `Ok(())` - Notification sent successfully
710    /// * `Err(Error::NullPtr)` - Thread handle is null
711    /// * `Err(Error::QueueFull)` - Notification failed
712    ///
713    /// # Examples
714    ///
715    /// ```ignore
716    /// use osal_rs::os::{Thread, ThreadFn, ThreadNotification};
717    /// 
718    /// let thread = get_worker_thread();
719    /// thread.notify(ThreadNotification::SetValueWithOverwrite(42)).unwrap();
720    /// ```
721    fn notify(&self, notification: ThreadNotification) -> Result<()> {
722        if self.handle.is_null() {
723            return Err(Error::NullPtr);
724        }
725
726        let (action, value) = notification.into();
727
728        let ret = xTaskNotify!(
729            self.handle,
730            value,
731            action
732        );
733        
734        if ret != pdPASS {
735            Err(Error::QueueFull)
736        } else {
737            Ok(())
738        }
739
740    }
741
742    /// Sends a notification to this thread from an ISR.
743    ///
744    /// # Parameters
745    ///
746    /// * `notification` - Type of notification action
747    /// * `higher_priority_task_woken` - Set to pdTRUE if a higher priority task was woken
748    ///
749    /// # Returns
750    ///
751    /// * `Ok(())` - Notification sent successfully
752    /// * `Err(Error::NullPtr)` - Thread handle is null
753    /// * `Err(Error::QueueFull)` - Notification failed
754    ///
755    /// # Examples
756    ///
757    /// ```ignore
758    /// // In ISR context:
759    /// let mut woken = pdFALSE;
760    /// thread.notify_from_isr(ThreadNotification::Increment, &mut woken).ok();
761    /// ```
762    fn notify_from_isr(&self, notification: ThreadNotification, higher_priority_task_woken: &mut BaseType) -> Result<()> {
763        if self.handle.is_null() {
764            return Err(Error::NullPtr);
765        }
766
767        let (action, value) = notification.into();
768
769        let ret = xTaskNotifyFromISR!(
770            self.handle,
771            value,
772            action,
773            higher_priority_task_woken
774        );
775
776        if ret != pdPASS {
777            Err(Error::QueueFull)
778        } else {
779            Ok(())
780        }
781    }
782
783    /// Waits for a thread notification.
784    ///
785    /// # Parameters
786    ///
787    /// * `bits_to_clear_on_entry` - Bits to clear in notification value before waiting
788    /// * `bits_to_clear_on_exit` - Bits to clear after receiving notification
789    /// * `timeout_ticks` - Maximum ticks to wait
790    ///
791    /// # Returns
792    ///
793    /// * `Ok(u32)` - Notification value received
794    /// * `Err(Error::NullPtr)` - Thread handle is null
795    /// * `Err(Error::Timeout)` - No notification within timeout
796    ///
797    /// # Examples
798    ///
799    /// ```ignore
800    /// use osal_rs::os::{Thread, ThreadFn};
801    /// 
802    /// let thread = Thread::current();
803    /// match thread.wait_notification(0, 0xFFFFFFFF, 1000) {
804    ///     Ok(value) => println!("Received notification: {}", value),
805    ///     Err(_) => println!("Timeout waiting for notification"),
806    /// }
807    /// ```
808    fn wait_notification(&self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32 , timeout_ticks: TickType) -> Result<u32> {
809        if self.handle.is_null() {
810            return Err(Error::NullPtr);
811        }
812
813        let mut notification_value: u32 = 0;
814
815        let ret = xTaskNotifyWait!(
816            bits_to_clear_on_entry,
817            bits_to_clear_on_exit,
818            &mut notification_value,
819            timeout_ticks
820        );
821        
822
823        if ret == pdTRUE {
824            Ok(notification_value)
825        } else {
826            Err(Error::Timeout)
827        }
828    }
829
830}
831
832
833// impl Drop for Thread {
834//     fn drop(&mut self) {
835//         if !self.handle.is_null() {
836//             unsafe { vTaskDelete( self.handle ); } 
837//         }
838//     }
839// }
840
841/// Allows dereferencing to the underlying FreeRTOS thread handle.
842///
843/// This enables direct access to the handle when needed for low-level operations.
844impl Deref for Thread {
845    type Target = ThreadHandle;
846
847    fn deref(&self) -> &Self::Target {
848        &self.handle
849    }
850}
851
852/// Formats the thread for debugging purposes.
853///
854/// Includes handle, name, stack depth, priority, and callback status.
855impl Debug for Thread {
856    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
857        f.debug_struct("Thread")
858            .field("handle", &self.handle)
859            .field("name", &self.name)
860            .field("stack_depth", &self.stack_depth)
861            .field("priority", &self.priority)
862            .field("callback", &self.callback.as_ref().map(|_| "Some(...)"))
863            .field("param", &self.param)
864            .finish()
865    }
866}
867
868/// Formats the thread for display purposes.
869///
870/// Shows a concise representation with handle, name, priority, and stack depth.
871impl Display for Thread {
872    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
873        write!(f, "Thread {{ handle: {:?}, name: {}, priority: {}, stack_depth: {} }}", self.handle, self.name, self.priority, self.stack_depth)
874    }
875}
876
877