Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Toggle main menu visibility
Loading...
Searching...
No Matches
sapi_safestate.c
Go to the documentation of this file.
1
6
#include "
safeapi/utils/safestate/sapi_safestate.h
"
7
#include "
safeapi/utils/lifecycle/sapi_lifecycle.h
"
8
10
12
15
static
sapi_safestate_handler_t
s_handlers
[3] = { NULL, NULL, NULL };
16
18
27
static
bool
sapi_safestate_level_to_index
(
sapi_safestate_level_t
level,
size_t
*out_index);
28
29
31
sapi_status_t
sapi_safestate_register_handler
(
sapi_safestate_level_t
level,
32
sapi_safestate_handler_t
handler)
33
{
34
size_t
index;
35
sapi_status_t
lifecycle_status;
36
37
if
((handler == NULL) || (!
sapi_safestate_level_to_index
(level, &index)))
38
{
39
return
SAPI_STATUS_INVALID_PARAM
;
40
}
41
/* REQ-LIFECYCLE-001 (ADR-026): a safe-state handler is a setup-only
42
* resource - refuse once the application's setup phase has been locked. */
43
lifecycle_status =
sapi_lifecycle_check_setup_allowed
();
44
if
(lifecycle_status !=
SAPI_STATUS_OK
)
45
{
46
return
lifecycle_status;
47
}
48
s_handlers
[index] = handler;
49
return
SAPI_STATUS_OK
;
50
}
51
52
void
sapi_safestate_enter
(
sapi_safestate_level_t
level,
53
sapi_safestate_reason_t
reason,
54
const
char
*file,
55
int32_t line,
56
const
char
*message)
57
{
58
size_t
index;
59
bool
valid_level =
sapi_safestate_level_to_index
(level, &index);
60
sapi_safestate_handler_t
handler = NULL;
61
62
if
(valid_level)
63
{
64
handler =
s_handlers
[index];
65
}
66
67
if
(handler != NULL)
68
{
69
handler(level, reason, file, line, message);
70
}
71
72
/* REQ-COMMON-SAFESTATE-002: SAFE and REBOOT never return control to the
73
* caller - not even if the handler above misbehaved and returned, and
74
* not even if no handler was registered at all. An unrecognized level
75
* value is itself treated as a fault and handled the same defensive
76
* way, since a corrupted `level` argument cannot be trusted to mean
77
* DEGRADED. */
78
if
((!valid_level) || (level ==
SAPI_SAFESTATE_LEVEL_SAFE
) || (level ==
SAPI_SAFESTATE_LEVEL_REBOOT
))
79
{
80
for
(;;)
/* GCOVR_EXCL_LINE - see tests/safestate/test_sapi_safestate.c's
81
* test_unrecognized_level_halts_forever() for why: this line
82
* IS proven to execute at runtime (via a SIGALRM escape),
83
* but gcov's flow-graph line-count reconstruction always
84
* reports 0 for a `for(;;){}` with no outgoing edge,
85
* regardless of how many times it actually ran - a tool
86
* limitation, not a real gap. */
87
{
88
/* Defensive halt: intentionally never returns. */
89
}
90
}
91
}
92
93
94
/****Local functions ****/
95
96
static
bool
sapi_safestate_level_to_index
(
sapi_safestate_level_t
level,
size_t
*out_index)
97
{
98
bool
found;
99
100
switch
(level)
101
{
102
case
SAPI_SAFESTATE_LEVEL_DEGRADED
:
103
*out_index = 0U;
104
found =
true
;
105
break
;
106
case
SAPI_SAFESTATE_LEVEL_SAFE
:
107
*out_index = 1U;
108
found =
true
;
109
break
;
110
case
SAPI_SAFESTATE_LEVEL_REBOOT
:
111
*out_index = 2U;
112
found =
true
;
113
break
;
114
default
:
115
found =
false
;
116
break
;
117
}
118
return
found;
119
}
sapi_lifecycle_check_setup_allowed
sapi_status_t sapi_lifecycle_check_setup_allowed(void)
Convenience check for a setup-only constructor: call this as one of the first checks in any function ...
Definition
sapi_lifecycle.c:40
sapi_safestate_register_handler
sapi_status_t sapi_safestate_register_handler(sapi_safestate_level_t level, sapi_safestate_handler_t handler)
Registers the reaction handler for one safe-state level. This is how an integrator supplies their own...
Definition
sapi_safestate.c:31
sapi_safestate_reason_t
uint16_t sapi_safestate_reason_t
Diagnostic reason code accompanying a safe-state transition.
Definition
sapi_safestate.h:63
sapi_safestate_level_t
sapi_safestate_level_t
Safe-state severity levels (ADR-004 section 2.1).
Definition
sapi_safestate.h:42
sapi_safestate_enter
void sapi_safestate_enter(sapi_safestate_level_t level, sapi_safestate_reason_t reason, const char *file, int32_t line, const char *message)
Enters a safe-state level: invokes the registered handler (if any), then, for SAPI_SAFESTATE_LEVEL_SA...
Definition
sapi_safestate.c:52
sapi_safestate_handler_t
void(*) sapi_safestate_handler_t(sapi_safestate_level_t level, sapi_safestate_reason_t reason, const char *file, int32_t line, const char *message)
Application-supplied reaction for one safe-state level.
Definition
sapi_safestate.h:91
SAPI_SAFESTATE_LEVEL_REBOOT
@ SAPI_SAFESTATE_LEVEL_REBOOT
Definition
sapi_safestate.h:53
SAPI_SAFESTATE_LEVEL_SAFE
@ SAPI_SAFESTATE_LEVEL_SAFE
Definition
sapi_safestate.h:49
SAPI_SAFESTATE_LEVEL_DEGRADED
@ SAPI_SAFESTATE_LEVEL_DEGRADED
Definition
sapi_safestate.h:45
sapi_status_t
sapi_status_t
Common result/status codes.
Definition
sapi_status.h:27
SAPI_STATUS_INVALID_PARAM
@ SAPI_STATUS_INVALID_PARAM
Definition
sapi_status.h:29
SAPI_STATUS_OK
@ SAPI_STATUS_OK
Definition
sapi_status.h:28
sapi_lifecycle.h
Process-wide application setup-phase lock (ADR-026).
sapi_safestate_level_to_index
static bool sapi_safestate_level_to_index(sapi_safestate_level_t level, size_t *out_index)
Maps a level enumerator to its handler-array index.
Definition
sapi_safestate.c:96
s_handlers
static sapi_safestate_handler_t s_handlers[3]
Definition
sapi_safestate.c:15
sapi_safestate.h
Safe-state transitions and checked assertions (ADR-004).
src
utils
safestate
sapi_safestate.c
Generated by
1.18.0