linux: Lock Memory and Increase Priority (#6131)

Realtime programming best practice is to lock realtime code
memory to prevent paging which will lead to unbounded latencies. The
Linux MCU process has well bounded memory and small RAM footprint
so locking the entire process' RAM has no downsides and will improve
behavior when the system comes under memory pressure.
(See bootlin training and Linux Foundation documentation linked below.)
RT process priority ranges from 0-99 (although POSIX only requires 32),
boost MCU process priority to half the max/2 to improve robustness when
the system comes under pressure from other RT Kernel or user processes.

Reference links:
bootlin: https://bootlin.com/doc/training/preempt-rt/preempt-rt-slides.pdf
Linux Foundation: https://wiki.linuxfoundation.org/realtime/documentation/howto/applications/application_base#howto_build_a_simple_rt_application

Signed-off-by: Matthew Swabey <matthew@swabey.org>
This commit is contained in:
Dr. Matthew Swabey 2023-03-27 21:34:24 -04:00 committed by GitHub
parent d518152ab2
commit 4026365270
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 9 additions and 2 deletions

View File

@ -4,10 +4,11 @@
// //
// This file may be distributed under the terms of the GNU GPLv3 license. // This file may be distributed under the terms of the GNU GPLv3 license.
#include </usr/include/sched.h> // sched_setscheduler #include </usr/include/sched.h> // sched_setscheduler sched_get_priority_max
#include <stdio.h> // fprintf #include <stdio.h> // fprintf
#include <string.h> // memset #include <string.h> // memset
#include <unistd.h> // getopt #include <unistd.h> // getopt
#include <sys/mman.h> // mlockall MCL_CURRENT MCL_FUTURE
#include "board/misc.h" // console_sendf #include "board/misc.h" // console_sendf
#include "command.h" // DECL_CONSTANT #include "command.h" // DECL_CONSTANT
#include "internal.h" // console_setup #include "internal.h" // console_setup
@ -25,12 +26,18 @@ realtime_setup(void)
{ {
struct sched_param sp; struct sched_param sp;
memset(&sp, 0, sizeof(sp)); memset(&sp, 0, sizeof(sp));
sp.sched_priority = 1; sp.sched_priority = sched_get_priority_max(SCHED_FIFO) / 2;
int ret = sched_setscheduler(0, SCHED_FIFO, &sp); int ret = sched_setscheduler(0, SCHED_FIFO, &sp);
if (ret < 0) { if (ret < 0) {
report_errno("sched_setscheduler", ret); report_errno("sched_setscheduler", ret);
return -1; return -1;
} }
// Lock ourselves into memory
ret = mlockall(MCL_CURRENT | MCL_FUTURE);
if (ret) {
report_errno("mlockall", ret);
return -1;
}
return 0; return 0;
} }