SafeAPI Backend POSIX
POSIX/Linux OAL backend for safeAPIFreamwork
Loading...
Searching...
No Matches
sapi_posix_backend_platform.c
Go to the documentation of this file.
1/* _GNU_SOURCE: this file needs RLIMIT_MEMLOCK / getrlimit() (XSI, not base
2 * POSIX), mlockall()/MCL_FUTURE (<sys/mman.h>) and the POSIX scheduling
3 * API together - _GNU_SOURCE exposes all three on glibc. Harmless on
4 * non-Linux libc; the Linux-only calls are __linux__-guarded below anyway.
5 * Must be defined before any header is included. */
6#define _GNU_SOURCE
7
34
35#if defined(__linux__)
36#include <sys/mman.h>
37#include <sys/resource.h>
38#include <sched.h>
39#include <pthread.h>
40#include <stdio.h>
41#include <errno.h>
42#include <string.h>
43#include "safeapi/oal/memory/sapi_mem_util.h"
44#include "safeapi/oal/log/sapi_log.h"
45#endif
46
48#if defined(__linux__)
51#define POSIX_PLATFORM_STACK_PREFAULT_BYTES (128U * 1024U)
53#define POSIX_PLATFORM_PAGE_BYTES 4096U
54#endif
55
57
59static sapi_status_t backend_realtime_init(uint32_t rt_priority);
60#if defined(__linux__)
61static void posix_platform_lock_memory(void);
62static void posix_platform_prefault_stack(void);
63static void posix_platform_set_rt_priority(uint32_t rt_priority);
64#endif
65
67static const sapi_platform_backend_t s_posix_platform_backend = { backend_realtime_init };
68
70
71
73const sapi_platform_backend_t *sapi_posix_backend_platform(void)
74{
76}
77
78
79/****Local functions ****/
80
81static sapi_status_t backend_realtime_init(uint32_t rt_priority)
82{
83 /* The framework (sapi_platform_realtime_init) has already rejected
84 * rt_priority > 99 before dispatching here. */
85#if defined(__linux__)
86 posix_platform_lock_memory();
87 posix_platform_prefault_stack();
88 if (rt_priority > 0U)
89 {
90 posix_platform_set_rt_priority(rt_priority);
91 }
92#else
93 (void)rt_priority;
94#endif
95 return SAPI_STATUS_OK;
96}
97
98#if defined(__linux__)
99static void posix_platform_lock_memory(void)
100{
101 struct rlimit memlock_limit;
102 int lock_flags = MCL_CURRENT | MCL_FUTURE;
103 char msg[160];
104
105 if ((getrlimit(RLIMIT_MEMLOCK, &memlock_limit) == 0) && (memlock_limit.rlim_cur != RLIM_INFINITY))
106 {
107 /* Bounded lockable memory: MCL_FUTURE here would make the next
108 * pthread_create() fail with EAGAIN (see file header). Lock only
109 * what is already mapped. */
110 lock_flags = MCL_CURRENT;
111 (void)snprintf(msg, sizeof(msg),
112 "RLIMIT_MEMLOCK bounded at %lu KiB - locking current memory only "
113 "(MCL_FUTURE would break later thread creation)",
114 (unsigned long)(memlock_limit.rlim_cur / 1024UL));
115 sapi_log_write(SAPI_LOG_LEVEL_WARNING, "RT-LINUX", msg);
116 }
117
118 if (mlockall(lock_flags) != 0)
119 {
120 (void)snprintf(msg, sizeof(msg), "mlockall(0x%x) skipped or not permitted (errno=%d: %s)",
121 (unsigned int)lock_flags, errno, strerror(errno));
122 sapi_log_write(SAPI_LOG_LEVEL_WARNING, "RT-LINUX", msg);
123 }
124 else if (lock_flags == MCL_CURRENT)
125 {
126 sapi_log_write(SAPI_LOG_LEVEL_INFO, "RT-LINUX", "mlockall(MCL_CURRENT) enabled: current memory locked into RAM");
127 }
128 else
129 {
130 sapi_log_write(SAPI_LOG_LEVEL_INFO, "RT-LINUX",
131 "mlockall(MCL_CURRENT|MCL_FUTURE) enabled: memory locked into RAM");
132 }
133}
134
135static void posix_platform_prefault_stack(void)
136{
137 volatile uint8_t dummy_stack[POSIX_PLATFORM_STACK_PREFAULT_BYTES];
138 size_t page_idx;
139
140 for (page_idx = 0U; page_idx < sizeof(dummy_stack); page_idx += POSIX_PLATFORM_PAGE_BYTES)
141 {
142 dummy_stack[page_idx] = 0U;
143 }
144}
145
146static void posix_platform_set_rt_priority(uint32_t rt_priority)
147{
148 struct sched_param sched;
149 int min_prio = sched_get_priority_min(SCHED_FIFO);
150 int max_prio = sched_get_priority_max(SCHED_FIFO);
151 int wanted = (int)rt_priority;
152 char msg[128];
153
154 if ((min_prio < 0) || (max_prio < 0))
155 {
156 return;
157 }
158 if (wanted < min_prio)
159 {
160 wanted = min_prio;
161 }
162 if (wanted > max_prio)
163 {
164 wanted = max_prio;
165 }
166
167 sapi_mem_set(&sched, 0, sizeof(sched));
168 sched.sched_priority = wanted;
169
170 if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sched) == 0)
171 {
172 (void)snprintf(msg, sizeof(msg), "SCHED_FIFO priority successfully set to %d", wanted);
173 sapi_log_write(SAPI_LOG_LEVEL_INFO, "RT-LINUX", msg);
174 }
175 else
176 {
177 (void)snprintf(msg, sizeof(msg), "pthread_setschedparam(SCHED_FIFO, prio=%d) skipped or unprivileged (errno=%d: %s)",
178 wanted, errno, strerror(errno));
179 sapi_log_write(SAPI_LOG_LEVEL_WARNING, "RT-LINUX", msg);
180 }
181}
182#endif /* __linux__ */
Real POSIX/Linux backend for every OAL service (ADR-018).
const sapi_platform_backend_t * sapi_posix_backend_platform(void)
The POSIX sapi_platform backend (ADR-035): real-time bring-up via mlockall() + SCHED_FIFO,...
static sapi_status_t backend_realtime_init(uint32_t rt_priority)
static const sapi_platform_backend_t s_posix_platform_backend