From 2b7c536500e2eaebdb6f5325e37fd3db630282d7 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 11 Dec 2025 16:46:04 +0000 Subject: [PATCH] Add memory locking for deterministic PLC execution - Add lock_memory() function that calls mlockall(MCL_CURRENT | MCL_FUTURE) - Call lock_memory() after set_realtime_priority() in plc_cycle_thread() - Add sys/mman.h include for mlockall support This prevents the kernel from swapping out memory pages during PLC execution, eliminating unpredictable latency spikes caused by page faults in the scan cycle. Requires container to have memlock ulimit set to unlimited (--ulimit memlock=-1). Co-Authored-By: Thiago Alves --- core/src/plc_app/plc_state_manager.c | 3 ++- core/src/plc_app/utils/utils.c | 14 ++++++++++++++ core/src/plc_app/utils/utils.h | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/src/plc_app/plc_state_manager.c b/core/src/plc_app/plc_state_manager.c index d43b4837..3982be6a 100644 --- a/core/src/plc_app/plc_state_manager.c +++ b/core/src/plc_app/plc_state_manager.c @@ -23,8 +23,9 @@ void *plc_cycle_thread(void *arg) { PluginManager *pm = (PluginManager *)arg; - // Initialize PLC + // Initialize PLC with real-time optimizations set_realtime_priority(); + lock_memory(); symbols_init(pm); ext_config_init__(); ext_glueVars(); diff --git a/core/src/plc_app/utils/utils.c b/core/src/plc_app/utils/utils.c index 9ea41d69..d01586cc 100644 --- a/core/src/plc_app/utils/utils.c +++ b/core/src/plc_app/utils/utils.c @@ -2,6 +2,7 @@ #include #include #include +#include #include unsigned long long *ext_common_ticktime__ = NULL; @@ -55,6 +56,19 @@ void set_realtime_priority(void) } } +// Lock all memory pages to prevent page faults during PLC execution +void lock_memory(void) +{ + if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) + { + log_error("mlockall failed: %s", strerror(errno)); + } + else + { + log_info("Memory locked successfully (MCL_CURRENT | MCL_FUTURE)"); + } +} + size_t parse_hex_string(const char *hex_string, uint8_t *data) { size_t count = 0; diff --git a/core/src/plc_app/utils/utils.h b/core/src/plc_app/utils/utils.h index 5e04384a..c3c8e88a 100644 --- a/core/src/plc_app/utils/utils.h +++ b/core/src/plc_app/utils/utils.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -42,6 +43,14 @@ void timespec_diff(struct timespec *a, struct timespec *b, */ void set_realtime_priority(void); +/** + * @brief Lock all current and future memory pages to prevent page faults + * + * This prevents the kernel from swapping out memory pages during PLC execution, + * which could cause unpredictable latency spikes in the scan cycle. + */ +void lock_memory(void); + /** * @brief Parse a hex string into a byte array *