Skip to main content

osal_rs/traits/
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-related traits and type definitions.
22//!
23//! This module provides the core abstractions for creating and managing RTOS tasks/threads,
24//! including thread lifecycle, notifications, and priority management.
25//!
26//! # Overview
27//!
28//! In RTOS terminology, tasks and threads are often used interchangeably. This module
29//! uses "Thread" for consistency with Rust conventions, but these map directly to
30//! RTOS tasks.
31//!
32//! # Thread Lifecycle
33//!
34//! 1. **Creation**: Use `Thread::new()` with name, stack size, and priority
35//! 2. **Spawning**: Call `spawn()` or `spawn_simple()` with the thread function
36//! 3. **Execution**: Thread runs until function returns or `delete()` is called
37//! 4. **Cleanup**: Call `delete()` to free resources
38//!
39//! # Thread Notifications
40//!
41//! Threads support lightweight task notifications as an alternative to semaphores
42//! and queues for simple signaling. See `ThreadNotification` for available actions.
43//!
44//! # Priority Management
45//!
46//! Higher priority threads preempt lower priority ones. Priority 0 is typically
47//! reserved for the idle task. Use `ToPriority` trait for flexible priority specification.
48
49use core::any::Any;
50use alloc::boxed::Box;
51use alloc::sync::Arc;
52
53use crate::os::types::{BaseType, StackType, ThreadHandle, TickType, UBaseType};
54use crate::utils::{Bytes, DoublePtr, Result};
55
56/// Maximum length (in bytes) of a thread name, shared by all backends.
57pub(crate) const MAX_TASK_NAME_LEN: usize = 16;
58
59/// Type-erased parameter that can be passed to thread callbacks.
60///
61/// Allows passing arbitrary data to thread functions in a thread-safe manner.
62/// The parameter is wrapped in an `Arc` for safe sharing across thread boundaries
63/// and can be downcast to its original type using `downcast_ref()`.
64///
65/// # Thread Safety
66///
67/// The inner type must implement `Any + Send + Sync` to ensure it can be
68/// safely shared between threads.
69///
70/// # Examples
71///
72/// ```
73/// use osal_rs::os::*;
74/// use std::sync::Arc;
75///
76/// // Create a parameter
77/// let param: ThreadParam = Arc::new(42u32);
78///
79/// // In the thread callback, downcast to access it
80/// assert_eq!(param.downcast_ref::<u32>(), Some(&42));
81///
82/// // A downcast to the wrong type simply reports `None`.
83/// assert!(param.downcast_ref::<i8>().is_none());
84/// ```
85pub type ThreadParam = Arc<dyn Any + Send + Sync>;
86
87/// Thread callback function pointer type.
88///
89/// Thread callbacks receive a boxed thread handle and optional parameter,
90/// and can return an updated parameter value.
91///
92/// # Parameters
93///
94/// - `Box<dyn Thread>` - Handle to the thread itself (for self-reference)
95/// - `Option<ThreadParam>` - Optional type-erased parameter passed at spawn time
96///
97/// # Returns
98///
99/// `Result<ThreadParam>` - Updated parameter or error
100///
101/// # Trait Bounds
102///
103/// The function must be `Send + Sync + 'static` to be safely used across
104/// thread boundaries and to live for the duration of the thread.
105///
106/// # Examples
107///
108/// ```
109/// use osal_rs::os::*;
110/// use std::sync::Arc;
111///
112/// let callback: Box<ThreadFnPtr> = Box::new(|_thread, param| {
113///     if let Some(p) = param {
114///         if let Some(count) = p.downcast_ref::<u32>() {
115///             return Ok(Arc::new(*count + 1));
116///         }
117///     }
118///     Ok(Arc::new(0u32))
119/// });
120///
121/// // This is how `spawn` invokes it: with a handle to the thread itself and
122/// // the parameter it was spawned with.
123/// let thread = Thread::new("worker", 1024, 1);
124/// let result = callback(Box::new(thread), Some(Arc::new(41u32))).unwrap();
125///
126/// assert_eq!(result.downcast_ref::<u32>(), Some(&42));
127/// ```
128pub type ThreadFnPtr = dyn Fn(Box<dyn Thread>, Option<ThreadParam>) -> Result<ThreadParam> + Send + Sync + 'static;
129
130/// Simple thread function pointer type without parameters.
131///
132/// Used for basic thread functions that don't need access to the thread handle
133/// or parameters. This is the simplest form of thread callback.
134///
135/// # Trait Bounds
136///
137/// The function must be `Send + Sync + 'static` to be safely used in a
138/// multi-threaded environment.
139///
140/// # Examples
141///
142/// ```
143/// use osal_rs::os::*;
144/// use std::sync::Arc;
145/// use std::sync::atomic::{AtomicU32, Ordering};
146///
147/// static RUNS: AtomicU32 = AtomicU32::new(0);
148///
149/// let mut thread = Thread::new("simple", 1024, 1);
150/// let worker = thread.spawn_simple(|| {
151///     for _ in 0..3 {
152///         RUNS.fetch_add(1, Ordering::SeqCst);
153///         System::delay(5);
154///     }
155///     Ok(Arc::new(()))
156/// }).unwrap();
157///
158/// worker.delete(); // waits for the thread to finish
159/// assert_eq!(RUNS.load(Ordering::SeqCst), 3);
160/// ```
161pub type ThreadSimpleFnPtr = dyn Fn() -> Result<ThreadParam> + Send + Sync + 'static;
162
163/// Thread notification actions.
164///
165/// Defines different ways to notify a thread, using a lightweight task-notification
166/// mechanism modeled on FreeRTOS's (backends without native support, e.g. POSIX,
167/// emulate the same one-slot semantics). Provides a lightweight alternative to
168/// semaphores and queues for simple signaling between threads or from ISRs to threads.
169///
170/// # Performance
171///
172/// Task notifications are faster and use less memory than semaphores or queues,
173/// but each thread has only one notification value (32 bits).
174///
175/// # Common Patterns
176///
177/// - **Event Signaling**: Use `Increment` or `SetBits` to signal events
178/// - **Value Passing**: Use `SetValueWithOverwrite` to pass a value
179/// - **Non-Blocking Updates**: Use `SetValueWithoutOverwrite` to avoid data races
180///
181/// # Examples
182///
183/// ```
184/// use osal_rs::os::*;
185///
186/// let thread = Thread::get_current();
187///
188/// // Increment notification counter
189/// thread.notify(ThreadNotification::Increment).unwrap();
190/// assert_eq!(thread.wait_notification(0, 0xFFFF_FFFF, 10).unwrap(), 1);
191///
192/// // Set specific bits (can combine multiple events)
193/// thread.notify(ThreadNotification::SetBits(0b1010)).unwrap();
194/// assert_eq!(thread.wait_notification(0, 0xFFFF_FFFF, 10).unwrap(), 0b1010);
195///
196/// // Set value, overwriting any existing value
197/// thread.notify(ThreadNotification::SetValueWithOverwrite(42)).unwrap();
198/// assert_eq!(thread.wait_notification(0, 0, 10).unwrap(), 42);
199///
200/// // Set value only if no pending notifications - the previous one was
201/// // consumed by the wait above, so this one goes through.
202/// thread.notify(ThreadNotification::SetValueWithoutOverwrite(100)).unwrap();
203/// assert_eq!(thread.wait_notification(0, 0, 10).unwrap(), 100);
204/// ```
205#[derive(Debug, Copy, Clone)]
206pub enum ThreadNotification {
207    /// Don't update the notification value.
208    ///
209    /// Can be used to just query whether a task has been notified.
210    NoAction,
211    /// Bitwise OR the notification value with the specified bits.
212    ///
213    /// Useful for setting multiple event flags that accumulate.
214    SetBits(u32),
215    /// Increment the notification value by one.
216    ///
217    /// Useful for counting events or implementing a lightweight counting semaphore.
218    Increment,
219    /// Set the notification value, overwriting any existing value.
220    ///
221    /// Use when you want to send a value and don't care if it overwrites
222    /// a previous unread value.
223    SetValueWithOverwrite(u32),
224    /// Set the notification value only if the receiving thread has no pending notifications.
225    ///
226    /// Use when you want to avoid overwriting an unread value. Returns an error
227    /// if a notification is already pending.
228    SetValueWithoutOverwrite(u32),
229}
230
231impl Into<(u32, u32)> for ThreadNotification {
232    fn into(self) -> (u32, u32) {
233        use ThreadNotification::*;
234        match self {
235            NoAction => (0, 0),
236            SetBits(bits) => (1, bits),
237            Increment => (2, 0),
238            SetValueWithOverwrite(value) => (3, value),
239            SetValueWithoutOverwrite(value) => (4, value),
240        }
241    }
242}
243
244/// Represents the possible states of an RTOS task/thread.
245///
246/// # Examples
247///
248/// ```
249/// use osal_rs::os::*;
250///
251/// let thread = Thread::get_current();
252/// let metadata = thread.get_metadata();
253///
254/// match metadata.state {
255///     ThreadState::Running => (),   // currently executing
256///     ThreadState::Ready => (),     // ready to run
257///     ThreadState::Blocked => (),   // waiting for an event
258///     ThreadState::Suspended => (), // explicitly suspended
259///     _ => (),                      // deleted or unknown
260/// }
261///
262/// // The thread asking is, by definition, the one running.
263/// assert_eq!(metadata.state, ThreadState::Running);
264/// ```
265#[derive(Copy, Clone, Debug, PartialEq)]
266#[repr(u8)]
267pub enum ThreadState {
268    /// Thread is currently executing on a CPU
269    Running = 0,
270    /// Thread is ready to run but not currently executing
271    Ready = 1,
272    /// Thread is blocked waiting for an event (e.g., semaphore, queue)
273    Blocked = 2,
274    /// Thread has been explicitly suspended
275    Suspended = 3,
276    /// Thread has been deleted
277    Deleted = 4,
278    /// Invalid or unknown state
279    Invalid,
280}
281
282/// Metadata and runtime information about a thread.
283///
284/// Contains detailed information about a thread's state, priorities, stack usage,
285/// and runtime statistics.
286///
287/// # Examples
288///
289/// ```
290/// use osal_rs::os::*;
291///
292/// let thread = Thread::get_current();
293/// let metadata = thread.get_metadata();
294///
295/// // Name, priority and stack usage are all part of the snapshot.
296/// let _ = (metadata.name.as_str(), metadata.priority, metadata.stack_high_water_mark);
297///
298/// assert_ne!(metadata.state, ThreadState::Invalid);
299/// ```
300#[derive(Clone, Debug)]
301pub struct ThreadMetadata {
302    /// OS-level thread/task handle
303    pub thread: ThreadHandle,
304    /// Thread name
305    pub name: Bytes<MAX_TASK_NAME_LEN>,
306    /// Original stack depth allocated for this thread
307    pub stack_depth: StackType,
308    /// Thread priority
309    pub priority: UBaseType,
310    /// Unique thread number assigned by OS
311    pub thread_number: UBaseType,
312    /// Current execution state
313    pub state: ThreadState,
314    /// Current priority (may differ from base priority due to priority inheritance)
315    pub current_priority: UBaseType,
316    /// Base priority without inheritance
317    pub base_priority: UBaseType,
318    /// Total runtime counter (requires configGENERATE_RUN_TIME_STATS)
319    pub run_time_counter: UBaseType,
320    /// Minimum remaining stack space ever recorded (lower values indicate higher stack usage)
321    pub stack_high_water_mark: StackType,
322}
323
324unsafe impl Send for ThreadMetadata {}
325unsafe impl Sync for ThreadMetadata {}
326
327/// Provides default values for ThreadMetadata.
328///
329/// Creates a metadata instance with null/zero values, representing an
330/// invalid or uninitialized thread.
331impl Default for ThreadMetadata {
332    fn default() -> Self {
333        ThreadMetadata {
334            thread: ThreadHandle::default(),
335            name: Bytes::new(),
336            stack_depth: 0,
337            priority: 0,
338            thread_number: 0,
339            state: ThreadState::Invalid,
340            current_priority: 0,
341            base_priority: 0,
342            run_time_counter: 0,
343            stack_high_water_mark: 0,
344        }
345    }
346}
347
348/// Core thread/task trait.
349///
350/// Provides methods for thread lifecycle management, synchronization,
351/// and communication through task notifications.
352///
353/// # Thread Creation
354///
355/// Threads are typically created with `Thread::new()` specifying name,
356/// stack size, and priority, then started with `spawn()` or `spawn_simple()`.
357///
358/// # Thread Safety
359///
360/// All methods are thread-safe. ISR-specific methods (suffixed with `_from_isr`)
361/// should only be called from interrupt context.
362///
363/// # Resource Management
364///
365/// Threads should be properly deleted with `delete()` when no longer needed
366/// to free stack memory and control structures.
367///
368/// # Examples
369///
370/// ```
371/// use osal_rs::os::*;
372/// use std::sync::Arc;
373/// use std::sync::atomic::{AtomicU32, Ordering};
374///
375/// static WORK: AtomicU32 = AtomicU32::new(0);
376///
377/// // Create and spawn a simple thread
378/// let mut thread = Thread::new("worker", 2048, 5);
379/// let worker = thread.spawn_simple(|| {
380///     for _ in 0..3 {
381///         WORK.fetch_add(1, Ordering::SeqCst);
382///         System::delay(5);
383///     }
384///     Ok(Arc::new(()))
385/// }).unwrap();
386///
387/// // Create thread with parameter
388/// let mut thread2 = Thread::new("counter", 1024, 5);
389/// let counter: ThreadParam = Arc::new(AtomicU32::new(0));
390/// let counting = thread2.spawn(Some(counter.clone()), |_thread, param| {
391///     let param = param.unwrap();
392///     if let Some(count) = param.downcast_ref::<AtomicU32>() {
393///         count.fetch_add(1, Ordering::SeqCst);
394///     }
395///     Ok(param)
396/// }).unwrap();
397///
398/// worker.delete();
399/// counting.delete();
400///
401/// assert_eq!(WORK.load(Ordering::SeqCst), 3);
402/// assert_eq!(counter.downcast_ref::<AtomicU32>().unwrap().load(Ordering::SeqCst), 1);
403/// ```
404pub trait Thread {
405
406    /// Returns `true` if the underlying OS handle is null, i.e. the thread
407    /// has not been spawned yet or has already been deleted.
408    fn is_null(&self) -> bool;
409
410    /// Spawns a thread with a callback function and optional parameter.
411    ///
412    /// Creates and starts a new thread that executes the provided callback function.
413    /// The callback receives a handle to itself and an optional parameter.
414    ///
415    /// # Parameters
416    ///
417    /// * `param` - Optional type-erased parameter passed to the callback
418    /// * `callback` - Function to execute in the thread context
419    ///
420    /// # Returns
421    ///
422    /// * `Ok(Self)` - Thread spawned successfully
423    /// * `Err(Error)` - Failed to create or start thread
424    ///
425    /// # Examples
426    ///
427    /// ```
428    /// use osal_rs::os::*;
429    /// use std::sync::Arc;
430    /// use std::sync::atomic::{AtomicU32, Ordering};
431    ///
432    /// static SEEN: AtomicU32 = AtomicU32::new(0);
433    ///
434    /// let mut thread = Thread::new("worker", 1024, 5);
435    /// let counter: ThreadParam = Arc::new(100u32);
436    ///
437    /// let spawned = thread.spawn(Some(counter.clone()), |_thread, param| {
438    ///     if let Some(p) = param {
439    ///         if let Some(count) = p.downcast_ref::<u32>() {
440    ///             SEEN.store(*count, Ordering::SeqCst);
441    ///         }
442    ///     }
443    ///     Ok(Arc::new(200u32))
444    /// }).unwrap();
445    ///
446    /// spawned.delete(); // waits for the thread to finish
447    /// assert_eq!(SEEN.load(Ordering::SeqCst), 100);
448    /// ```
449    fn spawn<F>(&mut self, param: Option<ThreadParam>, callback: F) -> Result<Self>
450    where 
451        F: Fn(Box<dyn Thread>, Option<ThreadParam>) -> Result<ThreadParam>,
452        F: Send + Sync + 'static,
453        Self: Sized;
454
455    /// Spawns a simple thread with a callback function (no parameters).
456    ///
457    /// Creates and starts a new thread that executes the provided callback.
458    /// This is a simpler version of `spawn()` for threads that don't need
459    /// parameters or self-reference.
460    ///
461    /// # Parameters
462    ///
463    /// * `callback` - Function to execute in the thread context
464    ///
465    /// # Returns
466    ///
467    /// * `Ok(Self)` - Thread spawned successfully
468    /// * `Err(Error)` - Failed to create or start thread
469    ///
470    /// # Examples
471    ///
472    /// ```
473    /// use osal_rs::os::*;
474    /// use std::sync::Arc;
475    /// use std::sync::atomic::{AtomicBool, Ordering};
476    ///
477    /// static LED: AtomicBool = AtomicBool::new(false);
478    ///
479    /// let mut thread = Thread::new("blinker", 512, 3);
480    /// let blinker = thread.spawn_simple(|| {
481    ///     for _ in 0..4 {
482    ///         LED.fetch_xor(true, Ordering::SeqCst); // toggle the LED
483    ///         System::delay(5);
484    ///     }
485    ///     Ok(Arc::new(()))
486    /// }).unwrap();
487    ///
488    /// blinker.delete();
489    /// assert!(!LED.load(Ordering::SeqCst)); // toggled an even number of times
490    /// ```
491    fn spawn_simple<F>(&mut self, callback: F) -> Result<Self>
492    where
493        F: Fn() -> Result<ThreadParam> + Send + Sync + 'static,
494        Self: Sized;
495
496    /// Deletes the thread and frees its resources.
497    ///
498    /// Terminates the thread and releases its stack and control structures.
499    /// After calling this, the thread handle becomes invalid.
500    ///
501    /// # Safety
502    ///
503    /// - The thread should not be holding any resources (mutexes, etc.)
504    /// - Other threads should not be waiting on this thread
505    /// - Cannot delete the currently running thread (use from another thread)
506    ///
507    /// # Examples
508    ///
509    /// ```
510    /// use osal_rs::os::*;
511    /// use std::sync::Arc;
512    ///
513    /// let mut thread = Thread::new("temp", 512, 1);
514    /// let spawned = thread.spawn_simple(|| {
515    ///     // Do some work
516    ///     System::delay(5);
517    ///     Ok(Arc::new(()))
518    /// }).unwrap();
519    ///
520    /// // Later, from another thread
521    /// spawned.delete();
522    /// ```
523    fn delete(&self);
524
525    /// Suspends the thread.
526    ///
527    /// Prevents the thread from executing until `resume()` is called.
528    /// The thread state is preserved and can be resumed later.
529    ///
530    /// # Use Cases
531    ///
532    /// - Temporarily pause a thread
533    /// - Debugging and development
534    /// - Dynamic task management
535    ///
536    /// # Examples
537    ///
538    /// ```
539    /// use osal_rs::os::*;
540    /// use std::sync::Arc;
541    /// use std::sync::atomic::{AtomicU32, Ordering};
542    ///
543    /// static COUNTER: AtomicU32 = AtomicU32::new(0);
544    ///
545    /// let mut thread = Thread::new("counter", 1024, 1);
546    /// let worker = thread.spawn_simple(|| {
547    ///     loop {
548    ///         COUNTER.fetch_add(1, Ordering::SeqCst);
549    ///         System::delay(1);
550    ///     }
551    /// }).unwrap();
552    ///
553    /// System::delay(30);
554    /// worker.suspend();  // Pauses the worker, not the caller
555    ///
556    /// let paused_at = COUNTER.load(Ordering::SeqCst);
557    /// System::delay(50);
558    ///
559    /// // No progress while suspended.
560    /// assert_eq!(COUNTER.load(Ordering::SeqCst), paused_at);
561    ///
562    /// worker.resume();
563    /// ```
564    fn suspend(&self);
565
566    /// Resumes a suspended thread.
567    ///
568    /// Resumes execution of a thread that was previously suspended with `suspend()`.
569    /// If the thread was not suspended, this has no effect.
570    ///
571    /// # Examples
572    ///
573    /// ```
574    /// use osal_rs::os::*;
575    /// use std::sync::Arc;
576    /// use std::sync::atomic::{AtomicU32, Ordering};
577    ///
578    /// static COUNTER: AtomicU32 = AtomicU32::new(0);
579    ///
580    /// let mut thread = Thread::new("counter", 1024, 1);
581    /// let worker_thread = thread.spawn_simple(|| {
582    ///     loop {
583    ///         COUNTER.fetch_add(1, Ordering::SeqCst);
584    ///         System::delay(1);
585    ///     }
586    /// }).unwrap();
587    ///
588    /// System::delay(30);
589    /// worker_thread.suspend();
590    ///
591    /// let paused_at = COUNTER.load(Ordering::SeqCst);
592    /// System::delay(50);
593    ///
594    /// worker_thread.resume();  // Resume the worker
595    /// System::delay(30);
596    ///
597    /// // Progress resumes.
598    /// assert!(COUNTER.load(Ordering::SeqCst) > paused_at);
599    /// ```
600    fn resume(&self);
601
602    /// Waits for the thread to complete and retrieves its return value.
603    ///
604    /// Blocks the calling thread until this thread terminates. The thread's
605    /// return value is stored in the provided pointer.
606    ///
607    /// # Parameters
608    ///
609    /// * `retval` - Pointer to store the thread's return value
610    ///
611    /// # Returns
612    ///
613    /// * `Ok(exit_code)` - Thread completed successfully
614    /// * `Err(Error)` - Join operation failed
615    ///
616    /// # Examples
617    ///
618    /// ```
619    /// use osal_rs::os::*;
620    /// use std::sync::Arc;
621    ///
622    /// let mut thread = Thread::new("worker", 1024, 1);
623    /// let spawned = thread.spawn_simple(|| {
624    ///     // Do work
625    ///     Ok(Arc::new(()))
626    /// }).unwrap();
627    ///
628    /// // Pass a null pointer when the exit value is not needed.
629    /// assert!(spawned.join(core::ptr::null_mut()).is_ok());
630    /// ```
631    fn join(&self, retval: DoublePtr) -> Result<i32>;
632
633    /// Gets metadata about the thread.
634    ///
635    /// Returns information such as thread name, priority, stack usage,
636    /// and current state.
637    ///
638    /// # Returns
639    ///
640    /// `ThreadMetadata` structure containing thread information
641    ///
642    /// # Examples
643    ///
644    /// ```
645    /// use osal_rs::os::*;
646    ///
647    /// let thread = Thread::new("worker", 1024, 3);
648    /// let meta = thread.get_metadata();
649    ///
650    /// assert_eq!(meta.name.as_str(), "worker");
651    /// assert_eq!(meta.priority, 3);
652    /// ```
653    fn get_metadata(&self) -> ThreadMetadata;
654
655    /// Gets a handle to the currently executing thread.
656    ///
657    /// Returns a handle to the thread that is currently running.
658    /// Useful for self-referential operations.
659    ///
660    /// # Returns
661    ///
662    /// Handle to the current thread
663    ///
664    /// # Examples
665    ///
666    /// ```
667    /// use osal_rs::os::*;
668    ///
669    /// let current = Thread::get_current();
670    /// assert!(!current.is_null());
671    ///
672    /// let meta = current.get_metadata();
673    /// assert_eq!(meta.state, ThreadState::Running);
674    /// ```
675    fn get_current() -> Self
676    where 
677        Self: Sized;
678
679    /// Sends a notification to the thread.
680    ///
681    /// Notifies the thread using the specified notification action.
682    /// Task notifications are a lightweight signaling mechanism.
683    ///
684    /// # Parameters
685    ///
686    /// * `notification` - The notification action to perform
687    ///
688    /// # Returns
689    ///
690    /// * `Ok(())` - Notification sent successfully
691    /// * `Err(Error)` - Failed to send notification
692    ///
693    /// # Examples
694    ///
695    /// ```
696    /// use osal_rs::os::*;
697    /// use std::sync::Arc;
698    /// use std::sync::atomic::{AtomicU32, Ordering};
699    ///
700    /// static RECEIVED: AtomicU32 = AtomicU32::new(0);
701    ///
702    /// let mut thread = Thread::new("worker", 1024, 1);
703    /// let worker = thread.spawn_simple(|| {
704    ///     let current = Thread::get_current();
705    ///     // Blocks until the notification below arrives.
706    ///     let value = current.wait_notification(0, 0, 1000).unwrap();
707    ///     RECEIVED.store(value, Ordering::SeqCst);
708    ///     Ok(Arc::new(()))
709    /// }).unwrap();
710    ///
711    /// // Send a value. `ThreadNotification::SetBits` would signal an event
712    /// // instead, without disturbing the bits another event already set.
713    /// worker.notify(ThreadNotification::SetValueWithOverwrite(42)).unwrap();
714    ///
715    /// worker.delete();
716    /// assert_eq!(RECEIVED.load(Ordering::SeqCst), 42);
717    /// ```
718    fn notify(&self, notification: ThreadNotification) -> Result<()>;
719
720    /// Sends a notification to the thread from ISR context.
721    ///
722    /// ISR-safe version of `notify()`. Must only be called from interrupt context.
723    ///
724    /// # Parameters
725    ///
726    /// * `notification` - The notification action to perform
727    /// * `higher_priority_task_woken` - Set to non-zero if a context switch should occur
728    ///
729    /// # Returns
730    ///
731    /// * `Ok(())` - Notification sent successfully
732    /// * `Err(Error)` - Failed to send notification
733    ///
734    /// # Examples
735    ///
736    /// ```
737    /// use osal_rs::os::*;
738    ///
739    /// // In interrupt handler
740    /// fn isr_handler(worker: &Thread) {
741    ///     let mut task_woken = 0;
742    ///
743    ///     worker.notify_from_isr(
744    ///         ThreadNotification::Increment,
745    ///         &mut task_woken
746    ///     ).ok();
747    ///
748    ///     System::yield_from_isr(task_woken);
749    /// }
750    ///
751    /// let current = Thread::get_current();
752    /// isr_handler(&current);
753    ///
754    /// // The notification is now pending on the notified thread.
755    /// assert_eq!(current.wait_notification(0, 0xFFFF_FFFF, 10).unwrap(), 1);
756    /// ```
757    fn notify_from_isr(&self, notification: ThreadNotification, higher_priority_task_woken: &mut BaseType) -> Result<()>;
758
759    /// Waits for a notification.
760    ///
761    /// Blocks the calling thread until a notification is received or timeout occurs.
762    /// Allows clearing specific bits on entry and/or exit.
763    ///
764    /// # Parameters
765    ///
766    /// * `bits_to_clear_on_entry` - Bits to clear before waiting
767    /// * `bits_to_clear_on_exit` - Bits to clear after receiving notification
768    /// * `timeout_ticks` - Maximum ticks to wait (0 = no wait, MAX = wait forever)
769    ///
770    /// # Returns
771    ///
772    /// * `Ok(notification_value)` - Notification received, returns the notification value
773    /// * `Err(Error::Timeout)` - No notification received within timeout
774    /// * `Err(Error)` - Other error occurred
775    ///
776    /// # Note
777    ///
778    /// This method does not use `ToTick` trait to maintain dynamic dispatch compatibility.
779    ///
780    /// # Examples
781    ///
782    /// ```
783    /// use osal_rs::os::*;
784    ///
785    /// let current = Thread::get_current();
786    ///
787    /// // Nothing pending yet: this gives up once the timeout expires rather
788    /// // than blocking forever.
789    /// assert!(current.wait_notification(0, 0, 10).is_err());
790    ///
791    /// // Wait for notification, clear all bits on exit
792    /// current.notify(ThreadNotification::SetValueWithOverwrite(7)).unwrap();
793    /// match current.wait_notification(0, 0xFFFFFFFF, 1000) {
794    ///     Ok(value) => assert_eq!(value, 7),
795    ///     Err(_) => panic!("timeout waiting for notification"),
796    /// }
797    ///
798    /// // Wait for specific bits
799    /// let bits_of_interest = 0b0011;
800    /// current.notify(ThreadNotification::SetBits(bits_of_interest)).unwrap();
801    /// match current.wait_notification(0, bits_of_interest, 5000) {
802    ///     Ok(value) => assert_ne!(value & bits_of_interest, 0),
803    ///     Err(_) => panic!("timeout"),
804    /// }
805    /// ```
806    fn wait_notification(&self, bits_to_clear_on_entry: u32, bits_to_clear_on_exit: u32 , timeout_ticks: TickType) -> Result<u32>;
807
808
809}
810
811/// Trait for converting types to thread priority values.
812///
813/// Allows flexible specification of thread priorities using different types
814/// (e.g., integers, enums) that can be converted to the underlying RTOS
815/// priority representation.
816///
817/// # Priority Ranges
818///
819/// Priority 0 is typically reserved for the idle task. Higher numbers
820/// indicate higher priority (preemptive scheduling).
821///
822/// # Examples
823///
824/// ```
825/// use osal_rs::os::*;
826/// use osal_rs::os::types::UBaseType;
827///
828/// // Implement for a custom priority enum
829/// enum TaskPriority {
830///     Low,
831///     Medium,
832///     High,
833/// }
834///
835/// impl ToPriority for TaskPriority {
836///     fn to_priority(&self) -> UBaseType {
837///         match self {
838///             TaskPriority::Low => 1,
839///             TaskPriority::Medium => 5,
840///             TaskPriority::High => 10,
841///         }
842///     }
843/// }
844///
845/// let thread = Thread::new_with_to_priority("worker", 1024, TaskPriority::High);
846/// assert_eq!(thread.get_metadata().priority, 10);
847/// ```
848pub trait ToPriority {
849    /// Converts this value to a priority.
850    ///
851    /// # Returns
852    ///
853    /// The priority value as `UBaseType`
854    fn to_priority(&self) -> UBaseType;
855}