RTE OSAdapter POSIX 0.1.0 build 41b3eb3
POSIX/Linux OAL OSAdapter for Platform_RTE
Loading...
Searching...
No Matches
rte_posix_osadapter_period.h File Reference

Private helper: pacing of a periodic thread by an absolute CLOCK_MONOTONIC deadline (OSA rule R3), and the wake-up of a waiting periodic thread by a stop (OSA rule R2, audit item 7b-1). More...

#include <signal.h>
#include <stdbool.h>
#include <time.h>
#include "rte/utils/status/rte_status.h"
#include "rte/utils/types/rte_types.h"
Include dependency graph for rte_posix_osadapter_period.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

rte_status_t posix_period_init (struct timespec *out_deadline)
 Starts a period: reads CLOCK_MONOTONIC into the deadline.
void posix_period_advance (struct timespec *deadline, rte_duration_ms_t period_ms)
 Moves the deadline one period later, keeping tv_nsec in [0, 1 s).
rte_status_t posix_period_sleep_until (const struct timespec *deadline, const volatile sig_atomic_t *should_stop)
 Waits until the absolute CLOCK_MONOTONIC deadline, or until a stop is requested.
bool posix_period_wake_ready (void)
 Creates the process-wide wake object on the first call; true once it exists.
void posix_period_wake_all (volatile sig_atomic_t *should_stop)
 Requests a stop of a periodic thread and wakes it from its wait.

Detailed Description

Private helper: pacing of a periodic thread by an absolute CLOCK_MONOTONIC deadline (OSA rule R3), and the wake-up of a waiting periodic thread by a stop (OSA rule R2, audit item 7b-1).

