From 22d49a13f4c95b864fa5740f1cb6826e74ab512c Mon Sep 17 00:00:00 2001 From: Efsane Soyer Date: Wed, 27 Mar 2024 17:15:26 -0700 Subject: [PATCH 1/4] made MIN_SLEEP_DURATION a platform property based on clk res --- core/threaded/reactor_threaded.c | 2 ++ include/core/reactor_common.h | 2 +- low_level_platform/api/platform/lf_unix_clock_support.h | 2 ++ low_level_platform/impl/src/lf_unix_clock_support.c | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index e364675d6..62eaef6c2 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -28,6 +28,8 @@ #include "reactor_common.h" #include "watchdog.h" +#include "platform/lf_unix_clock_support.h" + #ifdef FEDERATED #include "federate.h" #endif diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index fc1451a96..3e0ec1a38 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -42,7 +42,7 @@ * to prevent unnecessary delays caused by simply setting up and * performing the wait. */ -#define MIN_SLEEP_DURATION USEC(10) +// #define MIN_SLEEP_DURATION USEC(10) ////////////////////// Global Variables ////////////////////// diff --git a/low_level_platform/api/platform/lf_unix_clock_support.h b/low_level_platform/api/platform/lf_unix_clock_support.h index 0a2c80163..ca6c4e033 100644 --- a/low_level_platform/api/platform/lf_unix_clock_support.h +++ b/low_level_platform/api/platform/lf_unix_clock_support.h @@ -1,6 +1,8 @@ #include #include +extern instant_t MIN_SLEEP_DURATION; + /** * @brief Convert a _lf_time_spec_t ('tp') to an instant_t representation in * nanoseconds. diff --git a/low_level_platform/impl/src/lf_unix_clock_support.c b/low_level_platform/impl/src/lf_unix_clock_support.c index b9c9fae56..30881408e 100644 --- a/low_level_platform/impl/src/lf_unix_clock_support.c +++ b/low_level_platform/impl/src/lf_unix_clock_support.c @@ -6,6 +6,8 @@ #include "logging.h" #include "platform/lf_unix_clock_support.h" +instant_t MIN_SLEEP_DURATION; + instant_t convert_timespec_to_ns(struct timespec tp) { return ((instant_t)tp.tv_sec) * BILLION + tp.tv_nsec; } struct timespec convert_ns_to_timespec(instant_t t) { @@ -23,6 +25,7 @@ void _lf_initialize_clock() { } lf_print("---- System clock resolution: %ld nsec", res.tv_nsec); + MIN_SLEEP_DURATION = NSEC(res.tv_nsec); } /** From 0fc0a407596a03886c5bba4c4d98eb520f49c7ba Mon Sep 17 00:00:00 2001 From: Efsane Soyer Date: Wed, 27 Mar 2024 18:35:38 -0700 Subject: [PATCH 2/4] Busy wait if the wait time < MIN_SLEEP_DURATION --- core/threaded/reactor_threaded.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 62eaef6c2..7d1a34812 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -241,6 +241,9 @@ bool wait_until(instant_t logical_time, lf_cond_t* condition) { if (wait_duration < MIN_SLEEP_DURATION) { LF_PRINT_DEBUG("Wait time " PRINTF_TIME " is less than MIN_SLEEP_DURATION " PRINTF_TIME ". Skipping wait.", wait_duration, MIN_SLEEP_DURATION); + while (lf_time_physical() < wait_until_time) { + //Busy wait + } return true; } From bb552dceaf6549a14f93206133d340462fd3d4cb Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 28 Jan 2025 11:26:23 -0700 Subject: [PATCH 3/4] Rename `MIN_SLEEP_DURATION` to `lf_min_sleep_duration` and update comments --- core/federated/federate.c | 8 ++++---- core/threaded/reactor_threaded.c | 6 +++--- include/core/reactor_common.h | 15 --------------- include/core/threaded/reactor_threaded.h | 4 ++-- .../api/platform/lf_unix_clock_support.h | 13 ++++++++++++- .../impl/src/lf_unix_clock_support.c | 4 ++-- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index f7f52e37a..176f4dd4c 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1123,13 +1123,13 @@ static void* update_ports_from_staa_offsets(void* args) { // we require a minimum wait time here. Note that zero-valued STAAs are // included, and STA might be zero or very small. // In this case, this thread will fail to ever release the environment mutex. - // This causes chaos. The MIN_SLEEP_DURATION is the smallest amount of time + // This causes chaos. The lf_min_sleep_duration is the smallest amount of time // that wait_until will actually wait. Note that this strategy does not // block progress of any execution that is actually processing events. // It only slightly delays the decision that an event is absent, and only // if the STAA and STA are extremely small. - if (wait_time < 5 * MIN_SLEEP_DURATION) { - wait_until_time += 5 * MIN_SLEEP_DURATION; + if (wait_time < 5 * lf_min_sleep_duration) { + wait_until_time += 5 * lf_min_sleep_duration; } while (a_port_is_unknown(staa_elem)) { LF_PRINT_DEBUG("**** (update thread) waiting until: " PRINTF_TIME, wait_until_time - lf_time_start()); @@ -1197,7 +1197,7 @@ static void* update_ports_from_staa_offsets(void* args) { // The wait is necessary to prevent a busy wait, which will only occur if port // status are always known inside the while loop // Be sure to use wait_until() instead of sleep() because sleep() will not release the mutex. - instant_t wait_until_time = lf_time_add(env->current_tag.time, 2 * MIN_SLEEP_DURATION); + instant_t wait_until_time = lf_time_add(env->current_tag.time, 2 * lf_min_sleep_duration); wait_until(wait_until_time, &lf_port_status_changed); continue; diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index ebdb6f337..d0d108277 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -201,9 +201,9 @@ bool wait_until(instant_t wait_until_time, lf_cond_t* condition) { LF_PRINT_DEBUG("-------- Waiting until physical time " PRINTF_TIME, wait_until_time - start_time); // Check whether we actually need to wait, or if we have already passed the timepoint. interval_t wait_duration = wait_until_time - lf_time_physical(); - if (wait_duration < MIN_SLEEP_DURATION) { - LF_PRINT_DEBUG("Wait time " PRINTF_TIME " is less than MIN_SLEEP_DURATION " PRINTF_TIME ". Skipping wait.", - wait_duration, MIN_SLEEP_DURATION); + if (wait_duration < lf_min_sleep_duration) { + LF_PRINT_DEBUG("Wait time " PRINTF_TIME " is less than lf_min_sleep_duration " PRINTF_TIME ". Performing busy wait.", + wait_duration, lf_min_sleep_duration); while (lf_time_physical() < wait_until_time) { //Busy wait } diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index 242e659b1..0221a310b 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -29,21 +29,6 @@ #include "modes.h" #include "port.h" -////////////////////// Constants & Macros ////////////////////// - -/** - * @brief Constant giving the minimum amount of time to sleep to wait - * for physical time to reach a logical time. - * - * Unless the "fast" option is given, an LF program will wait until - * physical time matches logical time before handling an event with - * a given logical time. The amount of time is less than this given - * threshold, then no wait will occur. The purpose of this is - * to prevent unnecessary delays caused by simply setting up and - * performing the wait. - */ -// #define MIN_SLEEP_DURATION USEC(10) - ////////////////////// Global Variables ////////////////////// // The following variables are defined in reactor_common.c and used in reactor.c, diff --git a/include/core/threaded/reactor_threaded.h b/include/core/threaded/reactor_threaded.h index 2f5463165..2891ee730 100644 --- a/include/core/threaded/reactor_threaded.h +++ b/include/core/threaded/reactor_threaded.h @@ -94,8 +94,8 @@ void lf_synchronize_with_other_federates(void); * * The mutex lock associated with the condition argument is assumed to be held by * the calling thread. This mutex is released while waiting. If the wait time is - * too small to actually wait (less than MIN_SLEEP_DURATION), then this function - * immediately returns true and the mutex is not released. + * too small (less than lf_min_sleep_duration) to wait using lf_clock_cond_timedwait, + * then this function performs busy wait and the mutex is not released. * * @param env Environment within which we are executing. * @param wait_until_time The time to wait until physical time matches it. diff --git a/low_level_platform/api/platform/lf_unix_clock_support.h b/low_level_platform/api/platform/lf_unix_clock_support.h index ca6c4e033..53cf4e039 100644 --- a/low_level_platform/api/platform/lf_unix_clock_support.h +++ b/low_level_platform/api/platform/lf_unix_clock_support.h @@ -1,7 +1,18 @@ #include #include -extern instant_t MIN_SLEEP_DURATION; +/** + * @brief Constant giving the minimum amount of time to sleep to wait + * for physical time to reach a logical time. + * + * Unless the "fast" option is given, an LF program will wait until + * physical time matches logical time before handling an event with + * a given logical time. The amount of time is less than this given + * threshold, then no wait will occur. The purpose of this is + * to prevent unnecessary delays caused by simply setting up and + * performing the wait. + */ +extern instant_t lf_min_sleep_duration; /** * @brief Convert a _lf_time_spec_t ('tp') to an instant_t representation in diff --git a/low_level_platform/impl/src/lf_unix_clock_support.c b/low_level_platform/impl/src/lf_unix_clock_support.c index 30881408e..d2511c0d2 100644 --- a/low_level_platform/impl/src/lf_unix_clock_support.c +++ b/low_level_platform/impl/src/lf_unix_clock_support.c @@ -6,7 +6,7 @@ #include "logging.h" #include "platform/lf_unix_clock_support.h" -instant_t MIN_SLEEP_DURATION; +instant_t lf_min_sleep_duration; instant_t convert_timespec_to_ns(struct timespec tp) { return ((instant_t)tp.tv_sec) * BILLION + tp.tv_nsec; } @@ -25,7 +25,7 @@ void _lf_initialize_clock() { } lf_print("---- System clock resolution: %ld nsec", res.tv_nsec); - MIN_SLEEP_DURATION = NSEC(res.tv_nsec); + lf_min_sleep_duration = NSEC(res.tv_nsec); } /** From c2b5f8d44b68add782309cebfeacfa0de7ec666d Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 28 Jan 2025 11:34:13 -0700 Subject: [PATCH 4/4] Apply clang-format --- core/threaded/reactor_threaded.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index d0d108277..944b93778 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -202,10 +202,11 @@ bool wait_until(instant_t wait_until_time, lf_cond_t* condition) { // Check whether we actually need to wait, or if we have already passed the timepoint. interval_t wait_duration = wait_until_time - lf_time_physical(); if (wait_duration < lf_min_sleep_duration) { - LF_PRINT_DEBUG("Wait time " PRINTF_TIME " is less than lf_min_sleep_duration " PRINTF_TIME ". Performing busy wait.", + LF_PRINT_DEBUG("Wait time " PRINTF_TIME " is less than lf_min_sleep_duration " PRINTF_TIME + ". Performing busy wait.", wait_duration, lf_min_sleep_duration); while (lf_time_physical() < wait_until_time) { - //Busy wait + // Busy wait } return true; }