osal-rs 1.0.1

Operating System Abstraction Layer for Rust with support for FreeRTOS and POSIX
/***************************************************************************
 *
 * osal-rs
 * Copyright (C) 2026 Antonio Salsi <passy.linux@zresa.it>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 *
 ***************************************************************************/

//! POSIX type definitions and handle wrappers.
//!
//! This module provides type aliases and handle types that interface with the
//! POSIX threading API (pthreads). Types are generated at build time based on
//! the detected target architecture's native word size.
//!
//! # Generated Types
//!
//! The following types are generated by the build script, based on the host
//! architecture reported by `uname`:
//!
//! - `TickType` - System tick counter type (`u32` on 32-bit, `u64` on 64-bit)
//! - `BaseType` - Basic signed integer type for return values
//! - `UBaseType` - Basic unsigned integer type
//! - `StackType` - Type used for stack allocation
//!
//! # Handle Types
//!
//! POSIX OS objects are referenced through opaque pointers (handles):
//!
//! - `ThreadHandle` - References a pthread
//! - `QueueHandle` - References a message queue
//! - `SemaphoreHandle` - References a semaphore
//! - `MutexHandle` - References a mutex
//! - `EventGroupHandle` - References an event group
//! - `TimerHandle` - References a timer

// Include build-time generated types based on the target architecture.
// This file is generated by the build script and contains:
// - TickType: System tick counter type
// - BaseType: Basic signed integer type
// - UBaseType: Basic unsigned integer type
// - StackType: Stack allocation type
include!(concat!(env!("OUT_DIR"), "/types_generated.rs"));

use core::ffi::{ c_ulong, c_void };
use core::fmt::Debug;

use crate::posix::ffi::{pthread_cond_t, pthread_mutex_t};

/// POSIX opaque handle types for OS primitives.
///
/// These handles are opaque pointers used to reference POSIX/pthread-backed
/// objects. They should not be dereferenced directly; instead, use the safe
/// wrappers provided by this crate (e.g., `Thread`, `Queue`, `Semaphore`, etc.).

/// Backing handle for [`crate::os::Queue`], [`crate::os::Semaphore`] and
/// [`crate::os::EventGroup`]: a `pthread_mutex_t` + `pthread_cond_t` pair.
///
/// These three primitives share the same "wait on a condition, guarded by a
/// mutex" shape, so they all reuse this one handle type (see
/// [`QueueHandle`], [`SemaphoreHandle`], [`EventGroupHandle`]) instead of
/// each defining their own. Not constructible from outside this crate other
/// than via [`Default`]; the safe wrapper types are what application code
/// should use.
///
/// # Examples
///
/// ```
/// use osal_rs::os::types::ClockMonotonicHandle;
///
/// // A never-initialized handle reports as empty.
/// let handle = ClockMonotonicHandle::default();
/// assert!(handle.is_empty());
/// ```
#[derive(Default)]
pub struct ClockMonotonicHandle (
    pub(in crate::posix) pthread_mutex_t,
    pub(in crate::posix) pthread_cond_t,
);

impl Debug for ClockMonotonicHandle {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("ClockMonotonicHandle")
            .field("handle", &(&raw const self).addr())
            .finish()
    }
}

impl ClockMonotonicHandle {
    /// Returns `true` if this handle is still in its never-initialized (or
    /// already-deleted) state, i.e. both the mutex and condition variable
    /// are all-zero.
    ///
    /// # Examples
    ///
    /// ```
    /// use osal_rs::os::types::ClockMonotonicHandle;
    ///
    /// assert!(ClockMonotonicHandle::default().is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.0.is_empty() && self.1.is_empty()
    }
}

/// Opaque POSIX thread identifier (`pthread_t`).
///
/// glibc defines `pthread_t` as `unsigned long int`, so `c_ulong` has the
/// correct size/representation on every target this crate builds for. `0`
/// is used throughout this crate as the "no thread" sentinel (see
/// [`crate::os::ThreadFn::is_null`]).
pub type ThreadHandle = c_ulong;

/// Backing handle for [`crate::os::Queue`]/[`crate::os::QueueStreamed`].
/// See [`ClockMonotonicHandle`] for why this is a mutex/condvar pair rather
/// than a queue-specific type.
pub type QueueHandle = ClockMonotonicHandle;

/// Backing handle for [`crate::os::Semaphore`].
/// See [`ClockMonotonicHandle`] for why this is a mutex/condvar pair rather
/// than a semaphore-specific type (plain POSIX unnamed semaphores can't
/// enforce a maximum count or use priority inheritance).
pub type SemaphoreHandle = ClockMonotonicHandle;

/// Backing handle for [`crate::os::EventGroup`].
/// See [`ClockMonotonicHandle`] for why this is a mutex/condvar pair rather
/// than an event-group-specific type.
pub type EventGroupHandle = ClockMonotonicHandle;

/// Opaque POSIX per-process timer identifier (`timer_t`, `<time.h>`).
///
/// glibc defines `timer_t` as `void *`, so `*mut c_void` has the correct
/// size/representation on every target this crate builds for.
pub type TimerHandle = *mut c_void;

/// Backing handle for [`crate::os::Mutex`]/[`crate::os::RawMutex`]: a bare
/// `pthread_mutex_t`, with no condition variable attached since a mutex has
/// nothing to wait on beyond acquiring the lock itself.
pub type MutexHandle = pthread_mutex_t;

/// Type alias for event group bits.
///
/// Represents a set of event flags where each bit can be set or cleared
/// independently. The underlying type is `TickType`, matching the native
/// word size of the target architecture. The top byte is reserved (see
/// [`crate::os::EventGroup::MAX_MASK`]), so only the lower bits are usable
/// as flags.
///
/// # Examples
///
/// ```
/// use osal_rs::os::types::EventBits;
///
/// const READY: EventBits = 1 << 0;
/// const ERROR: EventBits = 1 << 1;
///
/// let bits: EventBits = READY | ERROR;
/// assert_eq!(bits & READY, READY);
/// ```
pub type EventBits = TickType;