One implementation of the period pacing shared by the timer OSAdapter's thread loop and the task OSAdapter's periodic loop (Platform_RTE REQ-OAL-TIMER-014: one monotonic time base). The deadline is a local of the calling thread: posix_period_init() reads the clock once at thread start, posix_period_advance() adds one period per cycle, posix_period_sleep_until() waits until it. The deadline is never re-read from the clock, so the run time of a callback or entry does not shift the next expiry (no drift), and a deadline that has already passed (the callback/entry overran) gives no wait: every expiry is delivered, late, none is skipped. A failed clock read is returned as RTE_STATUS_INTERNAL_ERROR and never used as time 0. macOS CLOCK_MONOTONIC keeps counting while the system sleeps, so after a laptop sleep a periodic thread delivers the expiries it missed back to back (a catch-up burst; harmless for the RBC's tick counters, development host only).

Wake-up (audit item 7b-1): the wait is a timed wait on ONE process-wide wake object, a priority-inheritance mutex and a condition variable, static in rte_posix_osadapter_period.c (a per-timer object would not fit rte_timer_storage_t / rte_task_storage_t, which are fixed by the Platform_RTE ABI). posix_period_wake_ready() creates it once per process; the timer and task OSAdapters call it from create and refuse the create without it. posix_period_wake_all() stores 1 in a thread's stop flag while it holds the wake mutex and broadcasts, so a waiting thread returns at once instead of at its deadline.

Why no wake-up is lost: the waiting thread reads its stop flag while it holds the wake mutex and, if the flag is 0, enters the condition wait, which releases the mutex and starts waiting as one atomic step. posix_period_wake_all() stores the flag and broadcasts while it holds the same mutex. Its critical section therefore lies either wholly before the waiter's check (the waiter sees 1 and does not wait) or wholly after the waiter started waiting (the broadcast wakes it); there is no point in between. Fallback: when the waker cannot take the mutex within RTE_POSIX_PERIOD_WAKE_LOCK_TIMEOUT_MS (default 50 ms) it stores 1 without the mutex and does not broadcast; the waiting thread then sees the flag when its wait ends at the deadline (the behaviour before 7b-1). A stop is never lost; at worst it takes one more period.

A broadcast wakes every waiting periodic thread of the process; a thread whose own flag is still 0 waits again to its same deadline: no expiry added, none lost, no drift.

Known limits: (1) inside pthread_cond_timedwait() the woken thread re-acquires the mutex with no bound of this adapter's (every holder only checks a flag, broadcasts or starts a wait: a handful of instructions). (2) glibc condition variables (since glibc 2.25) are not priority-inheritance aware: the wake-up path itself gives no boost, only the mutex does. (3) Other hosts than Linux take a contended mutex by polling (posix_osa_lock_bounded(): trylock and at most 1 ms sleep), so a contended wake mutex can add up to about 1 ms to a wake-up or an expiry.

Not installed: an internal header of this product, like rte_posix_osadapter_lock.h. A source file including it defines _POSIX_C_SOURCE before its first include (glibc declares clock_gettime() and pthread_condattr_setclock() only under a POSIX feature-test macro).

Definition in file rte_posix_osadapter_period.h.

Function Documentation

◆ posix_period_advance()

void posix_period_advance ( struct timespec * deadline,
rte_duration_ms_t period_ms )

Moves the deadline one period later, keeping tv_nsec in [0, 1 s).

Pure arithmetic on the deadline, no clock read. A NULL deadline is ignored.

Parameters
deadlineDeadline from posix_period_init() (normalised). Updated in place.
period_msPeriod to add, in milliseconds.
Returns
None.

Definition at line 92 of file rte_posix_osadapter_period.c.

◆ posix_period_init()

rte_status_t posix_period_init ( struct timespec * out_deadline)

Starts a period: reads CLOCK_MONOTONIC into the deadline.

Called once by the periodic thread when it starts; the first expiry is one posix_period_advance() later.

Parameters
out_deadlineReceives the current CLOCK_MONOTONIC time. Must not be NULL. Not written when the clock read fails.
Returns
RTE_STATUS_OK with *out_deadline written; RTE_STATUS_INVALID_PARAM for a NULL out_deadline; RTE_STATUS_INTERNAL_ERROR when clock_gettime(CLOCK_MONOTONIC) fails (the caller runs no callback/entry). REQ-OAL-TIMER-014

Global variables declarations Global functions

Definition at line 70 of file rte_posix_osadapter_period.c.

◆ posix_period_sleep_until()

rte_status_t posix_period_sleep_until ( const struct timespec * deadline,
const volatile sig_atomic_t * should_stop )

Waits until the absolute CLOCK_MONOTONIC deadline, or until a stop is requested.

Loop, while *should_stop == 0:

  • reads CLOCK_MONOTONIC; returns when the deadline has passed (no wait);
  • takes the wake mutex, waiting at most the time left to the deadline (posix_osa_lock_bounded(), rounded up to whole milliseconds). A lock timeout is not an error: the clock is read again, so the deadline decides and an expiry is never early;
  • holding the mutex, reads *should_stop; if it is 0, waits on the wake condition variable - non-Apple hosts: pthread_cond_timedwait() to the absolute deadline on a CLOCK_MONOTONIC condition variable; macOS (no condition variable clock attribute): pthread_cond_timedwait_relative_np() of the time left, read again under the mutex;
  • reads *should_stop again and releases the mutex. A wake-up (0) or a timeout (ETIMEDOUT) without a stop goes round the loop: the clock is read again and the wait resumes to the same deadline.

A deadline already passed gives no wait. A stop request returns RTE_STATUS_OK before the deadline; the caller checks should_stop after every return.

Parameters
deadlineAbsolute CLOCK_MONOTONIC deadline (normalised). Must not be NULL.
should_stopThe thread's stop flag, read only. Must not be NULL.
Returns
RTE_STATUS_OK when the deadline is reached or a stop was requested; RTE_STATUS_INVALID_PARAM for a NULL argument; RTE_STATUS_INTERNAL_ERROR when the wake object does not exist, the clock cannot be read, the wake mutex returns an error other than a timeout, the wait returns an error other than ETIMEDOUT or the mutex cannot be released - the caller then stops its loop. REQ-OAL-TIMER-014

Definition at line 109 of file rte_posix_osadapter_period.c.

◆ posix_period_wake_all()

void posix_period_wake_all ( volatile sig_atomic_t * should_stop)

Requests a stop of a periodic thread and wakes it from its wait.

Stores 1 in *should_stop while it holds the wake mutex (bounded by RTE_POSIX_PERIOD_WAKE_LOCK_TIMEOUT_MS) and broadcasts on the wake condition variable, then releases the mutex. When the mutex cannot be taken in time (or the wake object does not exist) it stores 1 without the mutex and does not broadcast: the thread then ends at its next deadline. Not an error either way: there is no return value, and the caller still joins. Callable from any thread, including the periodic thread itself (its callback/entry runs outside the mutex). A NULL should_stop is ignored.

Parameters
should_stopThe thread's stop flag. Written (set to 1).
Returns
None.

Definition at line 139 of file rte_posix_osadapter_period.c.

◆ posix_period_wake_ready()

bool posix_period_wake_ready ( void )

Creates the process-wide wake object on the first call; true once it exists.

pthread_once(): a priority-inheritance mutex (PTHREAD_PRIO_INHERIT requested at run time on every host, as the mutex OSAdapter does) and a condition variable (non-Apple hosts: clock CLOCK_MONOTONIC). A refusal of any of these calls reports DEGRADED / RTE_SAFESTATE_REASON_OSA_RT_ATTRIBUTE once ("period wake object refused - timer/task create failed"), destroys what was created and makes this and every later call return false (not retried, same posture as the timer and task thread-specific-data key). Never deleted: it lives as long as the process.

Returns
true when the wake object exists; false when it was refused or pthread_once() failed.

Definition at line 127 of file rte_posix_osadapter_period.c.