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(¤t);
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}