Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
rte_lifecycle.h File Reference

Process-wide application setup-phase lock (ADR-026). More...

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

Go to the source code of this file.

Functions

void rte_lifecycle_lock (void)
 Locks the application's setup phase.
void rte_lifecycle_unlock (void)
 Unlocks the application's setup phase (setup is allowed again).
bool rte_lifecycle_is_locked (void)
rte_status_t rte_lifecycle_check_setup_allowed (void)
 Convenience check for a setup-only constructor: call this as one of the first checks in any function that creates/registers a new long-lived resource (a timer, channel, voter, cross-comparator, or watchdog - see this file's own header for the excluded netlink/dual exceptions).

Detailed Description

Process-wide application setup-phase lock (ADR-026).

A safety-critical application shall have a well-defined INIT phase (create timers, channels, voters, cross-comparators, watchdogs) that completes before its RUN phase begins - and once RUN has begun, no further such construction is legitimate: an application whose resource set can still change while it is executing cyclically is not one whose behavior can be fully verified ahead of time.

rte_appmanager_run() is this framework's own INIT/RUN boundary: it calls rte_lifecycle_lock() the moment ops->init() returns successfully (see that function's own doc) and rte_lifecycle_unlock() at the very start of every call (mirroring its own existing g_app_state reset - see rte_appmanager.c). Every setup-only constructor this framework ships (rte_timer_create(), rte_channel_init(), rte_voter_init()/_register_channel(), rte_cross_comparator_init()/_register_channel(), rte_watchdog_create()) calls rte_lifecycle_check_setup_allowed() as one of its own first checks and returns RTE_STATUS_INVALID_STATE once locked - see each function's own doc for exactly where.

Deliberately excluded (ADR-026 section 3): rte_netlink_open(), rte_dual_channel_init(), and rte_dual_negotiator_init() are NOT gated by this lock. All three are legitimately re-invoked after RUN has begun by an application's own reconnect-after-link-loss logic (e.g. RBC_GP's former channel_ab_io.c/channel_ab_negotiate_reconnect()), which is re-establishing a link the application already owns, not adding a new one the application's own design never accounted for - see ADR-026 for the full rationale on why that distinction, not the "called after RUN" timing alone, is what this lock actually polices.

This is a single, process-wide flag (ADR-026 section 2, same single-instance assumption rte_appmanager's own g_app_state already makes - see that module's own file header) - not one lock per rte_appmanager_config_t, since this framework has no concept of more than one concurrently-running application per process today.

REQ-LIFECYCLE-001: setup-only constructors shall reject their call with RTE_STATUS_INVALID_STATE once the application's setup phase has been locked. REQ-LIFECYCLE-003: a rejected setup-only call shall be reported through rte_safestate_enter(RTE_SAFESTATE_LEVEL_DEGRADED, RTE_SAFESTATE_REASON_SETUP_AFTER_INIT, ...) before returning RTE_STATUS_INVALID_STATE (OSA model: a resource created after initialisation is a critical error reported to the platform's diagnostics). Gated since 2026-10-02 as well: rte_task_create(), rte_task_start(), rte_timer_start(), rte_ipc_create(), rte_nvm_open(), rte_channel_service_setup() (a POSIX task/timer start creates a thread). REQ-LIFECYCLE-002: the setup-phase lock shall be a plain, unsynchronized global (no dynamic allocation, no OS dependency) - this module has no OS dependency of its own, matching rte_safestate's own posture (ADR-002 section 4).

Definition in file rte_lifecycle.h.