From 33ec1fa27431b9e4def6816c59749ad7db6e064c Mon Sep 17 00:00:00 2001 From: Erling Rennemo Jellum Date: Mon, 9 Oct 2023 18:59:16 +0200 Subject: [PATCH 01/95] Add thread CPU affinity, priority and scheduler init to platform API Also provide an POSIX implementation of this API. Currently it defaults to SCHED_FIFO. This is debatable. --- core/platform/lf_POSIX_threads_support.c | 52 ++++++++++++++++++++++++ include/core/platform.h | 43 ++++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index 180cde8cd..c7843f33a 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -3,9 +3,34 @@ #include "lf_POSIX_threads_support.h" #include +#include #include #include // For fixed-width integral types +int lf_thread_scheduler_init() { + struct sched_param schedparam; + pthread_attr_t attr; + + // Set the current (main) threads scheduling policy to FIFO + schedparam.sched_priority = 3; + if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedparam) != 0) { + return -1; + } + + // Make any thread spawned from this thread inherit this policy + if (pthread_attr_init(&attr) != 0) { + return -2; + } + if (pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) != 0) { + return -3; + } + + // Clean up the attribute when you're done using it + pthread_attr_destroy(&attr); + + return 0; +} + int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { return pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); } @@ -33,6 +58,33 @@ int lf_mutex_init(lf_mutex_t* mutex) { return pthread_mutex_init((pthread_mutex_t*)mutex, &attr); } +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + // First verify that we have num_cores>cpu_number + if (lf_available_cores() <= cpu_number) { + return -1; + } + + // Create a CPU-set consisting of only the desired CPU + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + CPU_SET(cpu_number); + + return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); +} + + +int lf_thread_set_priority(lf_thread_t thread, int priority) [ + return pthread_setschedprio(thread, priority); +] + +int lf_thread_get_priority(lf_thread_t thread) { + return pthread_getschedprio(thread, priority); +} + +lf_thread_t lf_thread_self() { + return pthread_self(); +} + int lf_mutex_lock(lf_mutex_t* mutex) { return pthread_mutex_lock((pthread_mutex_t*)mutex); } diff --git a/include/core/platform.h b/include/core/platform.h index a32cfb516..9622b711a 100644 --- a/include/core/platform.h +++ b/include/core/platform.h @@ -135,6 +135,13 @@ int lf_critical_section_exit(environment_t* env); #if defined LF_THREADED +/** + * Initializes the underlying thread scheduler. + * + * @return int 0 on success, platform-specific error number otherwise. + */ +int lf_thread_scheduler_init(); + /** * @brief Get the number of cores on the host machine. */ @@ -160,6 +167,41 @@ int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arg */ int lf_thread_join(lf_thread_t thread, void** thread_return); +/** + * This pins a lf_thread to a specific CPU + * + * @param thread The thread + * @param cpu_number the CPU ID + * @return 0 on success, platform-specific error number otherwise. + */ +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); + +/** + * Sets the priority of a thread. Priority ranges from 0 to 99 where a higher + * number indicates higher priority. + * + * @param thread The thread. + * @param priority The priority. + * @return int 0 on success, platform-specific error otherwise + */ +int lf_thread_set_priority(lf_thread_t thread, int priority) + +/** + * Gets the priority of a thread. Priority ranges from 0 to 99 where a higher + * number indicates higher priority. + * + * @param thread The thread. + * @return The priority or platform-specific negative number otherwise + */ +int lf_thread_get_priority(lf_thread_t thread) + +/** + * Returns the thread ID of the calling thread + * + */ +lf_thread_t lf_thread_self(); + + /** * Initialize a mutex. * @@ -220,6 +262,7 @@ int lf_cond_wait(lf_cond_t* cond); */ int lf_cond_timedwait(lf_cond_t* cond, instant_t absolute_time_ns); + /* * Atomically increment the variable that ptr points to by the given value, and return the original value of the variable. * @param ptr A pointer to a variable. The value of this variable will be replaced with the result of the operation. From 4144af2ca66e273ae8f763631239ee2c62a19a0d Mon Sep 17 00:00:00 2001 From: Erling Rennemo Jellum Date: Mon, 9 Oct 2023 20:19:52 +0200 Subject: [PATCH 02/95] Hard-code usage of pthreads++ for now --- core/CMakeLists.txt | 2 ++ core/platform/lf_POSIX_threads_support.c | 16 +++++++++------- core/platform/lf_linux_support.c | 5 ----- core/platform/lf_unix_clock_support.c | 2 ++ include/core/platform.h | 11 +---------- include/core/platform/lf_linux_support.h | 4 ---- 6 files changed, 14 insertions(+), 26 deletions(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index a9026392c..264239595 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -124,3 +124,5 @@ define(SCHEDULER) define(LF_SOURCE_DIRECTORY) define(LF_PACKAGE_DIRECTORY) define(LF_FILE_SEPARATOR) + +target_compile_definitions(core PUBLIC _GNU_SOURCE=1) \ No newline at end of file diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index c7843f33a..ba6cf7e41 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -32,7 +32,13 @@ int lf_thread_scheduler_init() { } int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { - return pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); + static int core_id=0; + pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); + if (lf_thread_set_cpu(*thread, core_id) != 0) { + lf_print_error_and_exit("Could not set CPU"); + } + core_id++; + return 0; } int lf_thread_join(lf_thread_t thread, void** thread_return) { @@ -67,18 +73,14 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { // Create a CPU-set consisting of only the desired CPU cpu_set_t cpu_set; CPU_ZERO(&cpu_set); - CPU_SET(cpu_number); + CPU_SET(cpu_number, &cpu_set); return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); } -int lf_thread_set_priority(lf_thread_t thread, int priority) [ +int lf_thread_set_priority(lf_thread_t thread, int priority) { return pthread_setschedprio(thread, priority); -] - -int lf_thread_get_priority(lf_thread_t thread) { - return pthread_getschedprio(thread, priority); } lf_thread_t lf_thread_self() { diff --git a/core/platform/lf_linux_support.c b/core/platform/lf_linux_support.c index 3bb5077c8..51eed9103 100644 --- a/core/platform/lf_linux_support.c +++ b/core/platform/lf_linux_support.c @@ -44,12 +44,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #if defined LF_THREADED - #if __STDC_VERSION__ < 201112L || defined (__STDC_NO_THREADS__) - // (Not C++11 or later) or no threads support #include "lf_POSIX_threads_support.c" - #else - #include "lf_C11_threads_support.c" - #endif #endif #include "lf_unix_clock_support.h" diff --git a/core/platform/lf_unix_clock_support.c b/core/platform/lf_unix_clock_support.c index d5c032862..b03f587c9 100644 --- a/core/platform/lf_unix_clock_support.c +++ b/core/platform/lf_unix_clock_support.c @@ -50,6 +50,8 @@ void calculate_epoch_offset(void) { void _lf_initialize_clock() { calculate_epoch_offset(); + + lf_thread_scheduler_init(); } /** diff --git a/include/core/platform.h b/include/core/platform.h index 9622b711a..095f1916a 100644 --- a/include/core/platform.h +++ b/include/core/platform.h @@ -184,16 +184,7 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); * @param priority The priority. * @return int 0 on success, platform-specific error otherwise */ -int lf_thread_set_priority(lf_thread_t thread, int priority) - -/** - * Gets the priority of a thread. Priority ranges from 0 to 99 where a higher - * number indicates higher priority. - * - * @param thread The thread. - * @return The priority or platform-specific negative number otherwise - */ -int lf_thread_get_priority(lf_thread_t thread) +int lf_thread_set_priority(lf_thread_t thread, int priority); /** * Returns the thread ID of the calling thread diff --git a/include/core/platform/lf_linux_support.h b/include/core/platform/lf_linux_support.h index 828deb901..db1017308 100644 --- a/include/core/platform/lf_linux_support.h +++ b/include/core/platform/lf_linux_support.h @@ -39,12 +39,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "lf_tag_64_32.h" #if defined LF_THREADED - #if __STDC_VERSION__ < 201112L || defined (__STDC_NO_THREADS__) // (Not C++11 or later) or no threads support #include "lf_POSIX_threads_support.h" - #else - #include "lf_C11_threads_support.h" - #endif #endif // The underlying physical clock for Linux From 9d845bac6e760586c0cfbea587fbc07a89264db7 Mon Sep 17 00:00:00 2001 From: Erling Rennemo Jellum Date: Thu, 12 Oct 2023 15:50:07 +0200 Subject: [PATCH 03/95] Error if cant configure underlying thread scheduler --- core/platform/lf_unix_clock_support.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/platform/lf_unix_clock_support.c b/core/platform/lf_unix_clock_support.c index b03f587c9..a9c73c563 100644 --- a/core/platform/lf_unix_clock_support.c +++ b/core/platform/lf_unix_clock_support.c @@ -50,8 +50,10 @@ void calculate_epoch_offset(void) { void _lf_initialize_clock() { calculate_epoch_offset(); - - lf_thread_scheduler_init(); + int res = lf_thread_scheduler_init(); + if (res != 0) { + lf_print_error_and_exit("Could not init scheduler res=%i", res); + } } /** From 70551f64c3abf4cf98676c94f899c808d0313168 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 10:48:02 +0100 Subject: [PATCH 04/95] Remove C11 support --- core/platform/lf_C11_threads_support.c | 69 ------------------- core/platform/lf_macos_support.c | 13 +--- .../core/platform/lf_C11_threads_support.h | 44 ------------ include/core/platform/lf_macos_support.h | 7 +- 4 files changed, 3 insertions(+), 130 deletions(-) delete mode 100644 core/platform/lf_C11_threads_support.c delete mode 100644 include/core/platform/lf_C11_threads_support.h diff --git a/core/platform/lf_C11_threads_support.c b/core/platform/lf_C11_threads_support.c deleted file mode 100644 index 98dccb58d..000000000 --- a/core/platform/lf_C11_threads_support.c +++ /dev/null @@ -1,69 +0,0 @@ -#if !defined(LF_SINGLE_THREADED) && !defined(PLATFORM_ARDUINO) -#include "platform.h" -#include "lf_C11_threads_support.h" -#include -#include -#include // For fixed-width integral types - -int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { - return thrd_create((thrd_t*)thread, (thrd_start_t)lf_thread, arguments); -} - -int lf_thread_join(lf_thread_t thread, void** thread_return) { - // thrd_join wants the second argument to be an int* rather than a void** - return thrd_join((thrd_t)thread, (int*)thread_return); -} - -int lf_mutex_init(lf_mutex_t* mutex) { - // Set up a timed and recursive mutex (default behavior) - return mtx_init((mtx_t*)mutex, mtx_timed | mtx_recursive); -} - -int lf_mutex_lock(lf_mutex_t* mutex) { - return mtx_lock((mtx_t*) mutex); -} - -int lf_mutex_unlock(lf_mutex_t* mutex) { - return mtx_unlock((mtx_t*) mutex); -} - -int lf_cond_init(lf_cond_t* cond, lf_mutex_t* mutex) { - cond->mutex = mutex; - return cnd_init((cnd_t*)&cond->condition); -} - -int lf_cond_broadcast(lf_cond_t* cond) { - return cnd_broadcast((cnd_t*)&cond->condition); -} - -int lf_cond_signal(lf_cond_t* cond) { - return cnd_signal((cnd_t*)&cond->condition); -} - -int lf_cond_wait(lf_cond_t* cond) { - return cnd_wait((cnd_t*)&cond->condition, (mtx_t*)cond->mutex); -} - -int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { - struct timespec timespec_absolute_time = { - .tv_sec = wakeup_time / BILLION, - .tv_nsec = wakeup_time % BILLION - }; - - int return_value = cnd_timedwait( - (cnd_t*)&cond->condition, - (mtx_t*)cond->mutex, - ×pec_absolute_time - ); - - switch (return_value) { - case thrd_timedout: - return_value = LF_TIMEOUT; - break; - - default: - break; - } - return return_value; -} -#endif diff --git a/core/platform/lf_macos_support.c b/core/platform/lf_macos_support.c index 84e883b37..038b313b8 100644 --- a/core/platform/lf_macos_support.c +++ b/core/platform/lf_macos_support.c @@ -36,19 +36,10 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if defined LF_SINGLE_THREADED #include "lf_os_single_threaded_support.c" +#else + #include "lf_POSIX_threads_support.c" #endif -#if !defined LF_SINGLE_THREADED - #if __STDC_VERSION__ < 201112L || defined (__STDC_NO_THREADS__) - // (Not C++11 or later) or no threads support - #include "lf_POSIX_threads_support.c" - #else - #include "lf_C11_threads_support.c" - #endif -#endif - - - #include "lf_unix_clock_support.h" // See `man 2 clock_nanosleep` for return values diff --git a/include/core/platform/lf_C11_threads_support.h b/include/core/platform/lf_C11_threads_support.h deleted file mode 100644 index 52423de7c..000000000 --- a/include/core/platform/lf_C11_threads_support.h +++ /dev/null @@ -1,44 +0,0 @@ -/* C11 threads support for the C target of Lingua Franca. */ - -/************* -Copyright (c) 2019, The University of California at Berkeley. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -***************/ - -/** \file if_c11_threads_support.c - * C11 threads support for the C target of Lingua Franca. - * - * @author{Soroush Bateni } - */ -#ifndef LF_C11_THREADS_SUPPORT_H -#define LF_C11_THREADS_SUPPORT_H - -#include - -typedef mtx_t lf_mutex_t; -typedef struct { - lf_mutex_t* mutex; - cnd_t condition; -} lf_cond_t; -typedef thrd_t lf_thread_t; - -#endif diff --git a/include/core/platform/lf_macos_support.h b/include/core/platform/lf_macos_support.h index 60da3c299..bf315c758 100644 --- a/include/core/platform/lf_macos_support.h +++ b/include/core/platform/lf_macos_support.h @@ -38,12 +38,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "lf_tag_64_32.h" #if !defined LF_SINGLE_THREADED - #if __STDC_VERSION__ < 201112L || defined (__STDC_NO_THREADS__) - // (Not C++11 or later) or no threads support - #include "lf_POSIX_threads_support.h" - #else - #include "lf_C11_threads_support.h" - #endif + #include "lf_POSIX_threads_support.h" #endif #endif // LF_MACOS_SUPPORT_H From 5a25ca5072a3e6c2da1e1ce2a4b10a755cf43e7a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 13:07:29 +0100 Subject: [PATCH 05/95] Improve the thread scheduler API --- core/platform/lf_POSIX_threads_support.c | 41 +++++++++++++------ core/platform/lf_linux_support.c | 1 + core/platform/lf_macos_support.c | 1 + core/platform/lf_unix_clock_support.c | 5 --- core/platform/lf_windows_support.c | 21 +++++++--- core/platform/lf_zephyr_support.c | 43 ++++++++++++++++++++ include/core/platform.h | 52 +++++++++++++++++++----- 7 files changed, 131 insertions(+), 33 deletions(-) diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index 1ae1b4b5c..7bbe24261 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -1,5 +1,6 @@ #if !defined(LF_SINGLE_THREADED) && !defined(PLATFORM_ARDUINO) #include "platform.h" +#include "util.h" #include "lf_POSIX_threads_support.h" #include "lf_unix_clock_support.h" @@ -7,28 +8,44 @@ #include #include #include // For fixed-width integral types +#include -int lf_thread_scheduler_init() { +#if defined PLATFORM_Linux +#include +#endif + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { + int posix_policy; struct sched_param schedparam; - pthread_attr_t attr; - // Set the current (main) threads scheduling policy to FIFO - schedparam.sched_priority = 3; - if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedparam) != 0) { + // Get the current scheduling policy + if (pthread_getschedparam(thread, &posix_policy, &schedparam) != 0) { return -1; } - // Make any thread spawned from this thread inherit this policy - if (pthread_attr_init(&attr) != 0) { - return -2; + // Update the policy + switch(policy->policy) { + case LF_SCHED_FAIR: + posix_policy = SCHED_OTHER; + break; + case LF_SCHED_TIMESLICE: + posix_policy = SCHED_RR; + schedparam.sched_priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; + break; + case LF_SCHED_PRIORITY: + posix_policy = SCHED_FIFO; + schedparam.sched_priority = ((lf_scheduling_policy_priority_t *) policy)->priority; + break; + default: + return -1; + break; } - if (pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) != 0) { + + // Write it back + if (pthread_setschedparam(thread, posix_policy, &schedparam) != 0) { return -3; } - // Clean up the attribute when you're done using it - pthread_attr_destroy(&attr); - return 0; } diff --git a/core/platform/lf_linux_support.c b/core/platform/lf_linux_support.c index d1f6b7e24..6c3b477eb 100644 --- a/core/platform/lf_linux_support.c +++ b/core/platform/lf_linux_support.c @@ -32,6 +32,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @author{Marten Lohstroh } */ +#define _GNU_SOURCE #include "lf_linux_support.h" #include "platform.h" #include "tag.h" diff --git a/core/platform/lf_macos_support.c b/core/platform/lf_macos_support.c index 038b313b8..d9991c6d4 100644 --- a/core/platform/lf_macos_support.c +++ b/core/platform/lf_macos_support.c @@ -30,6 +30,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @author{Soroush Bateni } */ +#define _GNU_SOURCE #include "lf_macos_support.h" #include "platform.h" #include "tag.h" diff --git a/core/platform/lf_unix_clock_support.c b/core/platform/lf_unix_clock_support.c index 514512295..43a8653e9 100644 --- a/core/platform/lf_unix_clock_support.c +++ b/core/platform/lf_unix_clock_support.c @@ -25,11 +25,6 @@ void _lf_initialize_clock() { lf_print_error_and_exit("Could not obtain resolution for CLOCK_REALTIME"); } lf_print("---- System clock resolution: %ld nsec", res.tv_nsec); - - return_value = lf_thread_scheduler_init(); - if (return_value != 0) { - lf_print_error_and_exit("Could not init scheduler res=%i", res); - } } /** diff --git a/core/platform/lf_windows_support.c b/core/platform/lf_windows_support.c index 86e8a8271..0a9299958 100644 --- a/core/platform/lf_windows_support.c +++ b/core/platform/lf_windows_support.c @@ -167,8 +167,6 @@ int lf_available_cores() { return sysinfo.dwNumberOfProcessors; } -#if __STDC_VERSION__ < 201112L || defined (__STDC_NO_THREADS__) // (Not C++11 or later) or no threads support - int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { uintptr_t handle = _beginthreadex(NULL, 0, lf_thread, arguments, 0, NULL); *thread = (HANDLE)handle; @@ -194,6 +192,22 @@ int lf_thread_join(lf_thread_t thread, void** thread_return) { return 0; } +lf_thread_t lf_thread_self() { + return GetCurrentThread(); +} + +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + return -1; +} + +int lf_thread_set_priority(lf_thread_t thread, int priority) { + return -1; +} + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_thread_scheduling_policy_t policy) { + return -1; +} + int lf_mutex_init(_lf_critical_section_t* critical_section) { // Set up a recursive mutex InitializeCriticalSection((PCRITICAL_SECTION)critical_section); @@ -297,9 +311,6 @@ int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { // Success return 0; } -#else // If there is C11 support -#include "lf_C11_threads_support.c" -#endif #endif diff --git a/core/platform/lf_zephyr_support.c b/core/platform/lf_zephyr_support.c index f04412430..cbe8f7934 100644 --- a/core/platform/lf_zephyr_support.c +++ b/core/platform/lf_zephyr_support.c @@ -146,6 +146,49 @@ int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arg return 0; } +lf_thread_t lf_thread_self() { + return k_current_get(); +} + +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + return k_thread_cpu_pin(thread, cpu_number); +} + +int lf_thread_set_priority(lf_thread_t thread, int priority) { + k_thread_priority_set(thread, priority); + return 0; +} + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { + // Update the policy + switch(policy->policy) { + case LF_SCHED_FAIR: + break; + case LF_SCHED_TIMESLICE: { + int priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; + interval_t slice = ((lf_scheduling_policy_timeslice_t *) policy)->timeslice; + k_thread_priority_set(thread, 99 - priority); + k_sched_time_slice_set(0, slice/1000000); + break; + } + case LF_SCHED_PRIORITY: { + int priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; + k_thread_priority_set(thread, 99 - priority); + break; + } + default: + return -1; + break; + } + + // Write it back + if (pthread_setschedparam(thread, posix_policy, &schedparam) != 0) { + return -3; + } + + return 0; +} + int lf_thread_join(lf_thread_t thread, void** thread_return) { return k_thread_join(thread, K_FOREVER); } diff --git a/include/core/platform.h b/include/core/platform.h index 93bd0e735..87cbc7534 100644 --- a/include/core/platform.h +++ b/include/core/platform.h @@ -125,16 +125,15 @@ int lf_critical_section_exit(environment_t* env); // abstract the API so that the LF runtime remains portable. /** - * Initializes the underlying thread scheduler. - * - * @return int 0 on success, platform-specific error number otherwise. + * @brief Get the number of cores on the host machine. */ -int lf_thread_scheduler_init(); +int lf_available_cores(); /** - * @brief Get the number of cores on the host machine. + * Returns the thread ID of the calling thread + * */ -int lf_available_cores(); +lf_thread_t lf_thread_self(); /** * Create a new thread, starting with execution of lf_thread @@ -156,6 +155,36 @@ int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arg */ int lf_thread_join(lf_thread_t thread, void** thread_return); + +// The following API introduce the ability to change how the LF workers are sheduled +// by the underlying thread scheduling. This API is still experimental and future +// changes are expected. + +/** + * @brief The thread scheduling policies. + * + */ +typedef enum { + LF_SCHED_FAIR, // Non real-time scheduling policy. Corresponds to SCHED_OTHER + LF_SCHED_TIMESLICE, // Real-time, time-slicing priority-based policty. Corresponds to SCHED_RR. + LF_SCHED_PRIORITY, // Real-time, priority-only based scheduling. Corresponds to SCHED_FIFO. +} lf_scheduling_policy_type_t; + +typedef struct { + lf_scheduling_policy_type_t policy; +} lf_scheduling_policy_t; + +typedef struct { + lf_scheduling_policy_t base; + int priority; + interval_t time_slice; +} lf_scheduling_policy_timeslice_t; + +typedef struct { + lf_scheduling_policy_t base; + int priority; +} lf_scheduling_policy_priority_t; + /** * This pins a lf_thread to a specific CPU * @@ -167,7 +196,8 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); /** * Sets the priority of a thread. Priority ranges from 0 to 99 where a higher - * number indicates higher priority. + * number indicates higher priority. Setting the priority of a thread only + * makes sense if the thread is scheduled with LF_SCHED_TIMESLICE or LF_THREAD_PRIORITY * * @param thread The thread. * @param priority The priority. @@ -176,11 +206,11 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); int lf_thread_set_priority(lf_thread_t thread, int priority); /** - * Returns the thread ID of the calling thread - * + * Sets the scheduling policy of a thread. + * + * @return int 0 on success, platform-specific error number otherwise. */ -lf_thread_t lf_thread_self(); - +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy); /** * Initialize a mutex. From e069ba7b972ad04f4c4a8523e4a70ff782ab1196 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 13:35:26 +0100 Subject: [PATCH 06/95] Remove some outdated changes --- core/platform/lf_POSIX_threads_support.c | 12 +----------- core/platform/lf_zephyr_support.c | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index 7bbe24261..5974f849b 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -10,10 +10,6 @@ #include // For fixed-width integral types #include -#if defined PLATFORM_Linux -#include -#endif - int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { int posix_policy; struct sched_param schedparam; @@ -50,13 +46,7 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t * } int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { - static int core_id=0; - pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); - if (lf_thread_set_cpu(*thread, core_id) != 0) { - lf_print_error_and_exit("Could not set CPU"); - } - core_id++; - return 0; + return pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); } int lf_thread_join(lf_thread_t thread, void** thread_return) { diff --git a/core/platform/lf_zephyr_support.c b/core/platform/lf_zephyr_support.c index cbe8f7934..f248cde1e 100644 --- a/core/platform/lf_zephyr_support.c +++ b/core/platform/lf_zephyr_support.c @@ -155,7 +155,7 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { } int lf_thread_set_priority(lf_thread_t thread, int priority) { - k_thread_priority_set(thread, priority); + k_thread_priority_set(thread, 99 - priority); return 0; } From be17e0a4f4eb2eabf7ac43b01b94ac7b8a006521 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 13:42:51 +0100 Subject: [PATCH 07/95] Remove unix_syscall_support.c --- core/platform/CMakeLists.txt | 1 - core/platform/lf_POSIX_threads_support.c | 4 ++++ core/platform/lf_unix_syscall_support.c | 18 ------------------ 3 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 core/platform/lf_unix_syscall_support.c diff --git a/core/platform/CMakeLists.txt b/core/platform/CMakeLists.txt index eec94db65..89b3abefa 100644 --- a/core/platform/CMakeLists.txt +++ b/core/platform/CMakeLists.txt @@ -3,7 +3,6 @@ set(LF_PLATFORM_FILES lf_unix_clock_support.c - lf_unix_syscall_support.c lf_linux_support.c lf_macos_support.c lf_windows_support.c diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index 5974f849b..0270f135e 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -10,6 +10,10 @@ #include // For fixed-width integral types #include +int lf_available_cores() { + return (int)sysconf(_SC_NPROCESSORS_ONLN); +} + int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { int posix_policy; struct sched_param schedparam; diff --git a/core/platform/lf_unix_syscall_support.c b/core/platform/lf_unix_syscall_support.c deleted file mode 100644 index 331975846..000000000 --- a/core/platform/lf_unix_syscall_support.c +++ /dev/null @@ -1,18 +0,0 @@ -#if defined(PLATFORM_Linux) || defined(PLATFORM_Darwin) -/** - * @file lf_unix_syscall_support.c - * @author Soroush Bateni (soroush@utdallas.edu) - * @brief Platform support for syscalls in Unix-like systems. - * @version 0.1 - * @date 2022-03-09 - * - * @copyright Copyright (c) 2022 The University of Texas at Dallas - * - */ - -#include - -int lf_available_cores() { - return (int)sysconf(_SC_NPROCESSORS_ONLN); -} -#endif From d4d9c652193a9414bb15d382df5920c38102c7bb Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 13:54:17 +0100 Subject: [PATCH 08/95] Zephyr and Windows fixes --- core/platform/lf_windows_support.c | 2 +- core/platform/lf_zephyr_support.c | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/platform/lf_windows_support.c b/core/platform/lf_windows_support.c index 0a9299958..9150634ef 100644 --- a/core/platform/lf_windows_support.c +++ b/core/platform/lf_windows_support.c @@ -204,7 +204,7 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_thread_scheduling_policy_t policy) { +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { return -1; } diff --git a/core/platform/lf_zephyr_support.c b/core/platform/lf_zephyr_support.c index f248cde1e..f0b36a60a 100644 --- a/core/platform/lf_zephyr_support.c +++ b/core/platform/lf_zephyr_support.c @@ -181,11 +181,6 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t * break; } - // Write it back - if (pthread_setschedparam(thread, posix_policy, &schedparam) != 0) { - return -3; - } - return 0; } From bb27a229ab11415e8018dd81f1692e6ae5b01cd0 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 14:09:37 +0100 Subject: [PATCH 09/95] Zephyr fix --- core/platform/lf_zephyr_support.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/platform/lf_zephyr_support.c b/core/platform/lf_zephyr_support.c index f0b36a60a..318dd803d 100644 --- a/core/platform/lf_zephyr_support.c +++ b/core/platform/lf_zephyr_support.c @@ -166,7 +166,7 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t * break; case LF_SCHED_TIMESLICE: { int priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; - interval_t slice = ((lf_scheduling_policy_timeslice_t *) policy)->timeslice; + interval_t slice = ((lf_scheduling_policy_timeslice_t *) policy)->time_slice; k_thread_priority_set(thread, 99 - priority); k_sched_time_slice_set(0, slice/1000000); break; From cc1317d6d4f45664fe7e1fa086a0dc8ce2123b1a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 15:17:21 +0100 Subject: [PATCH 10/95] Move part of the thread scheduling API from POSIX to macOS and Linux --- core/platform/lf_POSIX_threads_support.c | 54 ------------------------ core/platform/lf_linux_support.c | 54 ++++++++++++++++++++++++ core/platform/lf_macos_support.c | 12 ++++++ 3 files changed, 66 insertions(+), 54 deletions(-) diff --git a/core/platform/lf_POSIX_threads_support.c b/core/platform/lf_POSIX_threads_support.c index 0270f135e..7ddc67482 100644 --- a/core/platform/lf_POSIX_threads_support.c +++ b/core/platform/lf_POSIX_threads_support.c @@ -14,41 +14,6 @@ int lf_available_cores() { return (int)sysconf(_SC_NPROCESSORS_ONLN); } -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { - int posix_policy; - struct sched_param schedparam; - - // Get the current scheduling policy - if (pthread_getschedparam(thread, &posix_policy, &schedparam) != 0) { - return -1; - } - - // Update the policy - switch(policy->policy) { - case LF_SCHED_FAIR: - posix_policy = SCHED_OTHER; - break; - case LF_SCHED_TIMESLICE: - posix_policy = SCHED_RR; - schedparam.sched_priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; - break; - case LF_SCHED_PRIORITY: - posix_policy = SCHED_FIFO; - schedparam.sched_priority = ((lf_scheduling_policy_priority_t *) policy)->priority; - break; - default: - return -1; - break; - } - - // Write it back - if (pthread_setschedparam(thread, posix_policy, &schedparam) != 0) { - return -3; - } - - return 0; -} - int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { return pthread_create((pthread_t*)thread, NULL, lf_thread, arguments); } @@ -76,25 +41,6 @@ int lf_mutex_init(lf_mutex_t* mutex) { return pthread_mutex_init((pthread_mutex_t*)mutex, &attr); } -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { - // First verify that we have num_cores>cpu_number - if (lf_available_cores() <= cpu_number) { - return -1; - } - - // Create a CPU-set consisting of only the desired CPU - cpu_set_t cpu_set; - CPU_ZERO(&cpu_set); - CPU_SET(cpu_number, &cpu_set); - - return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); -} - - -int lf_thread_set_priority(lf_thread_t thread, int priority) { - return pthread_setschedprio(thread, priority); -} - lf_thread_t lf_thread_self() { return pthread_self(); } diff --git a/core/platform/lf_linux_support.c b/core/platform/lf_linux_support.c index 6c3b477eb..c41856c14 100644 --- a/core/platform/lf_linux_support.c +++ b/core/platform/lf_linux_support.c @@ -64,4 +64,58 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_ti int lf_nanosleep(interval_t sleep_duration) { return lf_sleep(sleep_duration); } + +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + // First verify that we have num_cores>cpu_number + if (lf_available_cores() <= cpu_number) { + return -1; + } + + // Create a CPU-set consisting of only the desired CPU + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + CPU_SET(cpu_number, &cpu_set); + + return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); +} + +int lf_thread_set_priority(lf_thread_t thread, int priority) { + return pthread_setschedprio(thread, priority); +} + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { + int posix_policy; + struct sched_param schedparam; + + // Get the current scheduling policy + if (pthread_getschedparam(thread, &posix_policy, &schedparam) != 0) { + return -1; + } + + // Update the policy + switch(policy->policy) { + case LF_SCHED_FAIR: + posix_policy = SCHED_OTHER; + break; + case LF_SCHED_TIMESLICE: + posix_policy = SCHED_RR; + schedparam.sched_priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; + break; + case LF_SCHED_PRIORITY: + posix_policy = SCHED_FIFO; + schedparam.sched_priority = ((lf_scheduling_policy_priority_t *) policy)->priority; + break; + default: + return -1; + break; + } + + // Write it back + if (pthread_setschedparam(thread, posix_policy, &schedparam) != 0) { + return -3; + } + + return 0; +} + #endif diff --git a/core/platform/lf_macos_support.c b/core/platform/lf_macos_support.c index d9991c6d4..248280d6f 100644 --- a/core/platform/lf_macos_support.c +++ b/core/platform/lf_macos_support.c @@ -63,4 +63,16 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_ti int lf_nanosleep(interval_t sleep_duration) { return lf_sleep(sleep_duration); } + +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + return -1; +} + +int lf_thread_set_priority(lf_thread_t thread, int priority) { + return -1; +} + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { + return -1; +} #endif From 365f39ecf6a0b7f5a0768b67ed2d27bb28bba6b9 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 15:21:49 +0100 Subject: [PATCH 11/95] #ifdef LF_SINGLE_THREADED --- core/platform/lf_linux_support.c | 50 +++++++++++++++----------------- core/platform/lf_macos_support.c | 28 +++++++++--------- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/core/platform/lf_linux_support.c b/core/platform/lf_linux_support.c index c41856c14..f5b73519e 100644 --- a/core/platform/lf_linux_support.c +++ b/core/platform/lf_linux_support.c @@ -38,33 +38,9 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "tag.h" #if defined LF_SINGLE_THREADED - #include "lf_os_single_threaded_support.c" +#include "lf_os_single_threaded_support.c" #else - #include "lf_POSIX_threads_support.c" -#endif - -#include "lf_unix_clock_support.h" - -int lf_sleep(interval_t sleep_duration) { - const struct timespec tp = convert_ns_to_timespec(sleep_duration); - struct timespec remaining; - return nanosleep((const struct timespec*)&tp, (struct timespec*)&remaining); -} - -int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { - interval_t sleep_duration = wakeup_time - lf_time_physical(); - - if (sleep_duration <= 0) { - return 0; - } else { - return lf_sleep(sleep_duration); - } -} - -int lf_nanosleep(interval_t sleep_duration) { - return lf_sleep(sleep_duration); -} - +#include "lf_POSIX_threads_support.c" int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { // First verify that we have num_cores>cpu_number if (lf_available_cores() <= cpu_number) { @@ -117,5 +93,27 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t * return 0; } +#endif + +#include "lf_unix_clock_support.h" + +int lf_sleep(interval_t sleep_duration) { + const struct timespec tp = convert_ns_to_timespec(sleep_duration); + struct timespec remaining; + return nanosleep((const struct timespec*)&tp, (struct timespec*)&remaining); +} +int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { + interval_t sleep_duration = wakeup_time - lf_time_physical(); + + if (sleep_duration <= 0) { + return 0; + } else { + return lf_sleep(sleep_duration); + } +} + +int lf_nanosleep(interval_t sleep_duration) { + return lf_sleep(sleep_duration); +} #endif diff --git a/core/platform/lf_macos_support.c b/core/platform/lf_macos_support.c index 248280d6f..ad8542bb2 100644 --- a/core/platform/lf_macos_support.c +++ b/core/platform/lf_macos_support.c @@ -36,9 +36,21 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "tag.h" #if defined LF_SINGLE_THREADED - #include "lf_os_single_threaded_support.c" +#include "lf_os_single_threaded_support.c" #else - #include "lf_POSIX_threads_support.c" +#include "lf_POSIX_threads_support.c" + +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { + return -1; +} + +int lf_thread_set_priority(lf_thread_t thread, int priority) { + return -1; +} + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { + return -1; +} #endif #include "lf_unix_clock_support.h" @@ -63,16 +75,4 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_ti int lf_nanosleep(interval_t sleep_duration) { return lf_sleep(sleep_duration); } - -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { - return -1; -} - -int lf_thread_set_priority(lf_thread_t thread, int priority) { - return -1; -} - -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { - return -1; -} #endif From 3ea078f690ee651dce69f0663b1b4b76ef433482 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 16:43:05 +0100 Subject: [PATCH 12/95] Define max and min thread priority as macros --- core/platform/lf_zephyr_support.c | 4 ++-- include/core/platform.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/platform/lf_zephyr_support.c b/core/platform/lf_zephyr_support.c index 318dd803d..bd091cb21 100644 --- a/core/platform/lf_zephyr_support.c +++ b/core/platform/lf_zephyr_support.c @@ -155,7 +155,7 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { } int lf_thread_set_priority(lf_thread_t thread, int priority) { - k_thread_priority_set(thread, 99 - priority); + k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - priority); return 0; } @@ -167,7 +167,7 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t * case LF_SCHED_TIMESLICE: { int priority = ((lf_scheduling_policy_timeslice_t *) policy)->priority; interval_t slice = ((lf_scheduling_policy_timeslice_t *) policy)->time_slice; - k_thread_priority_set(thread, 99 - priority); + k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - priority); k_sched_time_slice_set(0, slice/1000000); break; } diff --git a/include/core/platform.h b/include/core/platform.h index 87cbc7534..b6c48dca0 100644 --- a/include/core/platform.h +++ b/include/core/platform.h @@ -160,6 +160,8 @@ int lf_thread_join(lf_thread_t thread, void** thread_return); // by the underlying thread scheduling. This API is still experimental and future // changes are expected. +#define LF_SCHED_MAX_PRIORITY 99 +#define LF_SCHED_MIN_PRIORITY 0 /** * @brief The thread scheduling policies. * From 1ce310f1cb457054663df76fbb7b0cd745c9d967 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 13 Feb 2024 18:24:18 +0100 Subject: [PATCH 13/95] Update lf-ref --- lingua-franca-ref.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lingua-franca-ref.txt b/lingua-franca-ref.txt index 2e722a57e..8b25206ff 100644 --- a/lingua-franca-ref.txt +++ b/lingua-franca-ref.txt @@ -1 +1 @@ -cleanup-pass +master \ No newline at end of file From 9f5cc39d8694eafeda397c824963078c6867d5f6 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 15:35:32 +0100 Subject: [PATCH 14/95] CMake cleanup: - Move linking with threading library to low-level platform with PRIVATE - Remove the wierd REACTORC_COMPILE_DEFS variable - Dont add source files when they are not to be compiled - Add custom function for enabling warnings and -Werror --- CMakeLists.txt | 2 +- core/CMakeLists.txt | 42 +++++---------- core/utils/CMakeLists.txt | 5 +- lf_utils.cmake | 7 +++ lib/CMakeLists.txt | 5 ++ low_level_platform/impl/CMakeLists.txt | 73 +++++++++++++++++++------- low_level_platform/impl/Platform.cmake | 18 ------- trace/impl/CMakeLists.txt | 4 ++ 8 files changed, 90 insertions(+), 66 deletions(-) create mode 100644 lf_utils.cmake delete mode 100644 low_level_platform/impl/Platform.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a916023f..2edacb188 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ if(DEFINED LF_SINGLE_THREADED) endif() # Warnings as errors -add_compile_options(-Werror) +add_compile_options(-Wall -Wpedantic -Werror) set(Test test) set(Lib lib) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 8eec31eb8..229d2fba2 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,17 +1,7 @@ set(CORE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) -if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - set(CMAKE_SYSTEM_VERSION 10.0) - message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Nrf52") - list(APPEND REACTORC_COMPILE_DEFS PLATFORM_NRF52) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - list(APPEND REACTORC_COMPILE_DEFS PLATFORM_ZEPHYR) - set(PLATFORM_ZEPHYR true) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040") - list(APPEND REACTORC_COMPILE_DEFS PLATFORM_RP2040) -endif() +include(${LF_ROOT}/lf_utils.cmake) # Get the general common sources for reactor-c list(APPEND GENERAL_SOURCES tag.c clock.c port.c mixed_radix.c reactor_common.c lf_token.c environment.c) @@ -50,7 +40,10 @@ endif() # Include sources from subdirectories include(utils/CMakeLists.txt) + +if (DEFINED MODAL_REACTORS) include(modal_models/CMakeLists.txt) +endif() # Print sources used for compilation list(JOIN REACTORC_SOURCES ", " PRINTABLE_SOURCE_LIST) @@ -58,7 +51,7 @@ message(STATUS "Including the following sources: " ${PRINTABLE_SOURCE_LIST}) # Create the reactor-c library. If we are targeting Zephyr we have to use the # Zephyr Cmake extension to create the library and add the sources. -if(PLATFORM_ZEPHYR) +if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") message("--- Building Zephyr library") zephyr_library_named(reactor-c) zephyr_library_sources(${REACTORC_SOURCES}) @@ -68,6 +61,8 @@ else() target_sources(reactor-c PRIVATE ${REACTORC_SOURCES}) endif() +lf_enable_compiler_warnings(reactor-c) + if (DEFINED LF_TRACE) include(${LF_ROOT}/trace/api/CMakeLists.txt) if(NOT LF_TRACE_PLUGIN) @@ -98,9 +93,6 @@ include(${LF_ROOT}/platform/impl/CMakeLists.txt) target_link_libraries(reactor-c PUBLIC lf::platform-api) target_link_libraries(reactor-c PRIVATE lf::platform-impl) -# Apply compile definitions to the reactor-c library. -target_compile_definitions(reactor-c PUBLIC ${REACTORC_COMPILE_DEFS}) - target_include_directories(reactor-c PUBLIC ../include) target_include_directories(reactor-c PUBLIC ../include/core) target_include_directories(reactor-c PUBLIC ../include/core/federated) @@ -134,13 +126,13 @@ if(DEFINED _LF_CLOCK_SYNC_ON) endif() endif() -# Link with thread library, unless we are on the Zephyr platform. -if(NOT DEFINED LF_SINGLE_THREADED OR DEFINED LF_TRACE) - if (NOT PLATFORM_ZEPHYR) - find_package(Threads REQUIRED) - target_link_libraries(reactor-c PUBLIC Threads::Threads) - endif() -endif() + +# FIXME: May want these to be application dependent, hence passed as +# parameters to Cmake. +target_compile_definitions(reactor-c PRIVATE INITIAL_EVENT_QUEUE_SIZE=10) +target_compile_definitions(reactor-c PRIVATE INITIAL_REACT_QUEUE_SIZE=10) +target_compile_definitions(reactor-c PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) + # Macro for translating a command-line argument into compile definition for # reactor-c lib @@ -151,12 +143,6 @@ macro(define X) endif(DEFINED ${X}) endmacro() -# FIXME: May want these to be application dependent, hence passed as -# parameters to Cmake. -target_compile_definitions(reactor-c PRIVATE INITIAL_EVENT_QUEUE_SIZE=10) -target_compile_definitions(reactor-c PRIVATE INITIAL_REACT_QUEUE_SIZE=10) -target_compile_definitions(reactor-c PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) - # Search and apply all possible compile definitions message(STATUS "Applying preprocessor definitions...") define(_LF_CLOCK_SYNC_ATTENUATION) diff --git a/core/utils/CMakeLists.txt b/core/utils/CMakeLists.txt index 7ab0db8d4..723b942c8 100644 --- a/core/utils/CMakeLists.txt +++ b/core/utils/CMakeLists.txt @@ -1,5 +1,8 @@ -set(UTIL_SOURCES vector.c pqueue_base.c pqueue_tag.c pqueue.c util.c lf_semaphore.c) +set(UTIL_SOURCES vector.c pqueue_base.c pqueue_tag.c pqueue.c util.c) +if(NOT DEFINED LF_SINGLE_THREADED) + list(APPEND UTIL_SOURCES lf_semaphore.c) +endif() list(TRANSFORM UTIL_SOURCES PREPEND utils/) list(APPEND REACTORC_SOURCES ${UTIL_SOURCES}) diff --git a/lf_utils.cmake b/lf_utils.cmake new file mode 100644 index 000000000..de6d4c5df --- /dev/null +++ b/lf_utils.cmake @@ -0,0 +1,7 @@ +function(lf_enable_compiler_warnings target) + if(MSVC) + target_compile_options(${target} PRIVATE /W4 /WX) + else() + target_compile_options(${target} PRIVATE -Wall -Wextra -pedantic -Werror) + endif() +endfunction() \ No newline at end of file diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f0b2c18bc..20b158505 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,3 +1,8 @@ +set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) +include(${LF_ROOT}/lf_utils.cmake) + add_library(lib schedule.c) target_link_libraries(lib PRIVATE lf::low-level-platform-api) target_link_libraries(lib PRIVATE lf::logging-api) + +lf_enable_compiler_warnings(lib) \ No newline at end of file diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 7641dd663..d14ecb830 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -1,32 +1,69 @@ # Check which system we are running on to select the correct platform support # file and assign the file's path to LF_PLATFORM_FILE set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..) -set(LF_LOW_LEVEL_PLATFORM_FILES - ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_clock_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_syscall_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_linux_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_macos_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_windows_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_nrf52_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_clock_counter.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_clock_kernel.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_rp2040_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_windows.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_gcc_clang.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_irq.c - ${CMAKE_CURRENT_LIST_DIR}/src/platform_internal.c -) -if(PLATFORM_ZEPHYR) +include(${LF_ROOT}/lf_utils.cmake) + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + set(CMAKE_SYSTEM_VERSION 10.0) + message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_windows_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_windows.c + ) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_clock_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_syscall_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_linux_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_gcc_clang.c + ) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_clock_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_syscall_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_macos_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_gcc_clang.c + ) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Nrf52") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_nrf52_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_irq.c + ) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_clock_counter.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_zephyr_clock_kernel.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_irq.c + ) +elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040") + set(LF_LOW_LEVEL_PLATFORM_FILES + ${CMAKE_CURRENT_LIST_DIR}/src/lf_rp2040_support.c + ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_irq.c + ) +else() + message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS, Windows, Zephyr, Nrf52 and RP2040.") +endif() + +list(APPEND LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/platform_internal.c) + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") message("--- Building Zephyr library") zephyr_library_named(lf-low-level-platform-impl) zephyr_library_sources(${LF_LOW_LEVEL_PLATFORM_FILES}) zephyr_library_link_libraries(kernel) else() -message("--- Building non-Zephyr library") + message("--- Building non-Zephyr library") add_library(lf-low-level-platform-impl STATIC ${LF_LOW_LEVEL_PLATFORM_FILES}) + # Link the platform to a threading library + if(NOT DEFINED LF_SINGLE_THREADED OR DEFINED LF_TRACE) + find_package(Threads REQUIRED) + target_link_libraries(lf-low-level-platform-impl PRIVATE Threads::Threads) + endif() endif() + add_library(lf::low-level-platform-impl ALIAS lf-low-level-platform-impl) +lf_enable_compiler_warnings(lf-low-level-platform-impl) target_link_libraries(lf-low-level-platform-impl PRIVATE lf::low-level-platform-api) target_link_libraries(lf-low-level-platform-impl PUBLIC lf-logging-api) diff --git a/low_level_platform/impl/Platform.cmake b/low_level_platform/impl/Platform.cmake deleted file mode 100644 index cc6042c7c..000000000 --- a/low_level_platform/impl/Platform.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Check which system we are running on to select the correct platform support -# file and assign the file's path to LF_PLATFORM_FILE -if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - set(LF_PLATFORM_FILE lf_linux_support.c) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - set(LF_PLATFORM_FILE lf_macos_support.c) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") - set(LF_PLATFORM_FILE lf_windows_support.c) - set(CMAKE_SYSTEM_VERSION 10.0) - message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}") -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - set(LF_PLATFORM_FILE lf_zephyr_support.c) -elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Rp2040") - message("Using pico-sdk for RP2040 target") - set(LF_PLATFORM_FILE lf_rp2040_support.c) -else() - message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS and Windows.") -endif() diff --git a/trace/impl/CMakeLists.txt b/trace/impl/CMakeLists.txt index 6aeeb6870..99f11c517 100644 --- a/trace/impl/CMakeLists.txt +++ b/trace/impl/CMakeLists.txt @@ -1,9 +1,13 @@ +set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..) +include(${LF_ROOT}/lf_utils.cmake) + add_library(lf-trace-impl STATIC) add_library(lf::trace-impl ALIAS lf-trace-impl) target_link_libraries(lf-trace-impl PRIVATE lf::trace-api) target_link_libraries(lf-trace-impl PRIVATE lf::platform-api) target_link_libraries(lf-trace-impl PRIVATE lf::logging-api) target_link_libraries(lf-trace-impl PRIVATE lf::version-api) +lf_enable_compiler_warnings(lf-trace-impl) target_sources(lf-trace-impl PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/trace_impl.c) From fc26972bfadd7f4316df4914529c1c86579199cd Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 15:38:39 +0100 Subject: [PATCH 15/95] Address warnings in the code-base: - printf %p must be casted to void* - comparison between signed and unsigned - unused function arguments - remove the empty trace macros - Add wrapper thread function for C11 --- .gitignore | 1 - core/environment.c | 22 ++- core/federated/RTI/rti_remote.c | 5 - core/federated/clock-sync.c | 13 +- core/federated/federate.c | 41 +++--- core/federated/network/net_util.c | 11 +- core/lf_token.c | 28 ++-- core/reactor.c | 31 +++- core/reactor_common.c | 18 +-- core/tag.c | 2 +- core/threaded/reactor_threaded.c | 14 +- core/threaded/scheduler_NP.c | 15 +- core/threaded/watchdog.c | 3 +- core/utils/pqueue.c | 10 +- core/utils/pqueue_support.h | 4 +- core/utils/pqueue_tag.c | 2 +- core/utils/util.c | 22 ++- include/core/federated/network/net_common.h | 2 - include/core/federated/network/net_util.h | 4 +- include/core/lf_token.h | 2 +- include/core/threaded/reactor_threaded.h | 2 +- include/core/tracepoint.h | 132 ++++++++++++++---- include/core/utils/impl/hashmap.h | 1 - lib/schedule.c | 12 +- low_level_platform/api/low_level_platform.h | 2 +- .../api/platform/lf_nrf52_support.h | 2 +- .../impl/src/lf_C11_threads_support.c | 18 ++- .../impl/src/lf_linux_support.c | 1 + platform/impl/platform.c | 3 +- test/general/utils/hashmap_test.c | 1 - 30 files changed, 271 insertions(+), 153 deletions(-) diff --git a/.gitignore b/.gitignore index 742de2ac4..b8237101d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ /docs/api **/.vscode/ **/build/ -**/lib/ **/.DS_Store /core/federated/RTI/build/ /cmake-build-debug/ diff --git a/core/environment.c b/core/environment.c index 7189090e4..40f369c62 100644 --- a/core/environment.c +++ b/core/environment.c @@ -53,7 +53,9 @@ static void environment_init_threaded(environment_t* env, int num_workers) { LF_MUTEX_INIT(&env->mutex); LF_COND_INIT(&env->event_q_changed, &env->mutex); LF_COND_INIT(&env->global_tag_barrier_requestors_reached_zero, &env->mutex); - +#else + (void)env; + (void)num_workers; #endif } /** @@ -67,6 +69,8 @@ static void environment_init_single_threaded(environment_t* env) { env->reaction_q = pqueue_init(INITIAL_REACT_QUEUE_SIZE, in_reverse_order, get_reaction_index, get_reaction_position, set_reaction_position, reaction_matches, print_reaction); +#else + (void)env; #endif } @@ -97,6 +101,10 @@ static void environment_init_modes(environment_t* env, int num_modes, int num_st } else { env->modes = NULL; } +#else + (void)env; + (void)num_modes; + (void)num_state_resets; #endif } @@ -113,6 +121,9 @@ static void environment_init_federated(environment_t* env, int num_is_present_fi env->_lf_intended_tag_fields = NULL; env->_lf_intended_tag_fields_size = 0; } +#else + (void)env; + (void)num_is_present_fields; #endif } @@ -132,12 +143,16 @@ static void environment_free_threaded(environment_t* env) { #if !defined(LF_SINGLE_THREADED) free(env->thread_ids); lf_sched_free(env->scheduler); +#else + (void)env; #endif } static void environment_free_single_threaded(environment_t* env) { #ifdef LF_SINGLE_THREADED pqueue_free(env->reaction_q); +#else + (void)env; #endif } @@ -148,12 +163,16 @@ static void environment_free_modes(environment_t* env) { free(env->modes->state_resets); free(env->modes); } +#else + (void)env; #endif } static void environment_free_federated(environment_t* env) { #ifdef FEDERATED_DECENTRALIZED free(env->_lf_intended_tag_fields); +#else + (void)env; #endif } @@ -179,6 +198,7 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke int num_startup_reactions, int num_shutdown_reactions, int num_reset_reactions, int num_is_present_fields, int num_modes, int num_state_resets, int num_watchdogs, const char* trace_file_name) { + (void)trace_file_name; // Will be used with future enclave support. env->name = malloc(strlen(name) + 1); // +1 for the null terminator LF_ASSERT_NON_NULL(env->name); diff --git a/core/federated/RTI/rti_remote.c b/core/federated/RTI/rti_remote.c index 2bc2dc8cf..ebd96550d 100644 --- a/core/federated/RTI/rti_remote.c +++ b/core/federated/RTI/rti_remote.c @@ -891,11 +891,6 @@ void* clock_synchronization_thread(void* noargs) { } // Initiate a clock synchronization every rti->clock_sync_period_ns - // Initiate a clock synchronization every rti->clock_sync_period_ns - struct timespec sleep_time = {(time_t)rti_remote->clock_sync_period_ns / BILLION, - rti_remote->clock_sync_period_ns % BILLION}; - struct timespec remaining_time; - bool any_federates_connected = true; while (any_federates_connected) { // Sleep diff --git a/core/federated/clock-sync.c b/core/federated/clock-sync.c index ddd845d6f..577d1104a 100644 --- a/core/federated/clock-sync.c +++ b/core/federated/clock-sync.c @@ -438,6 +438,7 @@ void handle_T4_clock_sync_message(unsigned char* buffer, int socket, instant_t r * Thread that listens for UDP inputs from the RTI. */ void* listen_to_rti_UDP_thread(void* args) { + (void)args; initialize_lf_thread_id(); // Listen for UDP messages from the RTI. // The only expected messages are T1 and T4, which have @@ -468,12 +469,12 @@ void* listen_to_rti_UDP_thread(void* args) { if (bytes > 0) { bytes_read += bytes; } - } while ((errno == EAGAIN || errno == EWOULDBLOCK) && bytes_read < message_size); + } while ((errno == EAGAIN || errno == EWOULDBLOCK) && bytes_read < (ssize_t)message_size); // Get local physical time before doing anything else. instant_t receive_time = lf_time_physical(); - if (bytes_read < message_size) { + if (bytes_read < (ssize_t)message_size) { // Either the socket has closed or the RTI has sent EOF. // Exit the thread to halt clock synchronization. lf_print_error("Clock sync: UDP socket to RTI is broken: %s. Clock sync is now disabled.", strerror(errno)); @@ -533,9 +534,9 @@ void clock_sync_remove_offset(instant_t* t) { *t -= (_lf_clock_sync_offset + _lf void clock_sync_set_constant_bias(interval_t offset) { _lf_clock_sync_constant_bias = offset; } #else -void clock_sync_apply_offset(instant_t* t) {} -void clock_sync_remove_offset(instant_t* t) {} -void clock_sync_set_constant_bias(interval_t offset) {} +void clock_sync_apply_offset(instant_t* t) { (void)t; } +void clock_sync_remove_offset(instant_t* t) { (void)t; } +void clock_sync_set_constant_bias(interval_t offset) { (void)offset; } #endif /** @@ -550,6 +551,8 @@ int create_clock_sync_thread(lf_thread_t* thread_id) { #ifdef _LF_CLOCK_SYNC_ON // One for UDP messages if clock synchronization is enabled for this federate return lf_thread_create(thread_id, listen_to_rti_UDP_thread, NULL); +#else + (void)thread_id; #endif // _LF_CLOCK_SYNC_ON return 0; } diff --git a/core/federated/federate.c b/core/federated/federate.c index edc8c5338..eab22304c 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -88,8 +88,8 @@ federate_instance_t _fed = {.socket_TCP_RTI = -1, .has_upstream = false, .has_downstream = false, .received_stop_request_from_rti = false, - .last_sent_LTC = (tag_t){.time = NEVER, .microstep = 0u}, - .last_sent_NET = (tag_t){.time = NEVER, .microstep = 0u}, + .last_sent_LTC.time = NEVER, + .last_sent_NET.time = NEVER, .min_delay_from_physical_action_to_federate_output = NEVER}; federation_metadata_t federation_metadata = { @@ -184,7 +184,7 @@ extern size_t staa_lst_size; * @return A pointer to an action struct or null if the ID is out of range. */ static lf_action_base_t* action_for_port(int port_id) { - if (port_id >= 0 && port_id < _lf_action_table_size) { + if (port_id >= 0 && ((size_t)port_id) < _lf_action_table_size) { return _lf_action_table[port_id]; } lf_print_error_and_exit("Invalid port ID: %d", port_id); @@ -206,7 +206,7 @@ static lf_action_base_t* action_for_port(int port_id) { static void update_last_known_status_on_input_ports(tag_t tag) { LF_PRINT_DEBUG("In update_last_known_status_on_input ports."); bool notify = false; - for (int i = 0; i < _lf_action_table_size; i++) { + for (size_t i = 0; i < _lf_action_table_size; i++) { lf_action_base_t* input_port_action = _lf_action_table[i]; // This is called when a TAG is received. // But it is possible for an input port to have received already @@ -215,7 +215,7 @@ static void update_last_known_status_on_input_ports(tag_t tag) { // is in the future and should not be rolled back. So in that case, // we do not update the last known status tag. if (lf_tag_compare(tag, input_port_action->trigger->last_known_status_tag) >= 0) { - LF_PRINT_DEBUG("Updating the last known status tag of port %d from " PRINTF_TAG " to " PRINTF_TAG ".", i, + LF_PRINT_DEBUG("Updating the last known status tag of port %zu from " PRINTF_TAG " to " PRINTF_TAG ".", i, input_port_action->trigger->last_known_status_tag.time - lf_time_start(), input_port_action->trigger->last_known_status_tag.microstep, tag.time - lf_time_start(), tag.microstep); @@ -436,7 +436,7 @@ static void close_inbound_socket(int fed_id, int flag) { * @param intended_tag The intended tag. */ static bool handle_message_now(environment_t* env, trigger_t* trigger, tag_t intended_tag) { - return trigger->reactions[0]->index >= max_level_allowed_to_advance && + return trigger->reactions[0]->index >= ((index_t)max_level_allowed_to_advance) && lf_tag_compare(intended_tag, lf_tag(env)) == 0 && lf_tag_compare(intended_tag, trigger->last_tag) > 0 && lf_tag_compare(intended_tag, trigger->last_known_status_tag) > 0 && env->execution_started && !trigger->is_physical; @@ -451,6 +451,7 @@ static bool handle_message_now(environment_t* env, trigger_t* trigger, tag_t int * @return 0 for success, -1 for failure. */ static int handle_message(int* socket, int fed_id) { + (void)fed_id; // Read the header. size_t bytes_to_read = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(int32_t); unsigned char buffer[bytes_to_read]; @@ -1054,20 +1055,21 @@ static bool a_port_is_unknown(staa_t* staa_elem) { } return do_wait; } -#endif /** * @brief Return the port ID of the port associated with the given action. * @return The port ID or -1 if there is no match. */ static int id_of_action(lf_action_base_t* input_port_action) { - for (int i = 0; i < _lf_action_table_size; i++) { + for (size_t i = 0; i < _lf_action_table_size; i++) { if (_lf_action_table[i] == input_port_action) return i; } return -1; } +#endif + /** * @brief Thread handling setting the known absent status of input ports. * For the code-generated array of staa offsets `staa_lst`, which is sorted by STAA offset, @@ -1111,7 +1113,7 @@ static void* update_ports_from_staa_offsets(void* args) { } while (a_port_is_unknown(staa_elem)) { LF_PRINT_DEBUG("**** (update thread) waiting until: " PRINTF_TIME, wait_until_time - lf_time_start()); - if (wait_until(env, wait_until_time, &lf_port_status_changed)) { + if (wait_until(wait_until_time, &lf_port_status_changed)) { if (lf_tag_compare(lf_tag(env), tag_when_started_waiting) != 0) { break; } @@ -1439,7 +1441,7 @@ static void handle_stop_request_message() { /** * Send a resign signal to the RTI. */ -static void send_resign_signal(environment_t* env) { +static void send_resign_signal() { size_t bytes_to_write = 1; unsigned char buffer[bytes_to_write]; buffer[0] = MSG_TYPE_RESIGN; @@ -1453,7 +1455,7 @@ static void send_resign_signal(environment_t* env) { /** * Send a failed signal to the RTI. */ -static void send_failed_signal(environment_t* env) { +static void send_failed_signal() { size_t bytes_to_write = 1; unsigned char buffer[bytes_to_write]; buffer[0] = MSG_TYPE_FAILED; @@ -1476,6 +1478,7 @@ static void handle_rti_failed_message(void) { exit(1); } * @param args Ignored */ static void* listen_to_rti_TCP(void* args) { + (void)args; initialize_lf_thread_id(); // Buffer for incoming messages. // This does not constrain the message size @@ -1623,10 +1626,10 @@ void lf_terminate_execution(environment_t* env) { if (_fed.socket_TCP_RTI >= 0) { if (_lf_normal_termination) { tracepoint_federate_to_rti(send_RESIGN, _lf_my_fed_id, &env->current_tag); - send_resign_signal(env); + send_resign_signal(); } else { tracepoint_federate_to_rti(send_FAILED, _lf_my_fed_id, &env->current_tag); - send_failed_signal(env); + send_failed_signal(); } } @@ -1656,7 +1659,7 @@ void lf_terminate_execution(environment_t* env) { if (_fed.number_of_inbound_p2p_connections > 0 && _fed.inbound_socket_listeners != NULL) { LF_PRINT_LOG("Waiting for %zu threads listening for incoming messages to exit.", _fed.number_of_inbound_p2p_connections); - for (int i = 0; i < _fed.number_of_inbound_p2p_connections; i++) { + for (size_t i = 0; i < _fed.number_of_inbound_p2p_connections; i++) { // Ignoring errors here. lf_thread_join(_fed.inbound_socket_listeners[i], NULL); } @@ -2082,7 +2085,7 @@ void lf_enqueue_port_absent_reactions(environment_t* env) { LF_PRINT_DEBUG("No port absent reactions."); return; } - for (int i = 0; i < num_port_absent_reactions; i++) { + for (size_t i = 0; i < num_port_absent_reactions; i++) { reaction_t* reaction = port_absent_reaction[i]; if (reaction && reaction->status == inactive) { LF_PRINT_DEBUG("Inserting port absent reaction on reaction queue."); @@ -2093,8 +2096,7 @@ void lf_enqueue_port_absent_reactions(environment_t* env) { void* lf_handle_p2p_connections_from_federates(void* env_arg) { assert(env_arg); - environment_t* env = (environment_t*)env_arg; - int received_federates = 0; + size_t received_federates = 0; // Allocate memory to store thread IDs. _fed.inbound_socket_listeners = (lf_thread_t*)calloc(_fed.number_of_inbound_p2p_connections, sizeof(lf_thread_t)); while (received_federates < _fed.number_of_inbound_p2p_connections && !_lf_termination_executed) { @@ -2217,7 +2219,6 @@ void lf_latest_tag_complete(tag_t tag_to_send) { } parse_rti_code_t lf_parse_rti_addr(const char* rti_addr) { - bool has_host = false, has_port = false, has_user = false; rti_addr_info_t rti_addr_info = {0}; extract_rti_addr_info(rti_addr, &rti_addr_info); if (!rti_addr_info.has_host && !rti_addr_info.has_port && !rti_addr_info.has_user) { @@ -2255,7 +2256,7 @@ void lf_reset_status_fields_on_input_port_triggers() { environment_t* env; _lf_get_environments(&env); tag_t now = lf_tag(env); - for (int i = 0; i < _lf_action_table_size; i++) { + for (size_t i = 0; i < _lf_action_table_size; i++) { if (lf_tag_compare(_lf_action_table[i]->trigger->last_known_status_tag, now) >= 0) { set_network_port_status(i, absent); // Default may be overriden to become present. } else { @@ -2670,7 +2671,7 @@ bool lf_update_max_level(tag_t tag, bool is_provisional) { size_t action_table_size = _lf_zero_delay_cycle_action_table_size; lf_action_base_t** action_table = _lf_zero_delay_cycle_action_table; #endif // FEDERATED_DECENTRALIZED - for (int i = 0; i < action_table_size; i++) { + for (size_t i = 0; i < action_table_size; i++) { lf_action_base_t* input_port_action = action_table[i]; #ifdef FEDERATED_DECENTRALIZED // In decentralized execution, if the current_tag is close enough to the diff --git a/core/federated/network/net_util.c b/core/federated/network/net_util.c index b591947d7..42d3bcabd 100644 --- a/core/federated/network/net_util.c +++ b/core/federated/network/net_util.c @@ -165,7 +165,6 @@ int write_to_socket(int socket, size_t num_bytes, unsigned char* buffer) { return -1; } ssize_t bytes_written = 0; - va_list args; while (bytes_written < (ssize_t)num_bytes) { ssize_t more = write(socket, buffer + bytes_written, num_bytes - (size_t)bytes_written); if (more <= 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) { @@ -492,7 +491,7 @@ bool validate_user(const char* user) { return match_regex(user, username_regex); } -bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int max_len, int min_len, +bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, size_t max_len, size_t min_len, const char* err_msg) { size_t size = group.rm_eo - group.rm_so; if (size > max_len || size < min_len) { @@ -505,7 +504,7 @@ bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int } bool extract_match_groups(const char* rti_addr, char** rti_addr_strs, bool** rti_addr_flags, regmatch_t* group_array, - int* gids, int* max_lens, int* min_lens, const char** err_msgs) { + int* gids, size_t* max_lens, size_t* min_lens, const char** err_msgs) { for (int i = 0; i < 3; i++) { if (group_array[gids[i]].rm_so != -1) { if (!extract_match_group(rti_addr, rti_addr_strs[i], group_array[gids[i]], max_lens[i], min_lens[i], @@ -527,8 +526,8 @@ void extract_rti_addr_info(const char* rti_addr, rti_addr_info_t* rti_addr_info) int gids[3] = {user_gid, host_gid, port_gid}; char* rti_addr_strs[3] = {rti_addr_info->rti_user_str, rti_addr_info->rti_host_str, rti_addr_info->rti_port_str}; bool* rti_addr_flags[3] = {&rti_addr_info->has_user, &rti_addr_info->has_host, &rti_addr_info->has_port}; - int max_lens[3] = {255, 255, 5}; - int min_lens[3] = {1, 1, 1}; + size_t max_lens[3] = {255, 255, 5}; + size_t min_lens[3] = {1, 1, 1}; const char* err_msgs[3] = {"User name must be between 1 to 255 characters long.", "Host must be between 1 to 255 characters long.", "Port must be between 1 to 5 characters long."}; @@ -543,7 +542,7 @@ void extract_rti_addr_info(const char* rti_addr, rti_addr_info_t* rti_addr_info) if (regexec(®ex_compiled, rti_addr, max_groups, group_array, 0) == 0) { // Check for matched username. group_array[0] is the entire matched string. - for (int i = 1; i < max_groups; i++) { + for (size_t i = 1; i < max_groups; i++) { // Annoyingly, the rm_so and rm_eo fields are long long on some platforms and int on others. // To suppress warnings, cast to long long LF_PRINT_DEBUG("runtime rti_addr regex: so: %lld eo: %lld\n", (long long)group_array[i].rm_so, diff --git a/core/lf_token.c b/core/lf_token.c index 4e13b9e6a..48913f85b 100644 --- a/core/lf_token.c +++ b/core/lf_token.c @@ -76,7 +76,7 @@ static lf_token_t* _lf_writable_copy_locked(lf_port_base_t* port) { lf_token_t* token = port->tmplt.token; if (token == NULL) return NULL; - LF_PRINT_DEBUG("lf_writable_copy: Requesting writable copy of token %p with reference count %zu.", token, + LF_PRINT_DEBUG("lf_writable_copy: Requesting writable copy of token %p with reference count %zu.", (void*)token, token->ref_count); if (port->num_destinations == 1 && token->ref_count == 1) { LF_PRINT_DEBUG("lf_writable_copy: Avoided copy because there " @@ -170,13 +170,13 @@ token_freed _lf_free_token(lf_token_t* token) { } if (hashset_num_items(_lf_token_recycling_bin) < _LF_TOKEN_RECYCLING_BIN_SIZE_LIMIT) { // Recycle instead of freeing. - LF_PRINT_DEBUG("_lf_free_token: Putting token on the recycling bin: %p", token); + LF_PRINT_DEBUG("_lf_free_token: Putting token on the recycling bin: %p", (void*)token); if (!hashset_add(_lf_token_recycling_bin, token)) { - lf_print_warning("Putting token %p on the recycling bin, but it is already there!", token); + lf_print_warning("Putting token %p on the recycling bin, but it is already there!", (void*)token); } } else { // Recycling bin is full. - LF_PRINT_DEBUG("_lf_free_token: Freeing allocated memory for token: %p", token); + LF_PRINT_DEBUG("_lf_free_token: Freeing allocated memory for token: %p", (void*)token); free(token); } #if !defined NDEBUG @@ -197,7 +197,7 @@ lf_token_t* _lf_new_token(token_type_t* type, void* value, size_t length) { if (hashset_iterator_next(iterator) >= 0) { result = hashset_iterator_value(iterator); hashset_remove(_lf_token_recycling_bin, result); - LF_PRINT_DEBUG("_lf_new_token: Retrieved token from the recycling bin: %p", result); + LF_PRINT_DEBUG("_lf_new_token: Retrieved token from the recycling bin: %p", (void*)result); } free(iterator); } @@ -212,7 +212,7 @@ lf_token_t* _lf_new_token(token_type_t* type, void* value, size_t length) { if (result == NULL) { // Nothing found on the recycle bin. result = (lf_token_t*)calloc(1, sizeof(lf_token_t)); - LF_PRINT_DEBUG("_lf_new_token: Allocated memory for token: %p", result); + LF_PRINT_DEBUG("_lf_new_token: Allocated memory for token: %p", (void*)result); } result->type = type; result->length = length; @@ -224,7 +224,7 @@ lf_token_t* _lf_new_token(token_type_t* type, void* value, size_t length) { lf_token_t* _lf_get_token(token_template_t* tmplt) { if (tmplt->token != NULL) { if (tmplt->token->ref_count == 1) { - LF_PRINT_DEBUG("_lf_get_token: Reusing template token: %p with ref_count %zu", tmplt->token, + LF_PRINT_DEBUG("_lf_get_token: Reusing template token: %p with ref_count %zu", (void*)tmplt->token, tmplt->token->ref_count); // Free any previous value in the token. _lf_free_token_value(tmplt->token); @@ -268,7 +268,8 @@ void _lf_initialize_template(token_template_t* tmplt, size_t element_size) { lf_token_t* _lf_initialize_token_with_value(token_template_t* tmplt, void* value, size_t length) { assert(tmplt != NULL); - LF_PRINT_DEBUG("_lf_initialize_token_with_value: template %p, value %p", tmplt, value); + LF_PRINT_DEBUG("_lf_initialize_token_with_value: template %p, value %p", (void*)tmplt, value); + lf_token_t* result = _lf_get_token(tmplt); result->value = value; // Count allocations to issue a warning if this is never freed. @@ -322,14 +323,15 @@ void _lf_free_all_tokens() { void _lf_replace_template_token(token_template_t* tmplt, lf_token_t* newtoken) { assert(tmplt != NULL); - LF_PRINT_DEBUG("_lf_replace_template_token: template: %p newtoken: %p.", tmplt, newtoken); + LF_PRINT_DEBUG("_lf_replace_template_token: template: %p newtoken: %p.", (void*)tmplt, (void*)newtoken); if (tmplt->token != newtoken) { if (tmplt->token != NULL) { _lf_done_using(tmplt->token); } if (newtoken != NULL) { newtoken->ref_count++; - LF_PRINT_DEBUG("_lf_replace_template_token: Incremented ref_count of %p to %zu.", newtoken, newtoken->ref_count); + LF_PRINT_DEBUG("_lf_replace_template_token: Incremented ref_count of %p to %zu.", (void*)newtoken, + newtoken->ref_count); } tmplt->token = newtoken; } @@ -339,16 +341,16 @@ token_freed _lf_done_using(lf_token_t* token) { if (token == NULL) { return NOT_FREED; } - LF_PRINT_DEBUG("_lf_done_using: token = %p, ref_count = %zu.", token, token->ref_count); + LF_PRINT_DEBUG("_lf_done_using: token = %p, ref_count = %zu.", (void*)token, token->ref_count); if (token->ref_count == 0) { - lf_print_warning("Token being freed that has already been freed: %p", token); + lf_print_warning("Token being freed that has already been freed: %p", (void*)token); return NOT_FREED; } token->ref_count--; return _lf_free_token(token); } -void _lf_free_token_copies(struct environment_t* env) { +void _lf_free_token_copies() { while (_lf_tokens_allocated_in_reactions != NULL) { lf_token_t* next = _lf_tokens_allocated_in_reactions->next; _lf_done_using(_lf_tokens_allocated_in_reactions); diff --git a/core/reactor.c b/core/reactor.c index 8bf3b9460..766ac108c 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -27,9 +27,18 @@ extern instant_t start_time; int lf_thread_id() { return 0; } -int lf_mutex_unlock(lf_mutex_t* mutex) { return 0; } -int lf_mutex_init(lf_mutex_t* mutex) { return 0; } -int lf_mutex_lock(lf_mutex_t* mutex) { return 0; } +int lf_mutex_unlock(lf_mutex_t* mutex) { + (void)mutex; + return 0; +} +int lf_mutex_init(lf_mutex_t* mutex) { + (void)mutex; + return 0; +} +int lf_mutex_lock(lf_mutex_t* mutex) { + (void)mutex; + return 0; +} // Defined in reactor_common.c: extern bool fast; @@ -88,6 +97,7 @@ void lf_print_snapshot(environment_t* env) { #endif // NDEBUG void _lf_trigger_reaction(environment_t* env, reaction_t* reaction, int worker_number) { + (void)worker_number; assert(env != GLOBAL_ENVIRONMENT); #ifdef MODAL_REACTORS @@ -368,9 +378,18 @@ int lf_reactor_c_main(int argc, const char* argv[]) { * @brief Notify of new event by calling the single-threaded platform API * @param env Environment in which we are executing. */ -int lf_notify_of_event(environment_t* env) { return _lf_single_threaded_notify_of_event(); } +int lf_notify_of_event(environment_t* env) { + (void)env; + return _lf_single_threaded_notify_of_event(); +} -int lf_critical_section_enter(environment_t* env) { return lf_disable_interrupts_nested(); } +int lf_critical_section_enter(environment_t* env) { + (void)env; + return lf_disable_interrupts_nested(); +} -int lf_critical_section_exit(environment_t* env) { return lf_enable_interrupts_nested(); } +int lf_critical_section_exit(environment_t* env) { + (void)env; + return lf_enable_interrupts_nested(); +} #endif diff --git a/core/reactor_common.c b/core/reactor_common.c index 6fc3d3824..fd3be5ae5 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -119,7 +119,7 @@ void lf_free(struct allocation_record_t** head) { LF_PRINT_DEBUG("Freeing memory at %p", record->allocated); free(record->allocated); struct allocation_record_t* tmp = record->next; - LF_PRINT_DEBUG("Freeing allocation record at %p", record); + LF_PRINT_DEBUG("Freeing allocation record at %p", (void*)record); free(record); record = tmp; } @@ -171,7 +171,7 @@ void _lf_start_time_step(environment_t* env) { LF_PRINT_LOG("--------- Start time step at tag " PRINTF_TAG ".", env->current_tag.time - start_time, env->current_tag.microstep); // Handle dynamically created tokens for mutable inputs. - _lf_free_token_copies(env); + _lf_free_token_copies(); bool** is_present_fields = env->is_present_fields_abbreviated; int size = env->is_present_fields_abbreviated_size; @@ -199,7 +199,7 @@ void _lf_start_time_step(environment_t* env) { #ifdef FEDERATED // If the environment is the top-level one, we have some work to do. environment_t* envs; - int num_envs = _lf_get_environments(&envs); + _lf_get_environments(&envs); if (env == envs) { // This is the top-level environment. @@ -278,7 +278,7 @@ void _lf_pop_events(environment_t* env) { reaction->is_STP_violated = true; LF_PRINT_LOG("Trigger %p has violated the reaction's STP offset. Intended tag: " PRINTF_TAG ". Current tag: " PRINTF_TAG, - event->trigger, event->intended_tag.time - start_time, event->intended_tag.microstep, + (void*)event->trigger, event->intended_tag.time - start_time, event->intended_tag.microstep, env->current_tag.time - start_time, env->current_tag.microstep); // Need to update the last_known_status_tag of the port because otherwise, // the MLAA could get stuck, causing the program to lock up. @@ -519,7 +519,7 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag // Increment the reference count of the token. if (token != NULL) { token->ref_count++; - LF_PRINT_DEBUG("_lf_schedule_at_tag: Incremented ref_count of %p to %zu.", token, token->ref_count); + LF_PRINT_DEBUG("_lf_schedule_at_tag: Incremented ref_count of %p to %zu.", (void*)token, token->ref_count); } // Do not schedule events if the tag is after the stop tag @@ -854,7 +854,7 @@ void schedule_output_reactions(environment_t* env, reaction_t* reaction, int wor for (int j = 0; j < reaction->triggered_sizes[i]; j++) { trigger_t* trigger = triggerArray[j]; if (trigger != NULL) { - LF_PRINT_DEBUG("Trigger %p lists %d reactions.", trigger, trigger->number_of_reactions); + LF_PRINT_DEBUG("Trigger %p lists %d reactions.", (void*)trigger, trigger->number_of_reactions); for (int k = 0; k < trigger->number_of_reactions; k++) { reaction_t* downstream_reaction = trigger->reactions[k]; #ifdef FEDERATED_DECENTRALIZED // Only pass down tardiness for federated LF programs @@ -1202,11 +1202,11 @@ void initialize_global(void) { _lf_count_token_allocations = 0; #endif - environment_t* envs; - int num_envs = _lf_get_environments(&envs); #if defined(LF_SINGLE_THREADED) int max_threads_tracing = 1; #else + environment_t* envs; + int num_envs = _lf_get_environments(&envs); int max_threads_tracing = envs[0].num_workers * num_envs + 1; // add 1 for the main thread #endif #if defined(FEDERATED) @@ -1329,7 +1329,7 @@ void termination(void) { } index_t lf_combine_deadline_and_level(interval_t deadline, int level) { - if (deadline > ULLONG_MAX >> 16) + if (deadline > ((interval_t)ULLONG_MAX >> 16)) return ((ULLONG_MAX >> 16) << 16) | level; else return (deadline << 16) | level; diff --git a/core/tag.c b/core/tag.c index b45b67acc..474d1af42 100644 --- a/core/tag.c +++ b/core/tag.c @@ -106,7 +106,7 @@ instant_t lf_time_logical(void* env) { interval_t lf_time_logical_elapsed(void* env) { return lf_time_logical(env) - start_time; } instant_t lf_time_physical(void) { - instant_t now, last_read_local; + instant_t now; // Get the current clock value LF_ASSERTN(lf_clock_gettime(&now), "Failed to read physical clock."); return now; diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 3419c3483..dda8dacda 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -184,7 +184,7 @@ void lf_set_present(lf_port_base_t* port) { // Support for sparse destination multiports. if (port->sparse_record && port->destination_channel >= 0 && port->sparse_record->size >= 0) { - int next = lf_atomic_fetch_add32(&port->sparse_record->size, 1); + size_t next = (size_t)lf_atomic_fetch_add32(&port->sparse_record->size, 1); if (next >= port->sparse_record->capacity) { // Buffer is full. Have to revert to the classic iteration. port->sparse_record->size = -1; @@ -220,7 +220,7 @@ void lf_set_present(lf_port_base_t* port) { * the stop time, if one was specified. Return true if the full wait time * was reached. */ -bool wait_until(environment_t* env, instant_t logical_time, lf_cond_t* condition) { +bool wait_until(instant_t logical_time, lf_cond_t* condition) { LF_PRINT_DEBUG("-------- Waiting until physical time matches logical time " PRINTF_TIME, logical_time); interval_t wait_until_time = logical_time; #ifdef FEDERATED_DECENTRALIZED // Only apply the STA if coordination is decentralized @@ -326,6 +326,8 @@ tag_t send_next_event_tag(environment_t* env, tag_t tag, bool wait_for_reply) { #elif defined(LF_ENCLAVES) return rti_next_event_tag_locked(env->enclave_info, tag); #else + (void)env; + (void)wait_for_reply; return tag; #endif } @@ -425,7 +427,7 @@ void _lf_next_locked(environment_t* env) { // This can be interrupted if a physical action triggers (e.g., a message // arrives from an upstream federate or a local physical action triggers). LF_PRINT_LOG("Waiting until elapsed time " PRINTF_TIME ".", (next_tag.time - start_time)); - while (!wait_until(env, next_tag.time, &env->event_q_changed)) { + while (!wait_until(next_tag.time, &env->event_q_changed)) { LF_PRINT_DEBUG("_lf_next_locked(): Wait until time interrupted."); // Sleep was interrupted. Check for a new next_event. // The interruption could also have been due to a call to lf_request_stop(). @@ -647,7 +649,7 @@ void _lf_initialize_start_tag(environment_t* env) { // Here we wait until the start time and also release the environment mutex. // this means that the other worker threads will be allowed to start. We need // this to avoid potential deadlock in federated startup. - while (!wait_until(env, start_time + lf_fed_STA_offset, &env->event_q_changed)) { + while (!wait_until(start_time + lf_fed_STA_offset, &env->event_q_changed)) { }; LF_PRINT_DEBUG("Done waiting for start time + STA offset " PRINTF_TIME ".", start_time + lf_fed_STA_offset); LF_PRINT_DEBUG("Physical time is ahead of current time by " PRINTF_TIME ". This should be close to the STA offset.", @@ -857,6 +859,8 @@ void _lf_worker_invoke_reaction(environment_t* env, int worker_number, reaction_ void try_advance_level(environment_t* env, volatile size_t* next_reaction_level) { #ifdef FEDERATED lf_stall_advance_level_federation(env, *next_reaction_level); +#else + (void)env; #endif if (*next_reaction_level < SIZE_MAX) *next_reaction_level += 1; @@ -987,7 +991,7 @@ void start_threads(environment_t* env) { assert(env != GLOBAL_ENVIRONMENT); LF_PRINT_LOG("Starting %u worker threads in environment", env->num_workers); - for (unsigned int i = 0; i < env->num_workers; i++) { + for (int i = 0; i < env->num_workers; i++) { if (lf_thread_create(&env->thread_ids[i], worker, env) != 0) { lf_print_error_and_exit("Could not start thread-%u", i); } diff --git a/core/threaded/scheduler_NP.c b/core/threaded/scheduler_NP.c index 630464dd6..800c9fc2b 100644 --- a/core/threaded/scheduler_NP.c +++ b/core/threaded/scheduler_NP.c @@ -92,7 +92,7 @@ int _lf_sched_distribute_ready_reactions(lf_scheduler_t* scheduler) { (void*)((reaction_t***)scheduler->triggered_reactions)[scheduler->next_reaction_level - 1]; LF_PRINT_DEBUG("Start of rxn queue at %zu is %p", scheduler->next_reaction_level - 1, - ((reaction_t**)scheduler->executing_reactions)[0]); + (void*)((reaction_t**)scheduler->executing_reactions)[0]); if (((reaction_t**)scheduler->executing_reactions)[0] != NULL) { // There is at least one reaction to execute return 1; @@ -111,12 +111,8 @@ void _lf_sched_notify_workers(lf_scheduler_t* scheduler) { // Calculate the number of workers that we need to wake up, which is the // Note: All threads are idle. Therefore, there is no need to lock the mutex // while accessing the index for the current level. - size_t workers_to_awaken = LF_MIN(scheduler->number_of_idle_workers, - scheduler->indexes[scheduler->next_reaction_level - 1 // Current - // reaction - // level - // to execute. - ]); + size_t workers_to_awaken = + LF_MIN(scheduler->number_of_idle_workers, (size_t)(scheduler->indexes[scheduler->next_reaction_level - 1])); LF_PRINT_DEBUG("Scheduler: Notifying %zu workers.", workers_to_awaken); scheduler->number_of_idle_workers -= workers_to_awaken; @@ -188,7 +184,7 @@ void _lf_scheduler_try_advance_tag_and_distribute(lf_scheduler_t* scheduler) { void _lf_sched_wait_for_work(lf_scheduler_t* scheduler, size_t worker_number) { // Increment the number of idle workers by 1 and check if this is the last // worker thread to become idle. - if (lf_atomic_add_fetch32((int32_t*)&scheduler->number_of_idle_workers, 1) == scheduler->number_of_workers) { + if (lf_atomic_add_fetch32((int32_t*)&scheduler->number_of_idle_workers, 1) == (int)scheduler->number_of_workers) { // Last thread to go idle LF_PRINT_DEBUG("Scheduler: Worker %zu is the last idle thread.", worker_number); // Call on the scheduler to distribute work or advance tag. @@ -338,6 +334,7 @@ reaction_t* lf_sched_get_ready_reaction(lf_scheduler_t* scheduler, int worker_nu * @param done_reaction The reaction that is done. */ void lf_sched_done_with_reaction(size_t worker_number, reaction_t* done_reaction) { + (void)worker_number; if (!lf_atomic_bool_compare_and_swap32((int32_t*)&done_reaction->status, queued, inactive)) { lf_print_error_and_exit("Unexpected reaction status: %d. Expected %d.", done_reaction->status, queued); } @@ -363,6 +360,8 @@ void lf_sched_done_with_reaction(size_t worker_number, reaction_t* done_reaction * */ void lf_scheduler_trigger_reaction(lf_scheduler_t* scheduler, reaction_t* reaction, int worker_number) { + (void)worker_number; + if (reaction == NULL || !lf_atomic_bool_compare_and_swap32((int32_t*)&reaction->status, inactive, queued)) { return; } diff --git a/core/threaded/watchdog.c b/core/threaded/watchdog.c index 4f26f26e7..3b9a6d62c 100644 --- a/core/threaded/watchdog.c +++ b/core/threaded/watchdog.c @@ -43,13 +43,12 @@ void _lf_initialize_watchdogs(environment_t* env) { * @brief Terminate all watchdog threads. */ void _lf_watchdog_terminate_all(environment_t* env) { - void* thread_return; + void* thread_ret; for (int i = 0; i < env->watchdogs_size; i++) { watchdog_t* watchdog = env->watchdogs[i]; LF_MUTEX_LOCK(watchdog->base->reactor_mutex); _lf_watchdog_terminate(watchdog); LF_MUTEX_UNLOCK(watchdog->base->reactor_mutex); - void* thread_ret; lf_thread_join(watchdog->thread_id, &thread_ret); } } diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index e73e3ed48..d26d8b2aa 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -15,7 +15,11 @@ int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return (thiz > that); } -int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 0; } +int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { + (void)thiz; + (void)that; + return 0; +} int event_matches(void* event1, void* event2) { return (((event_t*)event1)->trigger == ((event_t*)event2)->trigger); } @@ -35,10 +39,10 @@ void set_reaction_position(void* reaction, size_t pos) { ((reaction_t*)reaction) void print_reaction(void* reaction) { reaction_t* r = (reaction_t*)reaction; - LF_PRINT_DEBUG("%s: chain_id: %llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, r); + LF_PRINT_DEBUG("%s: chain_id: %llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, reaction); } void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, e->trigger, e->token); + LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, (void*)e->trigger, (void*)e->token); } diff --git a/core/utils/pqueue_support.h b/core/utils/pqueue_support.h index b7c0a08c1..c751b67f1 100644 --- a/core/utils/pqueue_support.h +++ b/core/utils/pqueue_support.h @@ -97,7 +97,7 @@ static void set_reaction_position(void* a, size_t pos) { ((reaction_t*)a)->pos = */ static void print_reaction(void* reaction) { reaction_t* r = (reaction_t*)reaction; - LF_PRINT_DEBUG("%s: chain_id:%llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, r); + LF_PRINT_DEBUG("%s: chain_id:%llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, (void*)r); } /** @@ -107,7 +107,7 @@ static void print_reaction(void* reaction) { */ static void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, e->trigger, e->token); + LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, (void*)e->trigger, (void*)e->token); } // ********** Priority Queue Support End diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 9406ca1ca..9fe00653d 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -81,7 +81,7 @@ pqueue_tag_t* pqueue_tag_init(size_t initial_size) { } void pqueue_tag_free(pqueue_tag_t* q) { - for (int i = 1; i < q->size; i++) { + for (size_t i = 1; i < q->size; i++) { if (q->d[i] != NULL && ((pqueue_tag_element_t*)q->d[i])->is_dynamic) { free(q->d[i]); } diff --git a/core/utils/util.c b/core/utils/util.c index 554707edb..881b6dc05 100644 --- a/core/utils/util.c +++ b/core/utils/util.c @@ -73,20 +73,20 @@ int lf_fed_id() { return _lf_my_fed_id; } // Declaration needed to attach attributes to suppress warnings of the form: // "warning: function '_lf_message_print' might be a candidate for 'gnu_printf' // format attribute [-Wsuggest-attribute=format]" -void _lf_message_print(int is_error, const char* prefix, const char* format, va_list args, int log_level) - ATTRIBUTE_FORMAT_PRINTF(3, 0); +void _lf_message_print(const char* prefix, const char* format, va_list args, int log_level) + ATTRIBUTE_FORMAT_PRINTF(2, 0); /** * Print a fatal error message. Internal function. */ static void lf_vprint_fatal_error(const char* format, va_list args) { - _lf_message_print(1, "FATAL ERROR: ", format, args, LOG_LEVEL_ERROR); + _lf_message_print("FATAL ERROR: ", format, args, LOG_LEVEL_ERROR); } /** * Internal implementation of the next few reporting functions. */ -void _lf_message_print(int is_error, const char* prefix, const char* format, va_list args, +void _lf_message_print(const char* prefix, const char* format, va_list args, int log_level) { // Disable warnings about format check. // The logging level may be set either by a LOG_LEVEL #define // (which is code generated based on the logging target property) @@ -151,7 +151,7 @@ void lf_print(const char* format, ...) { va_end(args); } -void lf_vprint(const char* format, va_list args) { _lf_message_print(0, "", format, args, LOG_LEVEL_INFO); } +void lf_vprint(const char* format, va_list args) { _lf_message_print("", format, args, LOG_LEVEL_INFO); } void lf_print_log(const char* format, ...) { va_list args; @@ -160,7 +160,7 @@ void lf_print_log(const char* format, ...) { va_end(args); } -void lf_vprint_log(const char* format, va_list args) { _lf_message_print(0, "LOG: ", format, args, LOG_LEVEL_LOG); } +void lf_vprint_log(const char* format, va_list args) { _lf_message_print("LOG: ", format, args, LOG_LEVEL_LOG); } void lf_print_debug(const char* format, ...) { va_list args; @@ -169,9 +169,7 @@ void lf_print_debug(const char* format, ...) { va_end(args); } -void lf_vprint_debug(const char* format, va_list args) { - _lf_message_print(0, "DEBUG: ", format, args, LOG_LEVEL_DEBUG); -} +void lf_vprint_debug(const char* format, va_list args) { _lf_message_print("DEBUG: ", format, args, LOG_LEVEL_DEBUG); } void lf_print_error(const char* format, ...) { va_list args; @@ -180,9 +178,7 @@ void lf_print_error(const char* format, ...) { va_end(args); } -void lf_vprint_error(const char* format, va_list args) { - _lf_message_print(1, "ERROR: ", format, args, LOG_LEVEL_ERROR); -} +void lf_vprint_error(const char* format, va_list args) { _lf_message_print("ERROR: ", format, args, LOG_LEVEL_ERROR); } void lf_print_warning(const char* format, ...) { va_list args; @@ -192,7 +188,7 @@ void lf_print_warning(const char* format, ...) { } void lf_vprint_warning(const char* format, va_list args) { - _lf_message_print(1, "WARNING: ", format, args, LOG_LEVEL_WARNING); + _lf_message_print("WARNING: ", format, args, LOG_LEVEL_WARNING); } void lf_print_error_and_exit(const char* format, ...) { diff --git a/include/core/federated/network/net_common.h b/include/core/federated/network/net_common.h index eb27d64d6..4d9393f28 100644 --- a/include/core/federated/network/net_common.h +++ b/include/core/federated/network/net_common.h @@ -483,7 +483,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST; \ encode_int64(time, &(buffer[1])); \ - assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) @@ -501,7 +500,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST_REPLY; \ encode_int64(time, &(buffer[1])); \ - assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) diff --git a/include/core/federated/network/net_util.h b/include/core/federated/network/net_util.h index 555c8df89..24b4782f9 100644 --- a/include/core/federated/network/net_util.h +++ b/include/core/federated/network/net_util.h @@ -365,7 +365,7 @@ bool validate_user(const char* user); * Extract one match group from the rti_addr regex . * @return true if SUCCESS, else false. */ -bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int max_len, int min_len, +bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, size_t max_len, size_t min_len, const char* err_msg); /** @@ -373,7 +373,7 @@ bool extract_match_group(const char* rti_addr, char* dest, regmatch_t group, int * @return true if success, else false. */ bool extract_match_groups(const char* rti_addr, char** rti_addr_strs, bool** rti_addr_flags, regmatch_t* group_array, - int* gids, int* max_lens, int* min_lens, const char** err_msgs); + int* gids, size_t* max_lens, size_t* min_lens, const char** err_msgs); /** * Extract the host, port and user from rti_addr. diff --git a/include/core/lf_token.h b/include/core/lf_token.h index f60fd18b5..219538dd3 100644 --- a/include/core/lf_token.h +++ b/include/core/lf_token.h @@ -341,7 +341,7 @@ token_freed _lf_done_using(lf_token_t* token); * to avoid memory leaks. * @param env Environment in which we are executing. */ -void _lf_free_token_copies(struct environment_t* env); +void _lf_free_token_copies(void); #endif /* LF_TOKEN_H */ /** @} */ diff --git a/include/core/threaded/reactor_threaded.h b/include/core/threaded/reactor_threaded.h index 6971cec17..96de7ac49 100644 --- a/include/core/threaded/reactor_threaded.h +++ b/include/core/threaded/reactor_threaded.h @@ -90,7 +90,7 @@ void _lf_decrement_tag_barrier_locked(environment_t* env); int _lf_wait_on_tag_barrier(environment_t* env, tag_t proposed_tag); void lf_synchronize_with_other_federates(void); -bool wait_until(environment_t* env, instant_t logical_time_ns, lf_cond_t* condition); +bool wait_until(instant_t logical_time_ns, lf_cond_t* condition); tag_t get_next_event_tag(environment_t* env); tag_t send_next_event_tag(environment_t* env, tag_t tag, bool wait_for_reply); void _lf_next_locked(environment_t* env); diff --git a/include/core/tracepoint.h b/include/core/tracepoint.h index aea972b14..b15fed269 100644 --- a/include/core/tracepoint.h +++ b/include/core/tracepoint.h @@ -367,10 +367,11 @@ void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int p void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag); #else -#define tracepoint_federate_to_rti(...) ; -#define tracepoint_federate_from_rti(...) ; -#define tracepoint_federate_to_federate(...) ; -#define tracepoint_federate_from_federate(...) ; +static inline void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag) {} +static inline void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* tag) {} +static inline void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) {} +static inline void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) { +} #endif // FEDERATED //////////////////////////////////////////////////////////// @@ -397,38 +398,107 @@ void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag); #else -#define tracepoint_rti_to_federate(...) ; -#define tracepoint_rti_from_federate(...) ; +static inline void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag) {} +static inline void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag) {} #endif // RTI_TRACE #else typedef struct trace_t trace_t; +static inline int register_user_trace_event(void* self, char* description) { + (void)self; + (void)description; + return 0; +} +static inline void tracepoint_schedule(environment_t* env, trigger_t* trigger, interval_t extra_delay) { + (void)env; + (void)trigger; + (void)extra_delay; +} +static inline void tracepoint_user_event(void* self, char* description) { + (void)self; + (void)description; +} +static inline void tracepoint_user_value(void* self, char* description, long long value) { + (void)self; + (void)description; + (void)value; +} +static inline void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)partner_id; + (void)tag; +} +static inline void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)partner_id; + (void)tag; +} +static inline void lf_tracing_global_init(char* file_name_prefix, int process_id, int max_num_local_threads) { + (void)file_name_prefix; + (void)process_id; + (void)max_num_local_threads; +} +static inline void lf_tracing_global_shutdown() {} +static inline void lf_tracing_set_start_time(int64_t start_time) { (void)start_time; } -// empty definition in case we compile without tracing -#define _lf_register_trace_event(...) 1 -#define register_user_trace_event(...) 1 -#define tracepoint_reaction_starts(...) -#define tracepoint_reaction_ends(...) -#define tracepoint_schedule(...) -#define tracepoint_user_event(...) -#define tracepoint_user_value(...) -#define tracepoint_worker_wait_starts(...) -#define tracepoint_worker_wait_ends(...) -#define tracepoint_scheduler_advancing_time_starts(...) ; -#define tracepoint_scheduler_advancing_time_ends(...) ; -#define tracepoint_reaction_deadline_missed(...) ; -#define tracepoint_federate_to_rti(...) ; -#define tracepoint_federate_from_rti(...) ; -#define tracepoint_federate_to_federate(...) ; -#define tracepoint_federate_from_federate(...) ; -#define tracepoint_rti_to_federate(...) ; -#define tracepoint_rti_from_federate(...) ; - -#define lf_tracing_register_trace_event(...) ; -#define lf_tracing_set_start_time(...) ; -#define tracepoint(...) ; -#define lf_tracing_global_init(...) ; -#define lf_tracing_global_shutdown(...) ; +#define tracepoint_reaction_starts(env, reaction, worker) \ + while (0) { \ + (void)env; \ + (void)reaction; \ + (void)worker; \ + } +#define tracepoint_reaction_ends(env, reaction, worker) \ + while (0) { \ + (void)env; \ + (void)reaction; \ + (void)worker; \ + } +#define tracepoint_worker_wait_starts(env, worker) \ + while (0) { \ + (void)env; \ + (void)worker; \ + } +#define tracepoint_worker_wait_ends(env, worker) \ + while (0) { \ + (void)env; \ + (void)worker; \ + } +#define tracepoint_scheduler_advancing_time_starts(env) \ + while (0) { \ + (void)env; \ + } +#define tracepoint_scheduler_advancing_time_ends(env) \ + while (0) { \ + (void)env; \ + } +#define tracepoint_reaction_deadline_missed(env, reaction, worker) \ + while (0) { \ + (void)env; \ + (void)reaction; \ + (void)worker; \ + } #endif // LF_TRACE #endif // TRACEPOINT_H diff --git a/include/core/utils/impl/hashmap.h b/include/core/utils/impl/hashmap.h index 8490e3f62..e64774887 100644 --- a/include/core/utils/impl/hashmap.h +++ b/include/core/utils/impl/hashmap.h @@ -125,7 +125,6 @@ void HASHMAP(free)(HASHMAP(t) * hashmap) { void HASHMAP(put)(HASHMAP(t) * hashmap, K key, V value) { assert(key != hashmap->nothing); - assert(key >= 0); HASHMAP(entry_t)* write_to = HASHMAP(get_actual_address)(hashmap, key); write_to->key = key; write_to->value = value; diff --git a/lib/schedule.c b/lib/schedule.c index 645bb41ec..8d237ce55 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -45,12 +45,6 @@ trigger_handle_t lf_schedule_token(void* action, interval_t extra_delay, lf_toke } trigger_handle_t lf_schedule_copy(void* action, interval_t offset, void* value, size_t length) { - if (length < 0) { - lf_print_error("schedule_copy():" - " Ignoring request to copy a value with a negative length (%zu).", - length); - return -1; - } if (value == NULL) { return lf_schedule_token(action, offset, NULL); } @@ -129,13 +123,13 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int extra_delay = 0LL; } - LF_PRINT_DEBUG("lf_schedule_trigger: scheduling trigger %p with delay " PRINTF_TIME " and token %p.", trigger, - extra_delay, token); + LF_PRINT_DEBUG("lf_schedule_trigger: scheduling trigger %p with delay " PRINTF_TIME " and token %p.", (void*)trigger, + extra_delay, (void*)token); // Increment the reference count of the token. if (token != NULL) { token->ref_count++; - LF_PRINT_DEBUG("lf_schedule_trigger: Incremented ref_count of %p to %zu.", token, token->ref_count); + LF_PRINT_DEBUG("lf_schedule_trigger: Incremented ref_count of %p to %zu.", (void*)token, token->ref_count); } // The trigger argument could be null, meaning that nothing is triggered. diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index e37a166a2..103801c35 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -77,7 +77,7 @@ int lf_critical_section_exit(environment_t* env); // To support the single-threaded runtime, we need the following functions. They // are not required by the threaded runtime and is thus hidden behind a #ifdef. #if defined(LF_SINGLE_THREADED) -typedef void lf_mutex_t; +typedef void* lf_mutex_t; /** * @brief Disable interrupts with support for nested calls * @return 0 on success diff --git a/low_level_platform/api/platform/lf_nrf52_support.h b/low_level_platform/api/platform/lf_nrf52_support.h index b93edaf8e..18613b2e0 100644 --- a/low_level_platform/api/platform/lf_nrf52_support.h +++ b/low_level_platform/api/platform/lf_nrf52_support.h @@ -48,7 +48,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * No mutex or condition variable needed for single threaded NRF platforms */ -typedef void lf_mutex_t; +typedef void* lf_mutex_t; typedef void _lf_cond_var_t; #endif // LF_nRF52832_SUPPORT_H diff --git a/low_level_platform/impl/src/lf_C11_threads_support.c b/low_level_platform/impl/src/lf_C11_threads_support.c index 527ce28d3..34ccd3969 100644 --- a/low_level_platform/impl/src/lf_C11_threads_support.c +++ b/low_level_platform/impl/src/lf_C11_threads_support.c @@ -5,8 +5,24 @@ #include #include // For fixed-width integral types +struct lf_thread_data { + void* (*thread)(void*); + void* arguments; +}; + +static int lf_thread_c11_wrapper(void* args) { + struct lf_thread_data* thread_data = (struct lf_thread_data*)args; + thread_data->thread(thread_data->arguments); + free(thread_data); + return 0; +} + int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* arguments) { - return thrd_create((thrd_t*)thread, (thrd_start_t)lf_thread, arguments); + struct lf_thread_data* thread_data = (struct lf_thread_data*)malloc(sizeof(struct lf_thread_data)); + thread_data->thread = lf_thread; + thread_data->arguments = arguments; + + return thrd_create((thrd_t*)thread, (thrd_start_t)lf_thread_c11_wrapper, thread_data); } int lf_thread_join(lf_thread_t thread, void** thread_return) { diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 3edf8d7ea..fb2d19cba 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -57,6 +57,7 @@ int lf_sleep(interval_t sleep_duration) { } int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { + (void)env; interval_t sleep_duration = wakeup_time - lf_time_physical(); if (sleep_duration <= 0) { diff --git a/platform/impl/platform.c b/platform/impl/platform.c index ddd182404..361f36992 100644 --- a/platform/impl/platform.c +++ b/platform/impl/platform.c @@ -20,7 +20,8 @@ lf_platform_mutex_ptr_t lf_platform_mutex_new() { if (mutex) lf_mutex_init(mutex); return mutex; -}; +} + void lf_platform_mutex_free(lf_platform_mutex_ptr_t mutex) { free((void*)mutex); } int lf_platform_mutex_lock(lf_platform_mutex_ptr_t mutex) { return lf_mutex_lock((lf_mutex_t*)mutex); } int lf_platform_mutex_unlock(lf_platform_mutex_ptr_t mutex) { return lf_mutex_unlock((lf_mutex_t*)mutex); } diff --git a/test/general/utils/hashmap_test.c b/test/general/utils/hashmap_test.c index 2134071e6..4cfd5d70d 100644 --- a/test/general/utils/hashmap_test.c +++ b/test/general/utils/hashmap_test.c @@ -54,7 +54,6 @@ void test_get(hashmap_object2int_t* h) { * which each of two actions are performed, expressed as percents. */ void run_test(hashmap_object2int_t* h, int* distribution) { - int result = 1; int r = rand(); int choice = (r < 0 ? -r : r) % 100; if ((choice = choice - distribution[0]) < 0) { From 8dfa8d19bd5759f09c555c7e902106c0298614a5 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 15:40:53 +0100 Subject: [PATCH 16/95] Fix errors in hashmap test --- test/general/utils/hashmap_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/general/utils/hashmap_test.c b/test/general/utils/hashmap_test.c index 4cfd5d70d..28e8deb27 100644 --- a/test/general/utils/hashmap_test.c +++ b/test/general/utils/hashmap_test.c @@ -15,9 +15,9 @@ static hashmap_object2int_entry_t mock[CAPACITY]; static size_t mock_size = 0; void test_put(hashmap_object2int_t* h) { - void* key = NULL; + int* key = NULL; while (!key) - key = NULL + (rand() % CAPACITY); // Generate a dummy pointer. + key += (rand() % CAPACITY); // Generate a dummy pointer. int value = rand(); hashmap_object2int_entry_t entry = (hashmap_object2int_entry_t){.key = key, .value = value}; hashmap_object2int_put(h, entry.key, entry.value); From ce373401774596e2ca09e6633ae03e4242aaba66 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 15:57:43 +0100 Subject: [PATCH 17/95] Add newlines to the end of some files --- low_level_platform/api/platform/lf_POSIX_threads_support.h | 2 +- test/src_gen_stub.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/low_level_platform/api/platform/lf_POSIX_threads_support.h b/low_level_platform/api/platform/lf_POSIX_threads_support.h index d27e7a16f..340fc3e88 100644 --- a/low_level_platform/api/platform/lf_POSIX_threads_support.h +++ b/low_level_platform/api/platform/lf_POSIX_threads_support.h @@ -44,4 +44,4 @@ typedef struct { } lf_cond_t; typedef pthread_t lf_thread_t; -#endif \ No newline at end of file +#endif diff --git a/test/src_gen_stub.c b/test/src_gen_stub.c index d67d238ea..1e4630a6e 100644 --- a/test/src_gen_stub.c +++ b/test/src_gen_stub.c @@ -19,4 +19,4 @@ void logical_tag_complete(tag_t tag_to_send) {} int _lf_get_environments(environment_t** envs) { *envs = &_env; return 1; -} \ No newline at end of file +} From 6983d66b2c55cc71d6ddf9268d3c4776e72c59ca Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 16:10:28 +0100 Subject: [PATCH 18/95] Fix warnings in trace_impl --- trace/impl/include/trace_impl.h | 6 +++--- trace/impl/src/trace_impl.c | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/trace/impl/include/trace_impl.h b/trace/impl/include/trace_impl.h index 3e1bd6fe6..f5a09ff09 100644 --- a/trace/impl/include/trace_impl.h +++ b/trace/impl/include/trace_impl.h @@ -20,10 +20,10 @@ typedef struct trace_t { * which will create a significant pause in the calling thread. */ trace_record_nodeps_t** _lf_trace_buffer; - int* _lf_trace_buffer_size; + size_t * _lf_trace_buffer_size; /** The number of trace buffers allocated when tracing starts. */ - int _lf_number_of_trace_buffers; + size_t _lf_number_of_trace_buffers; /** Marker that tracing is stopping or has stopped. */ int _lf_trace_stop; @@ -36,7 +36,7 @@ typedef struct trace_t { /** Table of pointers to a description of the object. */ object_description_t _lf_trace_object_descriptions[TRACE_OBJECT_TABLE_SIZE]; - int _lf_trace_object_descriptions_size; + size_t _lf_trace_object_descriptions_size; /** Indicator that the trace header information has been written to the file. */ bool _lf_trace_header_written; diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index d43a36e87..ba29163c7 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -45,7 +45,7 @@ static int write_trace_header(trace_t* trace) { _LF_TRACE_FAILURE(trace); // Next we write the table. - for (int i = 0; i < trace->_lf_trace_object_descriptions_size; i++) { + for (size_t i = 0; i < trace->_lf_trace_object_descriptions_size; i++) { // Write the pointer to the self struct. items_written = fwrite(&trace->_lf_trace_object_descriptions[i].pointer, sizeof(void*), 1, trace->_lf_trace_file); if (items_written != 1) @@ -63,7 +63,7 @@ static int write_trace_header(trace_t* trace) { _LF_TRACE_FAILURE(trace); // Write the description. - int description_size = strlen(trace->_lf_trace_object_descriptions[i].description); + size_t description_size = strlen(trace->_lf_trace_object_descriptions[i].description); items_written = fwrite(trace->_lf_trace_object_descriptions[i].description, sizeof(char), description_size + 1, // Include null terminator. trace->_lf_trace_file); @@ -137,11 +137,11 @@ static void start_trace(trace_t* trace, int max_num_local_threads) { trace->_lf_trace_buffer = (trace_record_nodeps_t**)malloc(sizeof(trace_record_nodeps_t*) * (trace->_lf_number_of_trace_buffers + 1)); trace->_lf_trace_buffer++; // the buffer at index -1 is a fallback for user threads. - for (int i = -1; i < trace->_lf_number_of_trace_buffers; i++) { + for (int i = -1; i < (int) trace->_lf_number_of_trace_buffers; i++) { trace->_lf_trace_buffer[i] = (trace_record_nodeps_t*)malloc(sizeof(trace_record_nodeps_t) * TRACE_BUFFER_CAPACITY); } // Array of counters that track the size of each trace record (per thread). - trace->_lf_trace_buffer_size = (int*)calloc(sizeof(int), trace->_lf_number_of_trace_buffers + 1); + trace->_lf_trace_buffer_size = (size_t*)calloc(sizeof(int), trace->_lf_number_of_trace_buffers + 1); trace->_lf_trace_buffer_size++; trace->_lf_trace_stop = 0; @@ -178,9 +178,9 @@ static void stop_trace_locked(trace_t* trace) { // Trace was already stopped. Nothing to do. return; } - for (int i = -1; i < trace->_lf_number_of_trace_buffers; i++) { + for (int i = -1; i < (int) trace->_lf_number_of_trace_buffers; i++) { // Flush the buffer if it has data. - LF_PRINT_DEBUG("Trace buffer %d has %d records.", i, trace->_lf_trace_buffer_size[i]); + LF_PRINT_DEBUG("Trace buffer %d has %zu records.", i, trace->_lf_trace_buffer_size[i]); if (trace->_lf_trace_buffer_size && trace->_lf_trace_buffer_size[i] > 0) { flush_trace_locked(trace, i); } @@ -231,6 +231,7 @@ void lf_tracing_register_trace_event(object_description_t description) { } void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { + (void)worker; // Worker argument determines which buffer to write to. int tid = lf_thread_id(); if (tid < 0) { @@ -239,8 +240,8 @@ void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { // Therefore we should fall back to using a mutex. lf_platform_mutex_lock(trace_mutex); } - if (tid > trace._lf_number_of_trace_buffers) { - lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%d)", tid, + if (((size_t) tid) > trace._lf_number_of_trace_buffers) { + lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%zu)", tid, trace._lf_number_of_trace_buffers); } From 5421e80d4a7c06b10faafba96e974c6d750cb7dd Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 16:26:16 +0100 Subject: [PATCH 19/95] Less errors on macOS because we use GNU specific extensions --- CMakeLists.txt | 2 +- lf_utils.cmake | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2edacb188..8a916023f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ if(DEFINED LF_SINGLE_THREADED) endif() # Warnings as errors -add_compile_options(-Wall -Wpedantic -Werror) +add_compile_options(-Werror) set(Test test) set(Lib lib) diff --git a/lf_utils.cmake b/lf_utils.cmake index de6d4c5df..294a7127a 100644 --- a/lf_utils.cmake +++ b/lf_utils.cmake @@ -1,6 +1,8 @@ function(lf_enable_compiler_warnings target) if(MSVC) target_compile_options(${target} PRIVATE /W4 /WX) + elseif(APPLE) + target_compile_options(${target} PRIVATE -Wall -Werror) else() target_compile_options(${target} PRIVATE -Wall -Wextra -pedantic -Werror) endif() From 249bf9d3ab0f00e7234f6216f36683adfe8ea8ba Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 6 Mar 2024 17:01:03 +0100 Subject: [PATCH 20/95] Move lf_utils.cmake --- core/CMakeLists.txt | 2 +- lf_utils.cmake => core/lf_utils.cmake | 0 lib/CMakeLists.txt | 2 +- low_level_platform/impl/CMakeLists.txt | 2 +- trace/impl/CMakeLists.txt | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename lf_utils.cmake => core/lf_utils.cmake (100%) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 229d2fba2..72eab35c5 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,7 +1,7 @@ set(CORE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) -include(${LF_ROOT}/lf_utils.cmake) +include(${LF_ROOT}/core/lf_utils.cmake) # Get the general common sources for reactor-c list(APPEND GENERAL_SOURCES tag.c clock.c port.c mixed_radix.c reactor_common.c lf_token.c environment.c) diff --git a/lf_utils.cmake b/core/lf_utils.cmake similarity index 100% rename from lf_utils.cmake rename to core/lf_utils.cmake diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 20b158505..0b805b7e4 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,5 +1,5 @@ set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/..) -include(${LF_ROOT}/lf_utils.cmake) +include(${LF_ROOT}/core/lf_utils.cmake) add_library(lib schedule.c) target_link_libraries(lib PRIVATE lf::low-level-platform-api) diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index d14ecb830..44c9e9366 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -1,7 +1,7 @@ # Check which system we are running on to select the correct platform support # file and assign the file's path to LF_PLATFORM_FILE set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..) -include(${LF_ROOT}/lf_utils.cmake) +include(${LF_ROOT}/core/lf_utils.cmake) if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") set(CMAKE_SYSTEM_VERSION 10.0) diff --git a/trace/impl/CMakeLists.txt b/trace/impl/CMakeLists.txt index 99f11c517..f4a6b8b55 100644 --- a/trace/impl/CMakeLists.txt +++ b/trace/impl/CMakeLists.txt @@ -1,5 +1,5 @@ set(LF_ROOT ${CMAKE_CURRENT_LIST_DIR}/../..) -include(${LF_ROOT}/lf_utils.cmake) +include(${LF_ROOT}/core/lf_utils.cmake) add_library(lf-trace-impl STATIC) add_library(lf::trace-impl ALIAS lf-trace-impl) From a6a04e4092ccb8f4231ad094fc724006fd10e845 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 09:05:49 +0100 Subject: [PATCH 21/95] Do not do -Werror on macOS and Win --- core/lf_utils.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lf_utils.cmake b/core/lf_utils.cmake index 294a7127a..226f0760d 100644 --- a/core/lf_utils.cmake +++ b/core/lf_utils.cmake @@ -1,9 +1,9 @@ function(lf_enable_compiler_warnings target) if(MSVC) - target_compile_options(${target} PRIVATE /W4 /WX) + target_compile_options(${target} PRIVATE /W4) elseif(APPLE) - target_compile_options(${target} PRIVATE -Wall -Werror) + target_compile_options(${target} PRIVATE -Wall) else() - target_compile_options(${target} PRIVATE -Wall -Wextra -pedantic -Werror) + target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror) endif() endfunction() \ No newline at end of file From 34442646f82c0391a454fdea0df8ec3c98c41316 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 09:05:56 +0100 Subject: [PATCH 22/95] Fix warnings --- core/tag.c | 2 +- core/threaded/reactor_threaded.c | 1 + include/core/tracepoint.h | 97 ++++++++++---------------------- trace/impl/include/trace_impl.h | 5 +- trace/impl/src/trace_impl.c | 12 +--- util/tracing/trace_util.c | 59 +++++++++++++++++++ util/tracing/trace_util.h | 6 ++ 7 files changed, 102 insertions(+), 80 deletions(-) diff --git a/core/tag.c b/core/tag.c index 474d1af42..9bb35933f 100644 --- a/core/tag.c +++ b/core/tag.c @@ -194,7 +194,7 @@ size_t lf_readable_time(char* buffer, instant_t time) { } size_t printed = lf_comma_separated_time(buffer, time); buffer += printed; - snprintf(buffer, 3, " %s", units); + snprintf(buffer, 4, " %s", units); buffer += strlen(units) + 1; } return (buffer - original_buffer); diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index dda8dacda..e364675d6 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -982,6 +982,7 @@ void lf_print_snapshot(environment_t* env) { } #else // NDEBUG void lf_print_snapshot(environment_t* env) { + (void)env; // Do nothing. } #endif // NDEBUG diff --git a/include/core/tracepoint.h b/include/core/tracepoint.h index b15fed269..a91f34e4a 100644 --- a/include/core/tracepoint.h +++ b/include/core/tracepoint.h @@ -106,68 +106,6 @@ typedef enum { #include "trace.h" -/** - * String description of event types. - */ -static const char* trace_event_names[] = { - "Reaction starts", - "Reaction ends", - "Reaction deadline missed", - "Schedule called", - "User-defined event", - "User-defined valued event", - "Worker wait starts", - "Worker wait ends", - "Scheduler advancing time starts", - "Scheduler advancing time ends", - "Federated marker", - // Sending messages - "Sending ACK", - "Sending FAILED", - "Sending TIMESTAMP", - "Sending NET", - "Sending LTC", - "Sending STOP_REQ", - "Sending STOP_REQ_REP", - "Sending STOP_GRN", - "Sending FED_ID", - "Sending PTAG", - "Sending TAG", - "Sending REJECT", - "Sending RESIGN", - "Sending PORT_ABS", - "Sending CLOSE_RQ", - "Sending TAGGED_MSG", - "Sending P2P_TAGGED_MSG", - "Sending MSG", - "Sending P2P_MSG", - "Sending ADR_AD", - "Sending ADR_QR", - // Receiving messages - "Receiving ACK", - "Receiving FAILED", - "Receiving TIMESTAMP", - "Receiving NET", - "Receiving LTC", - "Receiving STOP_REQ", - "Receiving STOP_REQ_REP", - "Receiving STOP_GRN", - "Receiving FED_ID", - "Receiving PTAG", - "Receiving TAG", - "Receiving REJECT", - "Receiving RESIGN", - "Receiving PORT_ABS", - "Receiving CLOSE_RQ", - "Receiving TAGGED_MSG", - "Receiving P2P_TAGGED_MSG", - "Receiving MSG", - "Receiving P2P_MSG", - "Receiving ADR_AD", - "Receiving ADR_QR", - "Receiving UNIDENTIFIED", -}; - /** * @brief A trace record that gets written in binary to the trace file in the default implementation. */ @@ -367,10 +305,27 @@ void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int p void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag); #else -static inline void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag) {} -static inline void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* tag) {} -static inline void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) {} +static inline void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)partner_id; + (void)tag; +} static inline void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)partner_id; + (void)tag; } #endif // FEDERATED @@ -398,8 +353,16 @@ void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag); #else -static inline void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag) {} -static inline void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag) {} +static inline void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} +static inline void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* tag) { + (void)event_type; + (void)fed_id; + (void)tag; +} #endif // RTI_TRACE #else diff --git a/trace/impl/include/trace_impl.h b/trace/impl/include/trace_impl.h index f5a09ff09..2ac6d51f5 100644 --- a/trace/impl/include/trace_impl.h +++ b/trace/impl/include/trace_impl.h @@ -6,6 +6,9 @@ /** Size of the table of trace objects. */ #define TRACE_OBJECT_TABLE_SIZE 1024 +/** Max length of trace file name*/ +#define TRACE_MAX_FILENAME_LENGTH 128 + // TYPE DEFINITIONS ********************************************************** /** @@ -32,7 +35,7 @@ typedef struct trace_t { FILE* _lf_trace_file; /** The file name where the traces are written*/ - char* filename; + char filename[TRACE_MAX_FILENAME_LENGTH]; /** Table of pointers to a description of the object. */ object_description_t _lf_trace_object_descriptions[TRACE_OBJECT_TABLE_SIZE]; diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index ba29163c7..c372e71fd 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -150,15 +150,8 @@ static void start_trace(trace_t* trace, int max_num_local_threads) { static void trace_new(char* filename) { - // Determine length of the filename - size_t len = strlen(filename) + 1; - - // Allocate memory for the filename on the trace struct - trace.filename = (char*)malloc(len * sizeof(char)); - LF_ASSERT(trace.filename, "Out of memory"); - // Copy it to the struct - strncpy(trace.filename, filename, len); + strncpy(trace.filename, filename, TRACE_MAX_FILENAME_LENGTH); // FIXME: location of trace file should be customizable. trace._lf_trace_file = fopen(trace.filename, "w"); if (trace._lf_trace_file == NULL) { @@ -171,8 +164,6 @@ static void trace_new(char* filename) { } } -static void trace_free(trace_t* trace) { free(trace->filename); } - static void stop_trace_locked(trace_t* trace) { if (trace->_lf_trace_stop) { // Trace was already stopped. Nothing to do. @@ -281,6 +272,5 @@ void lf_tracing_global_init(char* file_name_prefix, int fedid, int max_num_local void lf_tracing_set_start_time(int64_t time) { start_time = time; } void lf_tracing_global_shutdown() { stop_trace(&trace); - trace_free(&trace); lf_platform_mutex_free(trace_mutex); } diff --git a/util/tracing/trace_util.c b/util/tracing/trace_util.c index ed32c5baa..ffe0c6b8f 100644 --- a/util/tracing/trace_util.c +++ b/util/tracing/trace_util.c @@ -62,6 +62,65 @@ typedef struct open_file_t { } open_file_t; open_file_t* _open_files = NULL; +const char* trace_event_names[] = { + "Reaction starts", + "Reaction ends", + "Reaction deadline missed", + "Schedule called", + "User-defined event", + "User-defined valued event", + "Worker wait starts", + "Worker wait ends", + "Scheduler advancing time starts", + "Scheduler advancing time ends", + "Federated marker", + // Sending messages + "Sending ACK", + "Sending FAILED", + "Sending TIMESTAMP", + "Sending NET", + "Sending LTC", + "Sending STOP_REQ", + "Sending STOP_REQ_REP", + "Sending STOP_GRN", + "Sending FED_ID", + "Sending PTAG", + "Sending TAG", + "Sending REJECT", + "Sending RESIGN", + "Sending PORT_ABS", + "Sending CLOSE_RQ", + "Sending TAGGED_MSG", + "Sending P2P_TAGGED_MSG", + "Sending MSG", + "Sending P2P_MSG", + "Sending ADR_AD", + "Sending ADR_QR", + // Receiving messages + "Receiving ACK", + "Receiving FAILED", + "Receiving TIMESTAMP", + "Receiving NET", + "Receiving LTC", + "Receiving STOP_REQ", + "Receiving STOP_REQ_REP", + "Receiving STOP_GRN", + "Receiving FED_ID", + "Receiving PTAG", + "Receiving TAG", + "Receiving REJECT", + "Receiving RESIGN", + "Receiving PORT_ABS", + "Receiving CLOSE_RQ", + "Receiving TAGGED_MSG", + "Receiving P2P_TAGGED_MSG", + "Receiving MSG", + "Receiving P2P_MSG", + "Receiving ADR_AD", + "Receiving ADR_QR", + "Receiving UNIDENTIFIED", +}; + /** * Function to be invoked upon exiting. */ diff --git a/util/tracing/trace_util.h b/util/tracing/trace_util.h index 67d3c705b..2521cb2f3 100644 --- a/util/tracing/trace_util.h +++ b/util/tracing/trace_util.h @@ -33,6 +33,12 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "reactor.h" #include "trace.h" +/** + * String description of event types. + */ +extern const char* trace_event_names[]; + + /** Macro to use when access to trace file fails. */ #define _LF_TRACE_FAILURE(trace_file) \ do { \ From ccb47404bb5a245be622464de5e7b5b3f0a91629 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 09:59:04 +0100 Subject: [PATCH 23/95] Core-lib does not have to be a Zephyr lib --- core/CMakeLists.txt | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 72eab35c5..9621497d6 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -49,18 +49,8 @@ endif() list(JOIN REACTORC_SOURCES ", " PRINTABLE_SOURCE_LIST) message(STATUS "Including the following sources: " ${PRINTABLE_SOURCE_LIST}) -# Create the reactor-c library. If we are targeting Zephyr we have to use the -# Zephyr Cmake extension to create the library and add the sources. -if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - message("--- Building Zephyr library") - zephyr_library_named(reactor-c) - zephyr_library_sources(${REACTORC_SOURCES}) - zephyr_library_link_libraries(kernel) -else() - add_library(reactor-c) - target_sources(reactor-c PRIVATE ${REACTORC_SOURCES}) -endif() - +add_library(reactor-c) +target_sources(reactor-c PRIVATE ${REACTORC_SOURCES}) lf_enable_compiler_warnings(reactor-c) if (DEFINED LF_TRACE) From 94a9bc9cc684615d20c090be9e179c330b9728dc Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 09:59:17 +0100 Subject: [PATCH 24/95] Turn of -Werror for Zephyr for now --- core/lf_utils.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/lf_utils.cmake b/core/lf_utils.cmake index 226f0760d..0dcdcaaa1 100644 --- a/core/lf_utils.cmake +++ b/core/lf_utils.cmake @@ -3,6 +3,8 @@ function(lf_enable_compiler_warnings target) target_compile_options(${target} PRIVATE /W4) elseif(APPLE) target_compile_options(${target} PRIVATE -Wall) + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") + target_compile_options(${target} PRIVATE -Wall -Wextra) else() target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror) endif() From a7534cc1b726acd9cb83e724d55968d5045ea1cd Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 10:07:06 +0100 Subject: [PATCH 25/95] Fix Cmake issue for Zephyr --- platform/impl/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/impl/CMakeLists.txt b/platform/impl/CMakeLists.txt index df24aac27..eadea7764 100644 --- a/platform/impl/CMakeLists.txt +++ b/platform/impl/CMakeLists.txt @@ -1,7 +1,7 @@ set(LF_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/platform.c) -if(PLATFORM_ZEPHYR) +if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") message("--- Building Zephyr library") zephyr_library_named(lf-platform-impl) zephyr_library_sources(${LF_PLATFORM_FILES}) From d074769e57d07fcc7c97631680424775d3e11e16 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 15:00:13 +0100 Subject: [PATCH 26/95] Remove the unuused `is_interval_start` from the tracing API --- core/tracepoint.c | 14 ++++---------- include/core/tracepoint.h | 18 ++++++++---------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/core/tracepoint.c b/core/tracepoint.c index 24b2f2434..43005a073 100644 --- a/core/tracepoint.c +++ b/core/tracepoint.c @@ -61,7 +61,7 @@ int register_user_trace_event(void* self, char* description) { } void call_tracepoint(int event_type, void* reactor, tag_t tag, int worker, int src_id, int dst_id, - instant_t* physical_time, trigger_t* trigger, interval_t extra_delay, bool is_interval_start) { + instant_t* physical_time, trigger_t* trigger, interval_t extra_delay) { instant_t local_time; if (physical_time == NULL) { local_time = lf_time_physical(); @@ -97,7 +97,7 @@ void tracepoint_schedule(environment_t* env, trigger_t* trigger, interval_t extr // This is OK because it is called only while holding the mutex lock. // True argument specifies to record physical time as late as possible, when // the event is already on the event queue. - call_tracepoint(schedule_called, reactor, env->current_tag, -1, 0, 0, NULL, trigger, extra_delay, true); + call_tracepoint(schedule_called, reactor, env->current_tag, -1, 0, 0, NULL, trigger, extra_delay); } /** @@ -119,7 +119,7 @@ void tracepoint_user_event(void* self, char* description) { // There will be a performance hit for this. LF_ASSERT(self, "A pointer to the self struct is needed to trace an event"); environment_t* env = ((self_base_t*)self)->environment; - call_tracepoint(user_event, description, env->current_tag, -1, -1, -1, NULL, NULL, 0, false); + call_tracepoint(user_event, description, env->current_tag, -1, -1, -1, NULL, NULL, 0); } /** @@ -144,7 +144,7 @@ void tracepoint_user_value(void* self, char* description, long long value) { // because multiple reactions might be calling the same tracepoint function. // There will be a performance hit for this. environment_t* env = ((self_base_t*)self)->environment; - call_tracepoint(user_value, description, env->current_tag, -1, -1, -1, NULL, NULL, value, false); + call_tracepoint(user_value, description, env->current_tag, -1, -1, -1, NULL, NULL, value); } //////////////////////////////////////////////////////////// @@ -169,7 +169,6 @@ void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - true // is_interval_start ); } @@ -191,7 +190,6 @@ void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* t NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - false // is_interval_start ); } @@ -213,7 +211,6 @@ void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int p NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - true // is_interval_start ); } @@ -235,7 +232,6 @@ void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - false // is_interval_start ); } #endif // FEDERATED @@ -262,7 +258,6 @@ void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - true // is_interval_start ); } @@ -283,7 +278,6 @@ void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* t NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, 0, // interval_t extra_delay - false // is_interval_start ); } diff --git a/include/core/tracepoint.h b/include/core/tracepoint.h index a91f34e4a..c43763a07 100644 --- a/include/core/tracepoint.h +++ b/include/core/tracepoint.h @@ -137,7 +137,7 @@ typedef struct trace_record_t { * argument is currently unused) */ void call_tracepoint(int event_type, void* reactor, tag_t tag, int worker, int src_id, int dst_id, - instant_t* physical_time, trigger_t* trigger, interval_t extra_delay, bool is_interval_start); + instant_t* physical_time, trigger_t* trigger, interval_t extra_delay); /** * Register a trace object. @@ -166,8 +166,7 @@ int register_user_trace_event(void* self, char* description); * @param worker The thread number of the worker thread or 0 for single-threaded execution. */ #define tracepoint_reaction_starts(env, reaction, worker) \ - call_tracepoint(reaction_starts, reaction->self, env->current_tag, worker, worker, reaction->number, NULL, NULL, 0, \ - true) + call_tracepoint(reaction_starts, reaction->self, env->current_tag, worker, worker, reaction->number, NULL, NULL, 0) /** * Trace the end of a reaction execution. @@ -176,8 +175,7 @@ int register_user_trace_event(void* self, char* description); * @param worker The thread number of the worker thread or 0 for single-threaded execution. */ #define tracepoint_reaction_ends(env, reaction, worker) \ - call_tracepoint(reaction_ends, reaction->self, env->current_tag, worker, worker, reaction->number, NULL, NULL, 0, \ - false) + call_tracepoint(reaction_ends, reaction->self, env->current_tag, worker, worker, reaction->number, NULL, NULL, 0) /** * Trace a call to schedule. @@ -219,7 +217,7 @@ void tracepoint_user_value(void* self, char* description, long long value); * @param worker The thread number of the worker thread or 0 for single-threaded execution. */ #define tracepoint_worker_wait_starts(env, worker) \ - call_tracepoint(worker_wait_starts, NULL, env->current_tag, worker, worker, -1, NULL, NULL, 0, true) + call_tracepoint(worker_wait_starts, NULL, env->current_tag, worker, worker, -1, NULL, NULL, 0) /** * Trace the end of a worker waiting for something to change on the event or reaction queue. @@ -227,7 +225,7 @@ void tracepoint_user_value(void* self, char* description, long long value); * @param worker The thread number of the worker thread or 0 for single-threaded execution. */ #define tracepoint_worker_wait_ends(env, worker) \ - call_tracepoint(worker_wait_ends, NULL, env->current_tag, worker, worker, -1, NULL, NULL, 0, false) + call_tracepoint(worker_wait_ends, NULL, env->current_tag, worker, worker, -1, NULL, NULL, 0) /** * Trace the start of the scheduler waiting for logical time to advance or an event to @@ -235,7 +233,7 @@ void tracepoint_user_value(void* self, char* description, long long value); * @param trace The trace object. */ #define tracepoint_scheduler_advancing_time_starts(env) \ - call_tracepoint(scheduler_advancing_time_starts, NULL, env->current_tag, -1, -1, -1, NULL, NULL, 0, true); + call_tracepoint(scheduler_advancing_time_starts, NULL, env->current_tag, -1, -1, -1, NULL, NULL, 0); /** * Trace the end of the scheduler waiting for logical time to advance or an event to @@ -243,7 +241,7 @@ void tracepoint_user_value(void* self, char* description, long long value); * @param trace The trace object. */ #define tracepoint_scheduler_advancing_time_ends(env) \ - call_tracepoint(scheduler_advancing_time_ends, NULL, env->current_tag, -1, -1, -1, NULL, NULL, 0, false) + call_tracepoint(scheduler_advancing_time_ends, NULL, env->current_tag, -1, -1, -1, NULL, NULL, 0) /** * Trace the occurrence of a deadline miss. @@ -253,7 +251,7 @@ void tracepoint_user_value(void* self, char* description, long long value); */ #define tracepoint_reaction_deadline_missed(env, reaction, worker) \ call_tracepoint(reaction_deadline_missed, reaction->self, env->current_tag, worker, worker, reaction->number, NULL, \ - NULL, 0, false) + NULL, 0) /** * @brief Check if the tracing library is compatible with the current version From c2706b9004265e92b5702ffcdccc30e45a2eb96c Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 15:00:44 +0100 Subject: [PATCH 27/95] Format --- trace/impl/include/trace_impl.h | 2 +- trace/impl/src/trace_impl.c | 6 +++--- util/tracing/trace_util.h | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/trace/impl/include/trace_impl.h b/trace/impl/include/trace_impl.h index 2ac6d51f5..779a7be4a 100644 --- a/trace/impl/include/trace_impl.h +++ b/trace/impl/include/trace_impl.h @@ -23,7 +23,7 @@ typedef struct trace_t { * which will create a significant pause in the calling thread. */ trace_record_nodeps_t** _lf_trace_buffer; - size_t * _lf_trace_buffer_size; + size_t* _lf_trace_buffer_size; /** The number of trace buffers allocated when tracing starts. */ size_t _lf_number_of_trace_buffers; diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index c372e71fd..ea6c85182 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -137,7 +137,7 @@ static void start_trace(trace_t* trace, int max_num_local_threads) { trace->_lf_trace_buffer = (trace_record_nodeps_t**)malloc(sizeof(trace_record_nodeps_t*) * (trace->_lf_number_of_trace_buffers + 1)); trace->_lf_trace_buffer++; // the buffer at index -1 is a fallback for user threads. - for (int i = -1; i < (int) trace->_lf_number_of_trace_buffers; i++) { + for (int i = -1; i < (int)trace->_lf_number_of_trace_buffers; i++) { trace->_lf_trace_buffer[i] = (trace_record_nodeps_t*)malloc(sizeof(trace_record_nodeps_t) * TRACE_BUFFER_CAPACITY); } // Array of counters that track the size of each trace record (per thread). @@ -169,7 +169,7 @@ static void stop_trace_locked(trace_t* trace) { // Trace was already stopped. Nothing to do. return; } - for (int i = -1; i < (int) trace->_lf_number_of_trace_buffers; i++) { + for (int i = -1; i < (int)trace->_lf_number_of_trace_buffers; i++) { // Flush the buffer if it has data. LF_PRINT_DEBUG("Trace buffer %d has %zu records.", i, trace->_lf_trace_buffer_size[i]); if (trace->_lf_trace_buffer_size && trace->_lf_trace_buffer_size[i] > 0) { @@ -231,7 +231,7 @@ void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { // Therefore we should fall back to using a mutex. lf_platform_mutex_lock(trace_mutex); } - if (((size_t) tid) > trace._lf_number_of_trace_buffers) { + if (((size_t)tid) > trace._lf_number_of_trace_buffers) { lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%zu)", tid, trace._lf_number_of_trace_buffers); } diff --git a/util/tracing/trace_util.h b/util/tracing/trace_util.h index 2521cb2f3..089e57ee1 100644 --- a/util/tracing/trace_util.h +++ b/util/tracing/trace_util.h @@ -38,7 +38,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ extern const char* trace_event_names[]; - /** Macro to use when access to trace file fails. */ #define _LF_TRACE_FAILURE(trace_file) \ do { \ From 0170ae79cff211791a4ec0b1ccecb874e063c98b Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 15:04:36 +0100 Subject: [PATCH 28/95] Fix typos --- core/tracepoint.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/tracepoint.c b/core/tracepoint.c index 43005a073..b121be8da 100644 --- a/core/tracepoint.c +++ b/core/tracepoint.c @@ -168,7 +168,7 @@ void tracepoint_federate_to_rti(trace_event_t event_type, int fed_id, tag_t* tag -1, // int dst_id, NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } @@ -189,7 +189,7 @@ void tracepoint_federate_from_rti(trace_event_t event_type, int fed_id, tag_t* t -1, // int dst_id, NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } @@ -210,7 +210,7 @@ void tracepoint_federate_to_federate(trace_event_t event_type, int fed_id, int p partner_id, // int dst_id, NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } @@ -231,7 +231,7 @@ void tracepoint_federate_from_federate(trace_event_t event_type, int fed_id, int partner_id, // int dst_id, NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } #endif // FEDERATED @@ -257,7 +257,7 @@ void tracepoint_rti_to_federate(trace_event_t event_type, int fed_id, tag_t* tag fed_id, // int dst_id NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } @@ -277,7 +277,7 @@ void tracepoint_rti_from_federate(trace_event_t event_type, int fed_id, tag_t* t fed_id, // int dst_id NULL, // instant_t* physical_time (will be generated) NULL, // trigger_t* trigger, - 0, // interval_t extra_delay + 0 // interval_t extra_delay ); } From 00e21ac5c3416b68fa3d1a4f81a2a5bd3b47b2ab Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 15:12:07 +0100 Subject: [PATCH 29/95] Fix if condition in lf_tracing_tracepoint --- trace/impl/src/trace_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index ea6c85182..28534364b 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -231,7 +231,7 @@ void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { // Therefore we should fall back to using a mutex. lf_platform_mutex_lock(trace_mutex); } - if (((size_t)tid) > trace._lf_number_of_trace_buffers) { + if (tid > (int)trace._lf_number_of_trace_buffers) { lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%zu)", tid, trace._lf_number_of_trace_buffers); } From b3067e58e4849e6f563b11c4759c4775fb0737e1 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 15:53:37 +0100 Subject: [PATCH 30/95] Fix warnings in GEDF scheduler --- core/threaded/scheduler_GEDF_NP.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/threaded/scheduler_GEDF_NP.c b/core/threaded/scheduler_GEDF_NP.c index 0f3d971d5..d590adecb 100644 --- a/core/threaded/scheduler_GEDF_NP.c +++ b/core/threaded/scheduler_GEDF_NP.c @@ -155,7 +155,8 @@ void _lf_scheduler_try_advance_tag_and_distribute(lf_scheduler_t* scheduler) { void _lf_sched_wait_for_work(lf_scheduler_t* scheduler, size_t worker_number) { // Increment the number of idle workers by 1 and check if this is the last // worker thread to become idle. - if (lf_atomic_add_fetch32((int32_t*)&scheduler->number_of_idle_workers, 1) == scheduler->number_of_workers) { + if (((size_t)lf_atomic_add_fetch32((int32_t*)&scheduler->number_of_idle_workers, 1)) == + scheduler->number_of_workers) { // Last thread to go idle LF_PRINT_DEBUG("Scheduler: Worker %zu is the last idle thread.", worker_number); // Call on the scheduler to distribute work or advance tag. @@ -279,6 +280,7 @@ reaction_t* lf_sched_get_ready_reaction(lf_scheduler_t* scheduler, int worker_nu * @param done_reaction The reaction that is done. */ void lf_sched_done_with_reaction(size_t worker_number, reaction_t* done_reaction) { + (void)worker_number; if (!lf_atomic_bool_compare_and_swap32((int32_t*)&done_reaction->status, queued, inactive)) { lf_print_error_and_exit("Unexpected reaction status: %d. Expected %d.", done_reaction->status, queued); } @@ -301,6 +303,7 @@ void lf_sched_done_with_reaction(size_t worker_number, reaction_t* done_reaction * worker number does not make sense (e.g., the caller is not a worker thread). */ void lf_scheduler_trigger_reaction(lf_scheduler_t* scheduler, reaction_t* reaction, int worker_number) { + (void)worker_number; if (reaction == NULL || !lf_atomic_bool_compare_and_swap32((int32_t*)&reaction->status, inactive, queued)) { return; } From 914d4caf7208150d2fe7c0573548617f839e61fe Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 16:37:21 +0100 Subject: [PATCH 31/95] Fix warnings in adaptive scheduler --- core/threaded/scheduler_adaptive.c | 42 +++++++++++++----------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/core/threaded/scheduler_adaptive.c b/core/threaded/scheduler_adaptive.c index 99f50c043..4b0843028 100644 --- a/core/threaded/scheduler_adaptive.c +++ b/core/threaded/scheduler_adaptive.c @@ -293,13 +293,13 @@ static void worker_states_init(lf_scheduler_t* scheduler, size_t number_of_worke worker_states->worker_conds = (lf_cond_t*)malloc(sizeof(lf_cond_t) * num_conds); worker_states->cumsum_of_worker_group_sizes = (size_t*)calloc(num_conds, sizeof(size_t)); worker_states->mutex_held = (bool*)calloc(number_of_workers, sizeof(bool)); - for (int i = 0; i < number_of_workers; i++) { + for (size_t i = 0; i < number_of_workers; i++) { worker_states->cumsum_of_worker_group_sizes[cond_of(i)]++; } - for (int i = 1; i < num_conds; i++) { + for (size_t i = 1; i < num_conds; i++) { worker_states->cumsum_of_worker_group_sizes[i] += worker_states->cumsum_of_worker_group_sizes[i - 1]; } - for (int i = 0; i < num_conds; i++) { + for (size_t i = 0; i < num_conds; i++) { LF_COND_INIT(worker_states->worker_conds + i, &scheduler->env->mutex); } worker_states->num_loose_threads = scheduler->number_of_workers; @@ -322,7 +322,7 @@ static void worker_states_free(lf_scheduler_t* scheduler) { static void worker_states_awaken_locked(lf_scheduler_t* scheduler, size_t worker, size_t num_to_awaken) { worker_states_t* worker_states = scheduler->custom_data->worker_states; worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; - assert(num_to_awaken <= worker_assignments->max_num_workers); + LF_ASSERT(num_to_awaken <= worker_assignments->max_num_workers, "Sched requested to wake too many workers"); if ((worker == 0) && (num_to_awaken <= 1)) { worker_states->num_loose_threads = 1; return; @@ -339,7 +339,7 @@ static void worker_states_awaken_locked(lf_scheduler_t* scheduler, size_t worker worker_states->num_loose_threads += worker >= worker_states->num_loose_threads; worker_states->num_awakened = worker_states->num_loose_threads; scheduler->custom_data->level_counter++; - for (int cond = 0; cond <= max_cond; cond++) { + for (size_t cond = 0; cond <= max_cond; cond++) { lf_cond_broadcast(worker_states->worker_conds + cond); } } @@ -348,8 +348,8 @@ static void worker_states_awaken_locked(lf_scheduler_t* scheduler, size_t worker static void worker_states_lock(lf_scheduler_t* scheduler, size_t worker) { worker_states_t* worker_states = scheduler->custom_data->worker_states; worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; - assert(worker_states->num_loose_threads > 0); - assert(worker_states->num_loose_threads <= worker_assignments->max_num_workers); + LF_ASSERT(worker_states->num_loose_threads > 0, "Sched: No loose threads"); + LF_ASSERT(worker_states->num_loose_threads <= worker_assignments->max_num_workers, "Sched: Too many loose threads"); size_t lt = worker_states->num_loose_threads; if (lt > 1 || !fast) { // FIXME: Lock should be partially optimized out even when !fast LF_MUTEX_LOCK(&scheduler->env->mutex); @@ -377,9 +377,7 @@ static void worker_states_unlock(lf_scheduler_t* scheduler, size_t worker) { static bool worker_states_finished_with_level_locked(lf_scheduler_t* scheduler, size_t worker) { worker_states_t* worker_states = scheduler->custom_data->worker_states; worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; - assert(worker >= 0); - assert(worker_states->num_loose_threads > 0); - assert(worker_assignments->num_reactions_by_worker[worker] != 1); + LF_ASSERT(worker_assignments->num_reactions_by_worker[worker] != 1, "Sched: Current worker not assigned"); assert(((int64_t)worker_assignments->num_reactions_by_worker[worker]) <= 0); // Why use an atomic operation when we are supposed to be "as good as locked"? Because I took a // shortcut, and the shortcut was imperfect. @@ -401,8 +399,8 @@ static bool worker_states_finished_with_level_locked(lf_scheduler_t* scheduler, static void worker_states_sleep_and_unlock(lf_scheduler_t* scheduler, size_t worker, size_t level_counter_snapshot) { worker_states_t* worker_states = scheduler->custom_data->worker_states; worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; - assert(worker < worker_assignments->max_num_workers); - assert(worker_states->num_loose_threads <= worker_assignments->max_num_workers); + LF_ASSERT(worker < worker_assignments->max_num_workers, "Sched: Invalid worker"); + LF_ASSERT(worker_states->num_loose_threads <= worker_assignments->max_num_workers, "Sched: Too many loose threads"); if (!worker_states->mutex_held[worker]) { LF_MUTEX_LOCK(&scheduler->env->mutex); } @@ -413,7 +411,8 @@ static void worker_states_sleep_and_unlock(lf_scheduler_t* scheduler, size_t wor lf_cond_wait(worker_states->worker_conds + cond); } while (level_counter_snapshot == scheduler->custom_data->level_counter || worker >= worker_states->num_awakened); } - assert(!worker_states->mutex_held[worker]); // This thread holds the mutex, but it did not report that. + LF_ASSERT(!worker_states->mutex_held[worker], + "Sched: Worker doesnt hold the mutex"); // This thread holds the mutex, but it did not report that. LF_MUTEX_UNLOCK(&scheduler->env->mutex); } @@ -423,7 +422,6 @@ static void worker_states_sleep_and_unlock(lf_scheduler_t* scheduler, size_t wor */ static void advance_level_and_unlock(lf_scheduler_t* scheduler, size_t worker) { worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; - worker_states_t* worker_states = scheduler->custom_data->worker_states; size_t max_level = worker_assignments->num_levels - 1; while (true) { if (worker_assignments->current_level == max_level) { @@ -443,7 +441,7 @@ static void advance_level_and_unlock(lf_scheduler_t* scheduler, size_t worker) { size_t total_num_reactions = get_num_reactions(scheduler); if (total_num_reactions) { size_t num_workers_to_awaken = LF_MIN(total_num_reactions, worker_assignments->num_workers); - assert(num_workers_to_awaken > 0); + LF_ASSERT(num_workers_to_awaken > 0, ""); worker_states_awaken_locked(scheduler, worker, num_workers_to_awaken); worker_states_unlock(scheduler, worker); return; @@ -476,7 +474,7 @@ static void possible_nums_workers_init(lf_scheduler_t* scheduler) { data_collection->possible_nums_workers = (size_t*)malloc(pnw_length * sizeof(size_t)); temp = 1; data_collection->possible_nums_workers[0] = 0; - for (int i = 1; i < pnw_length; i++) { + for (size_t i = 1; i < pnw_length; i++) { data_collection->possible_nums_workers[i] = temp; temp *= 2; } @@ -492,7 +490,7 @@ static void possible_nums_workers_init(lf_scheduler_t* scheduler) { * would like to optimize. */ static int get_jitter(size_t current_state, interval_t execution_time) { - static const size_t parallelism_cost_max = 114688; + static const interval_t parallelism_cost_max = 114688; // The following handles the case where the current level really is just fluff: // No parallelism needed, no work to be done. if (execution_time < 16384 && current_state == 1) @@ -595,7 +593,6 @@ static size_t restrict_to_range(size_t start_inclusive, size_t end_inclusive, si */ static void compute_number_of_workers(lf_scheduler_t* scheduler, size_t* num_workers_by_level, size_t* max_num_workers_by_level, bool jitter) { - worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; data_collection_t* data_collection = scheduler->custom_data->data_collection; for (size_t level = 0; level < data_collection->num_levels; level++) { interval_t this_execution_time = @@ -603,7 +600,6 @@ static void compute_number_of_workers(lf_scheduler_t* scheduler, size_t* num_wor size_t ideal_number_of_workers; size_t max_reasonable_num_workers = max_num_workers_by_level[level]; ideal_number_of_workers = data_collection->execution_times_argmins[level]; - int range = 1; if (jitter) { ideal_number_of_workers = get_nums_workers_neighboring_state(scheduler, ideal_number_of_workers, this_execution_time); @@ -621,7 +617,6 @@ static void compute_number_of_workers(lf_scheduler_t* scheduler, size_t* num_wor */ static void compute_costs(lf_scheduler_t* scheduler, size_t* num_workers_by_level) { data_collection_t* data_collection = scheduler->custom_data->data_collection; - worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; for (size_t level = 0; level < data_collection->num_levels; level++) { interval_t score = data_collection->execution_times_by_num_workers_by_level[level][num_workers_by_level[level]]; if (!data_collection->execution_times_mins[level] | (score < data_collection->execution_times_mins[level]) | @@ -640,7 +635,6 @@ static void compute_costs(lf_scheduler_t* scheduler, size_t* num_workers_by_leve */ static void data_collection_end_tag(lf_scheduler_t* scheduler, size_t* num_workers_by_level, size_t* max_num_workers_by_level) { - worker_assignments_t* worker_assignments = scheduler->custom_data->worker_assignments; data_collection_t* data_collection = scheduler->custom_data->data_collection; if (data_collection->collecting_data && data_collection->start_times_by_level[0]) { compute_costs(scheduler, num_workers_by_level); @@ -716,13 +710,13 @@ reaction_t* lf_sched_get_ready_reaction(lf_scheduler_t* scheduler, int worker_nu } void lf_sched_done_with_reaction(size_t worker_number, reaction_t* done_reaction) { - assert(worker_number >= 0); - assert(done_reaction->status != inactive); + (void)worker_number; + LF_ASSERT(done_reaction->status != inactive, ""); done_reaction->status = inactive; } void lf_scheduler_trigger_reaction(lf_scheduler_t* scheduler, reaction_t* reaction, int worker_number) { - assert(worker_number >= -1); + LF_ASSERT(worker_number >= -1, "Sched: Invalid worker number"); if (!lf_atomic_bool_compare_and_swap32((int32_t*)&reaction->status, inactive, queued)) return; worker_assignments_put(scheduler, reaction); From 0e3668bd9ab20e5f2fd5aa3373aed8ab2886ce33 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 7 Mar 2024 16:55:04 +0100 Subject: [PATCH 32/95] Fix warnings in decentralized federations --- core/federated/federate.c | 23 +++++++++++++---------- logging/api/logging_macros.h | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index eab22304c..1805f86ab 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1047,7 +1047,7 @@ static void handle_tag_advance_grant(void) { */ static bool a_port_is_unknown(staa_t* staa_elem) { bool do_wait = false; - for (int j = 0; j < staa_elem->num_actions; ++j) { + for (size_t j = 0; j < staa_elem->num_actions; ++j) { if (staa_elem->actions[j]->trigger->status == unknown) { do_wait = true; break; @@ -1079,18 +1079,19 @@ static int id_of_action(lf_action_base_t* input_port_action) { */ #ifdef FEDERATED_DECENTRALIZED static void* update_ports_from_staa_offsets(void* args) { + (void)args; initialize_lf_thread_id(); if (staa_lst_size == 0) return NULL; // Nothing to do. // NOTE: Using only the top-level environment, which is the one that deals with network // input ports. environment_t* env; - int num_envs = _lf_get_environments(&env); + _lf_get_environments(&env); LF_MUTEX_LOCK(&env->mutex); while (1) { LF_PRINT_DEBUG("**** (update thread) starting"); tag_t tag_when_started_waiting = lf_tag(env); - for (int i = 0; i < staa_lst_size; ++i) { + for (size_t i = 0; i < staa_lst_size; ++i) { staa_t* staa_elem = staa_lst[i]; // The staa_elem is adjusted in the code generator to have subtracted the delay on the connection. // The list is sorted in increasing order of adjusted STAA offsets. @@ -1125,7 +1126,7 @@ static void* update_ports_from_staa_offsets(void* args) { lf_time_start()); */ - for (int j = 0; j < staa_elem->num_actions; ++j) { + for (size_t j = 0; j < staa_elem->num_actions; ++j) { lf_action_base_t* input_port_action = staa_elem->actions[j]; if (input_port_action->trigger->status == unknown) { input_port_action->trigger->status = absent; @@ -1157,7 +1158,7 @@ static void* update_ports_from_staa_offsets(void* args) { // it would be huge mistake to enter the wait for a new tag below because the // program will freeze. First, check whether any ports are unknown: bool port_unkonwn = false; - for (int i = 0; i < staa_lst_size; ++i) { + for (size_t i = 0; i < staa_lst_size; ++i) { staa_t* staa_elem = staa_lst[i]; if (a_port_is_unknown(staa_elem)) { port_unkonwn = true; @@ -2095,7 +2096,7 @@ void lf_enqueue_port_absent_reactions(environment_t* env) { } void* lf_handle_p2p_connections_from_federates(void* env_arg) { - assert(env_arg); + LF_ASSERT_NON_NULL(env_arg); size_t received_federates = 0; // Allocate memory to store thread IDs. _fed.inbound_socket_listeners = (lf_thread_t*)calloc(_fed.number_of_inbound_p2p_connections, sizeof(lf_thread_t)); @@ -2226,8 +2227,8 @@ parse_rti_code_t lf_parse_rti_addr(const char* rti_addr) { } if (rti_addr_info.has_host) { if (validate_host(rti_addr_info.rti_host_str)) { - char* rti_host = (char*)calloc(256, sizeof(char)); - strncpy(rti_host, rti_addr_info.rti_host_str, 255); + char* rti_host = (char*)calloc(257, sizeof(char)); + strncpy(rti_host, rti_addr_info.rti_host_str, 256); federation_metadata.rti_host = rti_host; } else { return INVALID_HOST; @@ -2242,8 +2243,8 @@ parse_rti_code_t lf_parse_rti_addr(const char* rti_addr) { } if (rti_addr_info.has_user) { if (validate_user(rti_addr_info.rti_user_str)) { - char* rti_user = (char*)calloc(256, sizeof(char)); - strncpy(rti_user, rti_addr_info.rti_user_str, 255); + char* rti_user = (char*)calloc(257, sizeof(char)); + strncpy(rti_user, rti_addr_info.rti_user_str, 256); federation_metadata.rti_user = rti_user; } else { return INVALID_USER; @@ -2656,6 +2657,8 @@ bool lf_update_max_level(tag_t tag, bool is_provisional) { int prev_max_level_allowed_to_advance = max_level_allowed_to_advance; max_level_allowed_to_advance = INT_MAX; #ifdef FEDERATED_DECENTRALIZED + (void)tag; + (void)is_provisional; size_t action_table_size = _lf_action_table_size; lf_action_base_t** action_table = _lf_action_table; #else diff --git a/logging/api/logging_macros.h b/logging/api/logging_macros.h index 73939f576..6f7ea1eba 100644 --- a/logging/api/logging_macros.h +++ b/logging/api/logging_macros.h @@ -76,7 +76,7 @@ #if defined(NDEBUG) #define LF_ASSERT(condition, format, ...) (void)(condition) #define LF_ASSERTN(condition, format, ...) (void)(condition) -#define LF_ASSERT_NON_NULL(pointer) +#define LF_ASSERT_NON_NULL(pointer) (void)(pointer) #else #define LF_ASSERT(condition, format, ...) \ do { \ From 898fa1cc934b84f7f3175272e818fc93b74d247b Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Thu, 7 Mar 2024 17:24:06 -0700 Subject: [PATCH 33/95] Use pqueue_tag instead of pqueue for event_q and simplfy scehduling non-zero microsteps events --- core/environment.c | 13 +- core/federated/federate.c | 29 ++- core/modal_models/modes.c | 10 +- core/reactor.c | 24 +- core/reactor_common.c | 376 +++++++++++++++---------------- core/threaded/reactor_threaded.c | 38 ++-- core/utils/pqueue.c | 8 +- include/core/environment.h | 2 +- include/core/lf_types.h | 8 +- include/core/reactor_common.h | 13 +- lib/schedule.c | 35 +-- 11 files changed, 278 insertions(+), 278 deletions(-) diff --git a/core/environment.c b/core/environment.c index 7189090e4..bf3bb9e02 100644 --- a/core/environment.c +++ b/core/environment.c @@ -165,9 +165,9 @@ void environment_free(environment_t* env) { free(env->reset_reactions); free(env->is_present_fields); free(env->is_present_fields_abbreviated); - pqueue_free(env->event_q); + pqueue_tag_free(env->event_q); pqueue_free(env->recycle_q); - pqueue_free(env->next_q); + // pqueue_free(env->next_q); environment_free_threaded(env); environment_free_single_threaded(env); @@ -241,12 +241,13 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke env->_lf_handle = 1; // Initialize our priority queues. - env->event_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_reverse_order, get_event_time, get_event_position, - set_event_position, event_matches, print_event); + // env->event_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_reverse_order, get_event_time, get_event_position, + // set_event_position, event_matches, print_event); + env->event_q = pqueue_tag_init(INITIAL_EVENT_QUEUE_SIZE); env->recycle_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, set_event_position, event_matches, print_event); - env->next_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, - set_event_position, event_matches, print_event); + // env->next_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, + // set_event_position, event_matches, print_event); // Initialize functionality depending on target properties. environment_init_threaded(env, num_workers); diff --git a/core/federated/federate.c b/core/federated/federate.c index edc8c5338..90e6ed16f 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1252,8 +1252,8 @@ static void handle_provisional_tag_advance_grant() { // (which it should be). Do not do this if the federate has not fully // started yet. - instant_t dummy_event_time = PTAG.time; - microstep_t dummy_event_relative_microstep = PTAG.microstep; + // instant_t dummy_event_time = PTAG.time; + // microstep_t dummy_event_microstep = PTAG.microstep; if (lf_tag_compare(env->current_tag, PTAG) == 0) { // The current tag can equal the PTAG if we are at the start time @@ -1278,22 +1278,18 @@ static void handle_provisional_tag_advance_grant() { // Nothing more to do. LF_MUTEX_UNLOCK(&env->mutex); return; - } else if (PTAG.time == env->current_tag.time) { - // We now know env->current_tag < PTAG, but the times are equal. - // Adjust the microstep for scheduling the dummy event. - dummy_event_relative_microstep -= env->current_tag.microstep; } // We now know env->current_tag < PTAG. - if (dummy_event_time != FOREVER) { - // Schedule a dummy event at the specified time and (relative) microstep. + if (PTAG.time != FOREVER) { + // Schedule a dummy event at the specified tag. LF_PRINT_DEBUG("At tag " PRINTF_TAG ", inserting into the event queue a dummy event " - "with time " PRINTF_TIME " and (relative) microstep " PRINTF_MICROSTEP ".", - env->current_tag.time - start_time, env->current_tag.microstep, dummy_event_time - start_time, - dummy_event_relative_microstep); - // Dummy event points to a NULL trigger and NULL real event. - event_t* dummy = _lf_create_dummy_events(env, NULL, dummy_event_time, NULL, dummy_event_relative_microstep); - pqueue_insert(env->event_q, dummy); + "with time " PRINTF_TIME " and microstep " PRINTF_MICROSTEP ".", + env->current_tag.time - start_time, env->current_tag.microstep, PTAG.time - start_time, + PTAG.microstep); + // Dummy event points to a NULL trigger. + event_t* dummy = _lf_create_dummy_events(env, NULL, PTAG); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) dummy); } LF_MUTEX_UNLOCK(&env->mutex); @@ -2408,8 +2404,9 @@ tag_t lf_send_next_event_tag(environment_t* env, tag_t tag, bool wait_for_reply) // Create a dummy event that will force this federate to advance time and subsequently // enable progress for downstream federates. Increment the time by ADVANCE_MESSAGE_INTERVAL // to prevent too frequent dummy events. - event_t* dummy = _lf_create_dummy_events(env, NULL, tag.time + ADVANCE_MESSAGE_INTERVAL, NULL, 0); - pqueue_insert(env->event_q, dummy); + tag_t dummy_event_tag = (tag_t) {.time = tag.time + ADVANCE_MESSAGE_INTERVAL, .microstep = tag.microstep}; + event_t* dummy = _lf_create_dummy_events(env, NULL, dummy_event_tag); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) dummy); } LF_PRINT_DEBUG("Inserted a dummy event for logical time " PRINTF_TIME ".", tag.time - lf_time_start()); diff --git a/core/modal_models/modes.c b/core/modal_models/modes.c index e6e6f5d95..5acf6a0b5 100644 --- a/core/modal_models/modes.c +++ b/core/modal_models/modes.c @@ -56,8 +56,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Forward declaration of functions and variables supplied by reactor_common.c void _lf_trigger_reaction(environment_t* env, reaction_t* reaction, int worker_number); -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, instant_t time, event_t* next, - microstep_t offset); +event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag); // ---------------------------------------------------------------------------- @@ -490,7 +489,7 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] // Retract all events from the event queue that are associated with now inactive modes if (env->event_q != NULL) { - size_t q_size = pqueue_size(env->event_q); + size_t q_size = pqueue_tag_size(env->event_q); if (q_size > 0) { event_t** delayed_removal = (event_t**)calloc(q_size, sizeof(event_t*)); size_t delayed_removal_count = 0; @@ -509,7 +508,7 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] LF_PRINT_DEBUG("Modes: Pulling %zu events from the event queue to suspend them. %d events are now suspended.", delayed_removal_count, _lf_suspended_events_num); for (size_t i = 0; i < delayed_removal_count; i++) { - pqueue_remove(env->event_q, delayed_removal[i]); + pqueue_tag_remove(env->event_q, (pqueue_tag_element_t*) (delayed_removal[i])); } free(delayed_removal); @@ -519,7 +518,8 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] if (env->modes->triggered_reactions_request) { // Insert a dummy event in the event queue for the next microstep to make // sure startup/reset reactions (if any) are triggered as soon as possible. - pqueue_insert(env->event_q, _lf_create_dummy_events(env, NULL, env->current_tag.time, NULL, 1)); + tag_t dummy_event_tag = (tag_t) {.time = env->current_tag.time, .microstep = 1}; + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) _lf_create_dummy_events(env, NULL, dummy_event_tag)); } } } diff --git a/core/reactor.c b/core/reactor.c index 8bf3b9460..d53dd2550 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -209,7 +209,7 @@ int next(environment_t* env) { // Enter the critical section and do not leave until we have // determined which tag to commit to and start invoking reactions for. LF_CRITICAL_SECTION_ENTER(env); - event_t* event = (event_t*)pqueue_peek(env->event_q); + event_t* event = (event_t*)pqueue_tag_peek(env->event_q); // pqueue_dump(event_q, event_q->prt); // If there is no next event and -keepalive has been specified // on the command line, then we will wait the maximum time possible. @@ -220,13 +220,13 @@ int next(environment_t* env) { lf_set_stop_tag(env, (tag_t){.time = env->current_tag.time, .microstep = env->current_tag.microstep + 1}); } } else { - next_tag.time = event->time; - // Deduce the microstep - if (next_tag.time == env->current_tag.time) { - next_tag.microstep = env->current_tag.microstep + 1; - } else { - next_tag.microstep = 0; - } + next_tag = event->base.tag; + // // Deduce the microstep + // if (next_tag.time == env->current_tag.time) { + // next_tag.microstep = env->current_tag.microstep + 1; + // } else { + // next_tag.microstep = 0; + // } } if (lf_is_tag_after_stop_tag(env, next_tag)) { @@ -234,10 +234,10 @@ int next(environment_t* env) { next_tag = env->stop_tag; } - LF_PRINT_LOG("Next event (elapsed) time is " PRINTF_TIME ".", next_tag.time - start_time); + LF_PRINT_LOG("Next event (elapsed) tag is " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep); // Wait until physical time >= event.time. int finished_sleep = wait_until(env, next_tag.time); - LF_PRINT_LOG("Next event (elapsed) time is " PRINTF_TIME ".", next_tag.time - start_time); + LF_PRINT_LOG("Next event (elapsed) tag is " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep); if (finished_sleep != 0) { LF_PRINT_DEBUG("***** wait_until was interrupted."); // Sleep was interrupted. This could happen when a physical action @@ -247,10 +247,10 @@ int next(environment_t* env) { LF_CRITICAL_SECTION_EXIT(env); return 1; } - // Advance current time to match that of the first event on the queue. + // Advance current tag to match that of the first event on the queue. // We can now leave the critical section. Any events that will be added // to the queue asynchronously will have a later tag than the current one. - _lf_advance_logical_time(env, next_tag.time); + _lf_advance_logical_tag(env, next_tag); // Trigger shutdown reactions if appropriate. if (lf_tag_compare(env->current_tag, env->stop_tag) >= 0) { diff --git a/core/reactor_common.c b/core/reactor_common.c index 6fc3d3824..a02d5cb04 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -230,19 +230,19 @@ void _lf_pop_events(environment_t* env) { _lf_handle_mode_triggered_reactions(env); #endif - event_t* event = (event_t*)pqueue_peek(env->event_q); - while (event != NULL && event->time == env->current_tag.time) { - event = (event_t*)pqueue_pop(env->event_q); + event_t* event = (event_t*)pqueue_tag_peek(env->event_q); + while (event != NULL && lf_tag_compare(event->base.tag, env->current_tag) == 0) { + event = (event_t*)pqueue_tag_pop(env->event_q); if (event->is_dummy) { LF_PRINT_DEBUG("Popped dummy event from the event queue."); - if (event->next != NULL) { - LF_PRINT_DEBUG("Putting event from the event queue for the next microstep."); - pqueue_insert(env->next_q, event->next); - } + // if (event->next != NULL) { + // LF_PRINT_DEBUG("Putting event from the event queue for the next microstep."); + // pqueue_insert(env->next_q, event->next); + // } lf_recycle_event(env, event); // Peek at the next event in the event queue. - event = (event_t*)pqueue_peek(env->event_q); + event = (event_t*)pqueue_tag_peek(env->event_q); continue; } @@ -328,25 +328,25 @@ void _lf_pop_events(environment_t* env) { // Mark the trigger present. event->trigger->status = present; - // If this event points to a next event, insert it into the next queue. - if (event->next != NULL) { - // Insert the next event into the next queue. - pqueue_insert(env->next_q, event->next); - } + // // If this event points to a next event, insert it into the next queue. + // if (event->next != NULL) { + // // Insert the next event into the next queue. + // pqueue_insert(env->next_q, event->next); + // } lf_recycle_event(env, event); - // Peek at the next event in the event queue. - event = (event_t*)pqueue_peek(env->event_q); + // // Peek at the next event in the event queue. + // event = (event_t*)pqueue_tag_peek(env->event_q); }; - LF_PRINT_DEBUG("There are %zu events deferred to the next microstep.", pqueue_size(env->next_q)); + // LF_PRINT_DEBUG("There are %zu events deferred to the next microstep.", pqueue_size(env->next_q)); - // After populating the reaction queue, see if there are things on the - // next queue to put back into the event queue. - while (pqueue_peek(env->next_q) != NULL) { - pqueue_insert(env->event_q, pqueue_pop(env->next_q)); - } + // // After populating the reaction queue, see if there are things on the + // // next queue to put back into the event queue. + // while (pqueue_peek(env->next_q) != NULL) { + // pqueue_insert(env->event_q, pqueue_pop(env->next_q)); + // } } event_t* lf_get_new_event(environment_t* env) { @@ -401,9 +401,9 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) { // Recycle event_t structs, if possible. event_t* e = lf_get_new_event(env); e->trigger = timer; - e->time = lf_time_logical(env) + delay; + e->base.tag = (tag_t) {.time = lf_time_logical(env) + delay, .microstep = 0}; // NOTE: No lock is being held. Assuming this only happens at startup. - pqueue_insert(env->event_q, e); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); tracepoint_schedule(env, timer, delay); // Trace even though schedule is not called. } @@ -462,38 +462,38 @@ void _lf_trigger_shutdown_reactions(environment_t* env) { void lf_recycle_event(environment_t* env, event_t* e) { assert(env != GLOBAL_ENVIRONMENT); - e->time = 0LL; + e->base.tag = (tag_t) {.time = 0LL, .microstep = 0}; + // e->time = 0LL; e->trigger = NULL; - e->pos = 0; + // e->pos = 0; e->token = NULL; e->is_dummy = false; #ifdef FEDERATED_DECENTRALIZED e->intended_tag = (tag_t){.time = NEVER, .microstep = 0u}; #endif - e->next = NULL; + // e->next = NULL; pqueue_insert(env->recycle_q, e); } -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, instant_t time, event_t* next, - microstep_t offset) { - event_t* first_dummy = lf_get_new_event(env); - event_t* dummy = first_dummy; - dummy->time = time; +event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag) { + event_t* dummy = lf_get_new_event(env); + dummy->base.tag = tag; + dummy->is_dummy = true; dummy->trigger = trigger; - while (offset > 0) { - if (offset == 1) { - dummy->next = next; - break; - } - dummy->next = lf_get_new_event(env); - dummy = dummy->next; - dummy->time = time; - dummy->is_dummy = true; - dummy->trigger = trigger; - offset--; - } - return first_dummy; + // while (offset > 0) { + // if (offset == 1) { + // dummy->next = next; + // break; + // } + // dummy->next = lf_get_new_event(env); + // dummy = dummy->next; + // dummy->time = time; + // dummy->is_dummy = true; + // dummy->trigger = trigger; + // offset--; + // } + return dummy; } void lf_replace_token(event_t* event, lf_token_t* token) { @@ -531,7 +531,7 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag event_t* e = lf_get_new_event(env); // Set the event time - e->time = tag.time; + e->base.tag = tag; tracepoint_schedule(env, trigger, tag.time - current_logical_tag.time); @@ -547,133 +547,135 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag e->intended_tag = trigger->intended_tag; #endif - event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, e); - if (found != NULL) { - if (tag.microstep == 0u) { - // The microstep is 0, which means that the event is being scheduled - // at a future time and at the beginning of the skip list of events - // at that time. - // In case the event is a dummy event - // convert it to a real event. - found->is_dummy = false; - switch (trigger->policy) { - case drop: - if (found->token != token) { - _lf_done_using(token); - } - lf_recycle_event(env, e); - return (0); - break; - case replace: - // Replace the payload of the event at the head with our - // current payload. - lf_replace_token(found, token); - lf_recycle_event(env, e); - return 0; - break; - default: - // Adding a microstep to the original - // intended tag. - if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = 1})) { - // Scheduling e will incur a microstep after the stop tag, - // which is illegal. - lf_recycle_event(env, e); - return 0; - } - if (found->next != NULL) { - lf_print_error("_lf_schedule_at_tag: in-order contract violated."); - return -1; - } - found->next = e; - } - } else { - // We are requesting a microstep greater than 0 - // where there is already an event for this trigger on the event queue. - // That event may itself be a dummy event for a real event that is - // also at a microstep greater than 0. - // We have to insert our event into the chain or append it - // to the end of the chain, depending on which microstep is lesser. - microstep_t microstep_of_found = 0; - if (tag.time == current_logical_tag.time) { - // This is a situation where the head of the queue - // is an event with microstep == current_microstep + 1 - // which should be reflected in our steps calculation. - microstep_of_found += current_logical_tag.microstep + 1; // Indicating that - // the found event - // is at this microstep. - } - // Follow the chain of events until the right point - // to insert the new event. - while (microstep_of_found < tag.microstep - 1) { - if (found->next == NULL) { - // The chain stops short of where we want to be. - // If it exactly one microstep short of where we want to be, - // then we don't need a dummy. Otherwise, we do. - microstep_t undershot_by = (tag.microstep - 1) - microstep_of_found; - if (undershot_by > 0) { - found->next = _lf_create_dummy_events(env, trigger, tag.time, e, undershot_by); - } else { - found->next = e; - } - return 1; - } - found = found->next; - microstep_of_found++; - } - // At this point, microstep_of_found == tag.microstep - 1. - if (found->next == NULL) { - found->next = e; - } else { - switch (trigger->policy) { - case drop: - if (found->next->token != token) { - _lf_done_using(token); - } - lf_recycle_event(env, e); - return 0; - break; - case replace: - // Replace the payload of the event at the head with our - // current payload. - lf_replace_token(found->next, token); - lf_recycle_event(env, e); - return 0; - break; - default: - // Adding a microstep to the original - // intended tag. - if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = microstep_of_found + 1})) { - // Scheduling e will incur a microstep at timeout, - // which is illegal. - lf_recycle_event(env, e); - return 0; - } - if (found->next->next != NULL) { - lf_print_error("_lf_schedule_at_tag: in-order contract violated."); - return -1; - } - found->next->next = e; - } - } - } - } else { - // No existing event queued. - microstep_t relative_microstep = tag.microstep; - if (tag.time == current_logical_tag.time) { - relative_microstep -= current_logical_tag.microstep; - } - if ((tag.time == current_logical_tag.time && relative_microstep == 1 && env->execution_started) || - tag.microstep == 0) { - // Do not need a dummy event if we are scheduling at 1 microstep - // in the future at current time or at microstep 0 in a future time. - // Note that if execution hasn't started, then we have to insert dummy events. - pqueue_insert(env->event_q, e); - } else { - // Create a dummy event. Insert it into the queue, and let its next - // pointer point to the actual event. - pqueue_insert(env->event_q, _lf_create_dummy_events(env, trigger, tag.time, e, relative_microstep)); - } - } + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); + + // event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, e); + // if (found != NULL) { + // if (tag.microstep == 0u) { + // // The microstep is 0, which means that the event is being scheduled + // // at a future time and at the beginning of the skip list of events + // // at that time. + // // In case the event is a dummy event + // // convert it to a real event. + // found->is_dummy = false; + // switch (trigger->policy) { + // case drop: + // if (found->token != token) { + // _lf_done_using(token); + // } + // lf_recycle_event(env, e); + // return (0); + // break; + // case replace: + // // Replace the payload of the event at the head with our + // // current payload. + // lf_replace_token(found, token); + // lf_recycle_event(env, e); + // return 0; + // break; + // default: + // // Adding a microstep to the original + // // intended tag. + // if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = 1})) { + // // Scheduling e will incur a microstep after the stop tag, + // // which is illegal. + // lf_recycle_event(env, e); + // return 0; + // } + // if (found->next != NULL) { + // lf_print_error("_lf_schedule_at_tag: in-order contract violated."); + // return -1; + // } + // found->next = e; + // } + // } else { + // // We are requesting a microstep greater than 0 + // // where there is already an event for this trigger on the event queue. + // // That event may itself be a dummy event for a real event that is + // // also at a microstep greater than 0. + // // We have to insert our event into the chain or append it + // // to the end of the chain, depending on which microstep is lesser. + // microstep_t microstep_of_found = 0; + // if (tag.time == current_logical_tag.time) { + // // This is a situation where the head of the queue + // // is an event with microstep == current_microstep + 1 + // // which should be reflected in our steps calculation. + // microstep_of_found += current_logical_tag.microstep + 1; // Indicating that + // // the found event + // // is at this microstep. + // } + // // Follow the chain of events until the right point + // // to insert the new event. + // while (microstep_of_found < tag.microstep - 1) { + // if (found->next == NULL) { + // // The chain stops short of where we want to be. + // // If it exactly one microstep short of where we want to be, + // // then we don't need a dummy. Otherwise, we do. + // microstep_t undershot_by = (tag.microstep - 1) - microstep_of_found; + // if (undershot_by > 0) { + // found->next = _lf_create_dummy_events(env, trigger, tag.time, e, undershot_by); + // } else { + // found->next = e; + // } + // return 1; + // } + // found = found->next; + // microstep_of_found++; + // } + // // At this point, microstep_of_found == tag.microstep - 1. + // if (found->next == NULL) { + // found->next = e; + // } else { + // switch (trigger->policy) { + // case drop: + // if (found->next->token != token) { + // _lf_done_using(token); + // } + // lf_recycle_event(env, e); + // return 0; + // break; + // case replace: + // // Replace the payload of the event at the head with our + // // current payload. + // lf_replace_token(found->next, token); + // lf_recycle_event(env, e); + // return 0; + // break; + // default: + // // Adding a microstep to the original + // // intended tag. + // if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = microstep_of_found + 1})) { + // // Scheduling e will incur a microstep at timeout, + // // which is illegal. + // lf_recycle_event(env, e); + // return 0; + // } + // if (found->next->next != NULL) { + // lf_print_error("_lf_schedule_at_tag: in-order contract violated."); + // return -1; + // } + // found->next->next = e; + // } + // } + // } + // } else { + // // No existing event queued. + // microstep_t relative_microstep = tag.microstep; + // if (tag.time == current_logical_tag.time) { + // relative_microstep -= current_logical_tag.microstep; + // } + // if ((tag.time == current_logical_tag.time && relative_microstep == 1 && env->execution_started) || + // tag.microstep == 0) { + // // Do not need a dummy event if we are scheduling at 1 microstep + // // in the future at current time or at microstep 0 in a future time. + // // Note that if execution hasn't started, then we have to insert dummy events. + // pqueue_insert(env->event_q, e); + // } else { + // // Create a dummy event. Insert it into the queue, and let its next + // // pointer point to the actual event. + // pqueue_insert(env->event_q, _lf_create_dummy_events(env, trigger, tag.time, e, relative_microstep)); + // } + // } trigger_handle_t return_value = env->_lf_handle++; if (env->_lf_handle < 0) { env->_lf_handle = 1; @@ -757,36 +759,34 @@ trigger_handle_t _lf_insert_reactions_for_trigger(environment_t* env, trigger_t* return 1; } -void _lf_advance_logical_time(environment_t* env, instant_t next_time) { +void _lf_advance_logical_tag(environment_t* env, tag_t next_tag) { assert(env != GLOBAL_ENVIRONMENT); -// FIXME: The following checks that _lf_advance_logical_time() +// FIXME: The following checks that _lf_advance_logical_tag() // is being called correctly. Namely, check if logical time // is being pushed past the head of the event queue. This should -// never happen if _lf_advance_logical_time() is called correctly. +// never happen if _lf_advance_logical_tag() is called correctly. // This is commented out because it will add considerable overhead // to the ordinary execution of LF programs. Instead, there might // be a need for a target property that enables these kinds of logic // assertions for development purposes only. #ifndef NDEBUG - event_t* next_event = (event_t*)pqueue_peek(env->event_q); + event_t* next_event = (event_t*)pqueue_tag_peek(env->event_q); if (next_event != NULL) { - if (next_time > next_event->time) { - lf_print_error_and_exit("_lf_advance_logical_time(): Attempted to move time to " PRINTF_TIME ", which is " - "past the head of the event queue, " PRINTF_TIME ".", - next_time - start_time, next_event->time - start_time); + if (lf_tag_compare(next_tag, next_event->base.tag) > 0) { + lf_print_error_and_exit("_lf_advance_logical_tag(): Attempted to move time to " PRINTF_TAG ", which is " + "past the head of the event queue, " PRINTF_TAG ".", + next_tag.time - start_time, next_tag.microstep, next_event->base.tag.time - start_time, + next_event->base.tag.microstep); } } #endif - if (env->current_tag.time < next_time) { - env->current_tag.time = next_time; - env->current_tag.microstep = 0; - } else if (env->current_tag.time == next_time) { - env->current_tag.microstep++; + if (lf_tag_compare(env->current_tag, next_tag) <= 0) { + env->current_tag = next_tag; } else { - lf_print_error_and_exit("_lf_advance_logical_time(): Attempted to move tag back in time."); + lf_print_error_and_exit("_lf_advance_logical_tag(): Attempted to move tag back in tag."); } - LF_PRINT_LOG("Advanced (elapsed) tag to " PRINTF_TAG " at physical time " PRINTF_TIME, next_time - start_time, + LF_PRINT_LOG("Advanced (elapsed) tag to " PRINTF_TAG " at physical time " PRINTF_TIME, next_tag.time - start_time, env->current_tag.microstep, lf_time_physical_elapsed()); } @@ -1273,7 +1273,7 @@ void termination(void) { lf_print_warning("---- There are %zu unprocessed future events on the event queue.", pqueue_size(env[i].event_q)); event_t* event = (event_t*)pqueue_peek(env[i].event_q); - interval_t event_time = event->time - start_time; + interval_t event_time = event->base.tag.time - start_time; lf_print_warning("---- The first future event has timestamp " PRINTF_TIME " after start time.", event_time); } // Print elapsed times. diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 3419c3483..c871bc3cd 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -276,24 +276,25 @@ tag_t get_next_event_tag(environment_t* env) { assert(env != GLOBAL_ENVIRONMENT); // Peek at the earliest event in the event queue. - event_t* event = (event_t*)pqueue_peek(env->event_q); + event_t* event = (event_t*)pqueue_tag_peek(env->event_q); tag_t next_tag = FOREVER_TAG; if (event != NULL) { // There is an event in the event queue. - if (event->time < env->current_tag.time) { - lf_print_error_and_exit("get_next_event_tag(): Earliest event on the event queue (" PRINTF_TIME ") is " - "earlier than the current time (" PRINTF_TIME ").", - event->time - start_time, env->current_tag.time - start_time); + if (lf_tag_compare(event->base.tag, env->current_tag) < 0) { + lf_print_error_and_exit("get_next_event_tag(): Earliest event on the event queue (" PRINTF_TAG ") is " + "earlier than the current tag (" PRINTF_TAG ").", + event->base.tag.time - start_time, event->base.tag.microstep, + env->current_tag.time - start_time, env->current_tag.microstep); } - next_tag.time = event->time; - if (next_tag.time == env->current_tag.time) { - LF_PRINT_DEBUG("Earliest event matches current time. Incrementing microstep. Event is dummy: %d.", - event->is_dummy); - next_tag.microstep = env->current_tag.microstep + 1; - } else { - next_tag.microstep = 0; - } + next_tag = event->base.tag; + // if (next_tag.time == env->current_tag.time) { + // LF_PRINT_DEBUG("Earliest event matches current time. Incrementing microstep. Event is dummy: %d.", + // event->is_dummy); + // next_tag.microstep = env->current_tag.microstep + 1; + // } else { + // next_tag.microstep = 0; + // } } // If a timeout tag was given, adjust the next_tag from the @@ -302,7 +303,7 @@ tag_t get_next_event_tag(environment_t* env) { next_tag = env->stop_tag; } LF_PRINT_LOG("Earliest event on the event queue (or stop time if empty) is " PRINTF_TAG ". Event queue has size %zu.", - next_tag.time - start_time, next_tag.microstep, pqueue_size(env->event_q)); + next_tag.time - start_time, next_tag.microstep, pqueue_tag_size(env->event_q)); return next_tag; } @@ -408,7 +409,7 @@ void _lf_next_locked(environment_t* env) { // behavior with centralized coordination as with unfederated execution. #else // not FEDERATED_CENTRALIZED nor LF_ENCLAVES - if (pqueue_peek(env->event_q) == NULL && !keepalive_specified) { + if (pqueue_tag_peek(env->event_q) == NULL && !keepalive_specified) { // There is no event on the event queue and keepalive is false. // No event in the queue // keepalive is not set so we should stop. @@ -476,7 +477,7 @@ void _lf_next_locked(environment_t* env) { } // At this point, finally, we have an event to process. - _lf_advance_logical_time(env, next_tag.time); + _lf_advance_logical_tag(env, next_tag); _lf_start_time_step(env); @@ -971,8 +972,9 @@ void lf_print_snapshot(environment_t* env) { LF_PRINT_DEBUG("Pending:"); // pqueue_dump(reaction_q, print_reaction); FIXME: reaction_q is not // accessible here - LF_PRINT_DEBUG("Event queue size: %zu. Contents:", pqueue_size(env->event_q)); - pqueue_dump(env->event_q, print_reaction); + LF_PRINT_DEBUG("Event queue size: %zu. Contents:", pqueue_tag_size(env->event_q)); + // FIXME: There is no pqueue_tag_dump now + // pqueue_dump(env->event_q, print_reaction); LF_PRINT_DEBUG(">>> END Snapshot"); } } diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index e73e3ed48..9852d847c 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -21,15 +21,15 @@ int event_matches(void* event1, void* event2) { return (((event_t*)event1)->trig int reaction_matches(void* a, void* b) { return (a == b); } -pqueue_pri_t get_event_time(void* event) { return (pqueue_pri_t)(((event_t*)event)->time); } +pqueue_pri_t get_event_time(void* event) { return (pqueue_pri_t)(((event_t*)event)->base.tag.time); } pqueue_pri_t get_reaction_index(void* reaction) { return ((reaction_t*)reaction)->index; } -size_t get_event_position(void* event) { return ((event_t*)event)->pos; } +size_t get_event_position(void* event) { return ((event_t*)event)->base.pos; } size_t get_reaction_position(void* reaction) { return ((reaction_t*)reaction)->pos; } -void set_event_position(void* event, size_t pos) { ((event_t*)event)->pos = pos; } +void set_event_position(void* event, size_t pos) { ((event_t*)event)->base.pos = pos; } void set_reaction_position(void* reaction, size_t pos) { ((reaction_t*)reaction)->pos = pos; } @@ -40,5 +40,5 @@ void print_reaction(void* reaction) { void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, e->trigger, e->token); + LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->base.tag.time, e->trigger, e->token); } diff --git a/include/core/environment.h b/include/core/environment.h index 98753c6fb..01b388d40 100644 --- a/include/core/environment.h +++ b/include/core/environment.h @@ -75,7 +75,7 @@ typedef struct environment_t { tag_t stop_tag; pqueue_t* event_q; pqueue_t* recycle_q; - pqueue_t* next_q; + // pqueue_t* next_q; bool** is_present_fields; int is_present_fields_size; bool** is_present_fields_abbreviated; diff --git a/include/core/lf_types.h b/include/core/lf_types.h index 5598cf820..0135762c8 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -21,6 +21,7 @@ #include "modal_models/modes.h" // Modal model support #include "utils/pqueue.h" +#include "utils/pqueue_tag.h" #include "lf_token.h" #include "tag.h" #include "vector.h" @@ -195,15 +196,16 @@ typedef struct event_t event_t; /** Event activation record to push onto the event queue. */ struct event_t { - instant_t time; // Time of release. + pqueue_tag_element_t base; // Elements of pqueue_tag + // instant_t time; // Time of release. trigger_t* trigger; // Associated trigger, NULL if this is a dummy event. - size_t pos; // Position in the priority queue. + // size_t pos; // Position in the priority queue. lf_token_t* token; // Pointer to the token wrapping the value. bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. #ifdef FEDERATED tag_t intended_tag; // The intended tag. #endif - event_t* next; // Pointer to the next event lined up in superdense time. + // event_t* next; // Pointer to the next event lined up in superdense time. }; /** diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index fc1451a96..8c5c320c9 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -198,13 +198,10 @@ void _lf_trigger_shutdown_reactions(environment_t* env); * Create dummy events to be used as spacers in the event queue. * @param env Environment in which we are executing. * @param trigger The eventual event to be triggered. - * @param time The logical time of that event. - * @param next The event to place after the dummy events. - * @param offset The number of dummy events to insert. - * @return A pointer to the first dummy event. + * @param tag The tag of that event. + * @return A pointer to the dummy event. */ -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, instant_t time, event_t* next, - microstep_t offset); +event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag); /** * @brief Schedule an event at a specific tag (time, microstep). @@ -250,9 +247,9 @@ trigger_handle_t _lf_insert_reactions_for_trigger(environment_t* env, trigger_t* * the current time, then increase the microstep. Otherwise, update the current * time and set the microstep to zero. * @param env The environment in which we are executing - * @param next_time The time step to advance to. + * @param next_tag The tag step to advance to. */ -void _lf_advance_logical_time(environment_t* env, instant_t next_time); +void _lf_advance_logical_tag(environment_t* env, tag_t next_tag); /** * @brief Pop all events from event_q with tag equal to current tag. diff --git a/lib/schedule.c b/lib/schedule.c index 645bb41ec..ecb4b163b 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -164,7 +164,7 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int event_t* e = lf_get_new_event(env); // Initialize the next pointer. - e->next = NULL; +// e->next = NULL; // Set the payload. e->token = token; @@ -207,16 +207,16 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Check for conflicts (a queued event with the same trigger and time). if (min_spacing <= 0) { // No minimum spacing defined. - e->time = intended_tag.time; + e->base.tag = intended_tag; event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, e); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; - // Skip to the last node in the linked list. - while (found->next != NULL) { - found = found->next; - intended_tag.microstep++; - } + // // Skip to the last node in the linked list. + // while (found->next != NULL) { + // found = found->next; + // intended_tag.microstep++; + // } if (lf_is_tag_after_stop_tag(env, intended_tag)) { LF_PRINT_DEBUG("Attempt to schedule an event after stop_tag was rejected."); // Scheduling an event will incur a microstep @@ -224,8 +224,8 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int lf_recycle_event(env, e); return 0; } - // Hook the event into the list. - found->next = e; + // // Hook the event into the list. + // found->next = e; trigger->last_tag = intended_tag; return (0); // FIXME: return value } @@ -254,13 +254,13 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int return (0); case replace: LF_PRINT_DEBUG("Policy is replace. Replacing the previous event."); - // If the event with the previous time is still on the event + // If the event with the previous tag is still on the event // queue, then replace the token. To find this event, we have // to construct a dummy event_t struct. event_t* dummy = lf_get_new_event(env); - dummy->next = NULL; + // dummy->next = NULL; dummy->trigger = trigger; - dummy->time = trigger->last_tag.time; + dummy->base.tag = trigger->last_tag; event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, dummy); if (found != NULL) { @@ -300,13 +300,14 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int #endif // Set the tag of the event. - e->time = intended_tag.time; + e->base.tag = intended_tag; // Do not schedule events if if the event time is past the stop time // (current microsteps are checked earlier). + // FIXME: Maybe this tag itself should be compared? LF_PRINT_DEBUG("Comparing event with elapsed time " PRINTF_TIME " against stop time " PRINTF_TIME ".", - e->time - lf_time_start(), env->stop_tag.time - lf_time_start()); - if (e->time > env->stop_tag.time) { + e->base.tag.time - lf_time_start(), env->stop_tag.time - lf_time_start()); + if (e->base.tag.time > env->stop_tag.time) { LF_PRINT_DEBUG("lf_schedule_trigger: event time is past the timeout. Discarding event."); _lf_done_using(token); lf_recycle_event(env, e); @@ -324,8 +325,8 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // and any new events added at this tag will go into the reaction_q // rather than the event_q, so anything put in the event_q with this // same time will automatically be executed at the next microstep. - LF_PRINT_LOG("Inserting event in the event queue with elapsed time " PRINTF_TIME ".", e->time - lf_time_start()); - pqueue_insert(env->event_q, e); + LF_PRINT_LOG("Inserting event in the event queue with elapsed time " PRINTF_TIME ".", e->base.tag.time - lf_time_start()); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); tracepoint_schedule(env, trigger, e->time - env->current_tag.time); From 89a7a9585ac78d31e3e9de45f0750e548b2c800d Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 15:12:16 +0100 Subject: [PATCH 34/95] Fix some minor errors --- core/federated/RTI/rti_remote.c | 2 ++ trace/impl/src/trace_impl.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/federated/RTI/rti_remote.c b/core/federated/RTI/rti_remote.c index ebd96550d..24ac7f1dc 100644 --- a/core/federated/RTI/rti_remote.c +++ b/core/federated/RTI/rti_remote.c @@ -1318,6 +1318,7 @@ static int receive_connection_information(int* socket_id, uint16_t fed_id) { // Allocate memory for the upstream and downstream pointers if (fed->enclave.num_upstream > 0) { + // FIXME: This looks wrong. We are casting an array of uint16_ts to an int*? fed->enclave.upstream = (int*)malloc(sizeof(uint16_t) * fed->enclave.num_upstream); // Allocate memory for the upstream delay pointers fed->enclave.upstream_delay = (interval_t*)malloc(sizeof(interval_t) * fed->enclave.num_upstream); @@ -1326,6 +1327,7 @@ static int receive_connection_information(int* socket_id, uint16_t fed_id) { fed->enclave.upstream_delay = (interval_t*)NULL; } if (fed->enclave.num_downstream > 0) { + // FIXME: This looks wrong. We are casting an array of uint16_ts to an int*? fed->enclave.downstream = (int*)malloc(sizeof(uint16_t) * fed->enclave.num_downstream); } else { fed->enclave.downstream = (int*)NULL; diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index 28534364b..00e253830 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -141,7 +141,7 @@ static void start_trace(trace_t* trace, int max_num_local_threads) { trace->_lf_trace_buffer[i] = (trace_record_nodeps_t*)malloc(sizeof(trace_record_nodeps_t) * TRACE_BUFFER_CAPACITY); } // Array of counters that track the size of each trace record (per thread). - trace->_lf_trace_buffer_size = (size_t*)calloc(sizeof(int), trace->_lf_number_of_trace_buffers + 1); + trace->_lf_trace_buffer_size = (size_t*)calloc(sizeof(size_t), trace->_lf_number_of_trace_buffers + 1); trace->_lf_trace_buffer_size++; trace->_lf_trace_stop = 0; @@ -231,7 +231,7 @@ void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { // Therefore we should fall back to using a mutex. lf_platform_mutex_lock(trace_mutex); } - if (tid > (int)trace._lf_number_of_trace_buffers) { + if (((size_t)tid) > trace._lf_number_of_trace_buffers) { lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%zu)", tid, trace._lf_number_of_trace_buffers); } From b9ab82db572264c989184f1da0f50d91e259bb13 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 15:21:33 +0100 Subject: [PATCH 35/95] Fix casting mistake in trace_impl --- trace/impl/src/trace_impl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index 00e253830..7f79c49a5 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -231,7 +231,7 @@ void lf_tracing_tracepoint(int worker, trace_record_nodeps_t* tr) { // Therefore we should fall back to using a mutex. lf_platform_mutex_lock(trace_mutex); } - if (((size_t)tid) > trace._lf_number_of_trace_buffers) { + if (tid > (int)trace._lf_number_of_trace_buffers) { lf_print_error_and_exit("the thread id (%d) exceeds the number of trace buffers (%zu)", tid, trace._lf_number_of_trace_buffers); } From 002c03014652485bb363d4c46528f4fbdb7cda0d Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 15:52:04 +0100 Subject: [PATCH 36/95] More unused warnings --- core/reactor.c | 4 ++-- core/reactor_common.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/reactor.c b/core/reactor.c index 766ac108c..235e1d34d 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -92,6 +92,7 @@ void lf_print_snapshot(environment_t* env) { } #else // NDEBUG void lf_print_snapshot(environment_t* env) { + (void)env; // Do nothing. } #endif // NDEBUG @@ -283,8 +284,7 @@ int next(environment_t* env) { void lf_request_stop(void) { // There is only one enclave, so get its environment. environment_t* env; - int num_environments = _lf_get_environments(&env); - assert(num_environments == 1); + _lf_get_environments(&env); tag_t new_stop_tag; new_stop_tag.time = env->current_tag.time; diff --git a/core/reactor_common.c b/core/reactor_common.c index fd3be5ae5..ba6f9574c 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1329,7 +1329,7 @@ void termination(void) { } index_t lf_combine_deadline_and_level(interval_t deadline, int level) { - if (deadline > ((interval_t)ULLONG_MAX >> 16)) + if (deadline > (interval_t)(ULLONG_MAX >> 16)) return ((ULLONG_MAX >> 16) << 16) | level; else return (deadline << 16) | level; From e78580882e57a61f57357ea78d8827bd67621c6f Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 16:32:56 +0100 Subject: [PATCH 37/95] More warnings --- core/lf_utils.cmake | 10 +++++----- low_level_platform/impl/src/lf_macos_support.c | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/lf_utils.cmake b/core/lf_utils.cmake index 0dcdcaaa1..5b6b35921 100644 --- a/core/lf_utils.cmake +++ b/core/lf_utils.cmake @@ -1,11 +1,11 @@ function(lf_enable_compiler_warnings target) - if(MSVC) + if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror) + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") target_compile_options(${target} PRIVATE /W4) - elseif(APPLE) + elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") target_compile_options(${target} PRIVATE -Wall) - elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - target_compile_options(${target} PRIVATE -Wall -Wextra) else() - target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic -Werror) + target_compile_options(${target} PRIVATE -Wall) endif() endfunction() \ No newline at end of file diff --git a/low_level_platform/impl/src/lf_macos_support.c b/low_level_platform/impl/src/lf_macos_support.c index 54fcfd296..4cb3002cd 100644 --- a/low_level_platform/impl/src/lf_macos_support.c +++ b/low_level_platform/impl/src/lf_macos_support.c @@ -57,6 +57,7 @@ int lf_sleep(interval_t sleep_duration) { } int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { + (void)env; interval_t sleep_duration = wakeup_time - lf_time_physical(); if (sleep_duration <= 0) { From b60db68aa7546a849757c323111a51dff16eed94 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 16:44:17 +0100 Subject: [PATCH 38/95] Formatting --- core/platform/lf_windows_support.c | 303 ++++++++---------- low_level_platform/api/low_level_platform.h | 33 +- .../impl/src/lf_macos_support.c | 1 - 3 files changed, 157 insertions(+), 180 deletions(-) diff --git a/core/platform/lf_windows_support.c b/core/platform/lf_windows_support.c index 9150634ef..e6e7906fd 100644 --- a/core/platform/lf_windows_support.c +++ b/core/platform/lf_windows_support.c @@ -34,7 +34,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @see https://gist.github.com/Soroosh129/127d1893fa4c1da6d3e1db33381bb273 */ -#include // Order in which windows.h is included does matter! +#include // Order in which windows.h is included does matter! #include #include #include @@ -59,16 +59,15 @@ int _lf_use_performance_counter = 0; double _lf_frequency_to_ns = 1.0; void _lf_initialize_clock() { - // Check if the performance counter is available - LARGE_INTEGER performance_frequency; - _lf_use_performance_counter = QueryPerformanceFrequency(&performance_frequency); - if (_lf_use_performance_counter) { - _lf_frequency_to_ns = (double)performance_frequency.QuadPart / BILLION; - } else { - lf_print_error( - "High resolution performance counter is not supported on this machine."); - _lf_frequency_to_ns = 0.01; - } + // Check if the performance counter is available + LARGE_INTEGER performance_frequency; + _lf_use_performance_counter = QueryPerformanceFrequency(&performance_frequency); + if (_lf_use_performance_counter) { + _lf_frequency_to_ns = (double)performance_frequency.QuadPart / BILLION; + } else { + lf_print_error("High resolution performance counter is not supported on this machine."); + _lf_frequency_to_ns = 0.01; + } } /** @@ -80,31 +79,31 @@ void _lf_initialize_clock() { * set to EINVAL or EFAULT. */ int _lf_clock_gettime(instant_t* t) { - // Adapted from gclib/GResUsage.cpp - // (https://github.com/gpertea/gclib/blob/8aee376774ccb2f3bd3f8e3bf1c9df1528ac7c5b/GResUsage.cpp) - // License: https://github.com/gpertea/gclib/blob/master/LICENSE.txt - int result = -1; - if (t == NULL) { - // The t argument address references invalid memory - errno = EFAULT; - return result; - } - LARGE_INTEGER windows_time; - if (_lf_use_performance_counter) { - int result = QueryPerformanceCounter(&windows_time); - if ( result == 0) { - lf_print_error("_lf_clock_gettime(): Failed to read the value of the physical clock."); - return result; - } - } else { - FILETIME f; - GetSystemTimeAsFileTime(&f); - windows_time.QuadPart = f.dwHighDateTime; - windows_time.QuadPart <<= 32; - windows_time.QuadPart |= f.dwLowDateTime; + // Adapted from gclib/GResUsage.cpp + // (https://github.com/gpertea/gclib/blob/8aee376774ccb2f3bd3f8e3bf1c9df1528ac7c5b/GResUsage.cpp) + // License: https://github.com/gpertea/gclib/blob/master/LICENSE.txt + int result = -1; + if (t == NULL) { + // The t argument address references invalid memory + errno = EFAULT; + return result; + } + LARGE_INTEGER windows_time; + if (_lf_use_performance_counter) { + int result = QueryPerformanceCounter(&windows_time); + if (result == 0) { + lf_print_error("_lf_clock_gettime(): Failed to read the value of the physical clock."); + return result; } - *t = (instant_t)((double)windows_time.QuadPart / _lf_frequency_to_ns); - return (0); + } else { + FILETIME f; + GetSystemTimeAsFileTime(&f); + windows_time.QuadPart = f.dwHighDateTime; + windows_time.QuadPart <<= 32; + windows_time.QuadPart |= f.dwLowDateTime; + } + *t = (instant_t)((double)windows_time.QuadPart / _lf_frequency_to_ns); + return (0); } /** @@ -116,65 +115,62 @@ int _lf_clock_gettime(instant_t* t) { * - EINVAL: All other errors */ int lf_sleep(interval_t sleep_duration) { - /* Declarations */ - HANDLE timer; /* Timer handle */ - LARGE_INTEGER li; /* Time defintion */ - /* Create timer */ - if(!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) { - return FALSE; - } - /** - * Set timer properties. - * A negative number indicates relative time to wait. - * The requested sleep duration must be in number of 100 nanoseconds. - */ - li.QuadPart = -1 * (sleep_duration / 100); - if(!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)){ - CloseHandle(timer); - return FALSE; - } - /* Start & wait for timer */ - WaitForSingleObject(timer, INFINITE); - /* Clean resources */ + /* Declarations */ + HANDLE timer; /* Timer handle */ + LARGE_INTEGER li; /* Time defintion */ + /* Create timer */ + if (!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) { + return FALSE; + } + /** + * Set timer properties. + * A negative number indicates relative time to wait. + * The requested sleep duration must be in number of 100 nanoseconds. + */ + li.QuadPart = -1 * (sleep_duration / 100); + if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) { CloseHandle(timer); - /* Slept without problems */ - return TRUE; + return FALSE; + } + /* Start & wait for timer */ + WaitForSingleObject(timer, INFINITE); + /* Clean resources */ + CloseHandle(timer); + /* Slept without problems */ + return TRUE; } int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { - interval_t sleep_duration = wakeup_time - lf_time_physical(); - - if (sleep_duration <= 0) { - return 0; - } else { - return lf_sleep(sleep_duration); - } -} + interval_t sleep_duration = wakeup_time - lf_time_physical(); -int lf_nanosleep(interval_t sleep_duration) { + if (sleep_duration <= 0) { + return 0; + } else { return lf_sleep(sleep_duration); + } } +int lf_nanosleep(interval_t sleep_duration) { return lf_sleep(sleep_duration); } + #if defined(LF_SINGLE_THREADED) #include "lf_os_single_threaded_support.c" #endif - #if !defined(LF_SINGLE_THREADED) int lf_available_cores() { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; } -int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arguments) { - uintptr_t handle = _beginthreadex(NULL, 0, lf_thread, arguments, 0, NULL); - *thread = (HANDLE)handle; - if(handle == 0){ - return errno; - }else{ - return 0; - } +int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* arguments) { + uintptr_t handle = _beginthreadex(NULL, 0, lf_thread, arguments, 0, NULL); + *thread = (HANDLE)handle; + if (handle == 0) { + return errno; + } else { + return 0; + } } /** @@ -185,37 +181,29 @@ int lf_thread_create(lf_thread_t* thread, void *(*lf_thread) (void *), void* arg * @return 0 on success, EINVAL otherwise. */ int lf_thread_join(lf_thread_t thread, void** thread_return) { - DWORD retvalue = WaitForSingleObject(thread, INFINITE); - if(retvalue == WAIT_FAILED){ - return EINVAL; - } - return 0; + DWORD retvalue = WaitForSingleObject(thread, INFINITE); + if (retvalue == WAIT_FAILED) { + return EINVAL; + } + return 0; } -lf_thread_t lf_thread_self() { - return GetCurrentThread(); -} +lf_thread_t lf_thread_self() { return GetCurrentThread(); } -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { - return -1; -} +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } -int lf_thread_set_priority(lf_thread_t thread, int priority) { - return -1; -} +int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy) { - return -1; -} +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { return -1; } int lf_mutex_init(_lf_critical_section_t* critical_section) { - // Set up a recursive mutex - InitializeCriticalSection((PCRITICAL_SECTION)critical_section); - if(critical_section != NULL){ - return 0; - }else{ - return 1; - } + // Set up a recursive mutex + InitializeCriticalSection((PCRITICAL_SECTION)critical_section); + if (critical_section != NULL) { + return 0; + } else { + return 1; + } } /** @@ -230,88 +218,79 @@ int lf_mutex_init(_lf_critical_section_t* critical_section) { * @return 0 */ int lf_mutex_lock(_lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. It can - // raise a EXCEPTION_POSSIBLE_DEADLOCK. See synchapi.h. - EnterCriticalSection((PCRITICAL_SECTION)critical_section); - return 0; + // The following Windows API does not return a value. It can + // raise a EXCEPTION_POSSIBLE_DEADLOCK. See synchapi.h. + EnterCriticalSection((PCRITICAL_SECTION)critical_section); + return 0; } int lf_mutex_unlock(_lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. - LeaveCriticalSection((PCRITICAL_SECTION)critical_section); - return 0; + // The following Windows API does not return a value. + LeaveCriticalSection((PCRITICAL_SECTION)critical_section); + return 0; } int lf_cond_init(lf_cond_t* cond, _lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. - cond->critical_section = critical_section; - InitializeConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; + // The following Windows API does not return a value. + cond->critical_section = critical_section; + InitializeConditionVariable((PCONDITION_VARIABLE)&cond->condition); + return 0; } int lf_cond_broadcast(lf_cond_t* cond) { - // The following Windows API does not return a value. - WakeAllConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; + // The following Windows API does not return a value. + WakeAllConditionVariable((PCONDITION_VARIABLE)&cond->condition); + return 0; } int lf_cond_signal(lf_cond_t* cond) { - // The following Windows API does not return a value. - WakeConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; + // The following Windows API does not return a value. + WakeConditionVariable((PCONDITION_VARIABLE)&cond->condition); + return 0; } int lf_cond_wait(lf_cond_t* cond) { - // According to synchapi.h, the following Windows API returns 0 on failure, - // and non-zero on success. - int return_value = - (int)SleepConditionVariableCS( - (PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, - INFINITE - ); - switch (return_value) { - case 0: - // Error - return 1; - break; - - default: - // Success - return 0; - break; - } + // According to synchapi.h, the following Windows API returns 0 on failure, + // and non-zero on success. + int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, + (PCRITICAL_SECTION)cond->critical_section, INFINITE); + switch (return_value) { + case 0: + // Error + return 1; + break; + + default: + // Success + return 0; + break; + } } int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { - // Convert the absolute time to a relative time. - interval_t wait_duration = wakeup_time - lf_time_physical(); - if (wait_duration<= 0) { - // physical time has already caught up sufficiently and we do not need to wait anymore - return 0; - } + // Convert the absolute time to a relative time. + interval_t wait_duration = wakeup_time - lf_time_physical(); + if (wait_duration <= 0) { + // physical time has already caught up sufficiently and we do not need to wait anymore + return 0; + } + + // convert ns to ms and round up to closest full integer + DWORD wait_duration_ms = (wait_duration + 999999LL) / 1000000LL; - // convert ns to ms and round up to closest full integer - DWORD wait_duration_ms = (wait_duration + 999999LL) / 1000000LL; - - int return_value = - (int)SleepConditionVariableCS( - (PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, - wait_duration_ms - ); - if (return_value == 0) { - // Error - if (GetLastError() == ERROR_TIMEOUT) { - return LF_TIMEOUT; - } - return -1; + int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, + (PCRITICAL_SECTION)cond->critical_section, wait_duration_ms); + if (return_value == 0) { + // Error + if (GetLastError() == ERROR_TIMEOUT) { + return LF_TIMEOUT; } + return -1; + } - // Success - return 0; + // Success + return 0; } #endif - #endif diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 2955d9bbd..fd0145621 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -109,7 +109,7 @@ int lf_available_cores(); /** * Returns the thread ID of the calling thread - * + * */ lf_thread_t lf_thread_self(); @@ -138,7 +138,6 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum */ int lf_thread_join(lf_thread_t thread, void** thread_return); - // The following API introduce the ability to change how the LF workers are sheduled // by the underlying thread scheduling. This API is still experimental and future // changes are expected. @@ -146,34 +145,34 @@ int lf_thread_join(lf_thread_t thread, void** thread_return); #define LF_SCHED_MAX_PRIORITY 99 #define LF_SCHED_MIN_PRIORITY 0 /** - * @brief The thread scheduling policies. - * + * @brief The thread scheduling policies. + * */ typedef enum { - LF_SCHED_FAIR, // Non real-time scheduling policy. Corresponds to SCHED_OTHER - LF_SCHED_TIMESLICE, // Real-time, time-slicing priority-based policty. Corresponds to SCHED_RR. - LF_SCHED_PRIORITY, // Real-time, priority-only based scheduling. Corresponds to SCHED_FIFO. + LF_SCHED_FAIR, // Non real-time scheduling policy. Corresponds to SCHED_OTHER + LF_SCHED_TIMESLICE, // Real-time, time-slicing priority-based policty. Corresponds to SCHED_RR. + LF_SCHED_PRIORITY, // Real-time, priority-only based scheduling. Corresponds to SCHED_FIFO. } lf_scheduling_policy_type_t; typedef struct { - lf_scheduling_policy_type_t policy; + lf_scheduling_policy_type_t policy; } lf_scheduling_policy_t; typedef struct { - lf_scheduling_policy_t base; - int priority; - interval_t time_slice; + lf_scheduling_policy_t base; + int priority; + interval_t time_slice; } lf_scheduling_policy_timeslice_t; typedef struct { - lf_scheduling_policy_t base; - int priority; + lf_scheduling_policy_t base; + int priority; } lf_scheduling_policy_priority_t; /** * This pins a lf_thread to a specific CPU - * - * @param thread The thread + * + * @param thread The thread * @param cpu_number the CPU ID * @return 0 on success, platform-specific error number otherwise. */ @@ -192,10 +191,10 @@ int lf_thread_set_priority(lf_thread_t thread, int priority); /** * Sets the scheduling policy of a thread. - * + * * @return int 0 on success, platform-specific error number otherwise. */ -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t *policy); +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy); /** * Initialize a mutex. diff --git a/low_level_platform/impl/src/lf_macos_support.c b/low_level_platform/impl/src/lf_macos_support.c index 9c36502e5..4232d5825 100644 --- a/low_level_platform/impl/src/lf_macos_support.c +++ b/low_level_platform/impl/src/lf_macos_support.c @@ -46,7 +46,6 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { return -1; } #endif -#include "lf_unix_clock_support.h" #include "platform/lf_unix_clock_support.h" // See `man 2 clock_nanosleep` for return values From 0fc284fbccb2a2c7ecd7b37c63d4c4d08f4a8b9a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 16:57:59 +0100 Subject: [PATCH 39/95] Improve the lf_scheduling_policy_t --- low_level_platform/api/low_level_platform.h | 15 +++------------ low_level_platform/impl/src/lf_linux_support.c | 4 ++-- low_level_platform/impl/src/lf_zephyr_support.c | 9 +++------ 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index fd0145621..d3049b610 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -155,20 +155,11 @@ typedef enum { } lf_scheduling_policy_type_t; typedef struct { - lf_scheduling_policy_type_t policy; + lf_scheduling_policy_type_t policy; // The scheduling policy + int priority; // The priority, if applicable + interval_t time_slice; // The time-slice allocated, if applicable. } lf_scheduling_policy_t; -typedef struct { - lf_scheduling_policy_t base; - int priority; - interval_t time_slice; -} lf_scheduling_policy_timeslice_t; - -typedef struct { - lf_scheduling_policy_t base; - int priority; -} lf_scheduling_policy_priority_t; - /** * This pins a lf_thread to a specific CPU * diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 46c3094e4..755ee1751 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -75,11 +75,11 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* break; case LF_SCHED_TIMESLICE: posix_policy = SCHED_RR; - schedparam.sched_priority = ((lf_scheduling_policy_timeslice_t*)policy)->priority; + schedparam.sched_priority = policy->priority; break; case LF_SCHED_PRIORITY: posix_policy = SCHED_FIFO; - schedparam.sched_priority = ((lf_scheduling_policy_priority_t*)policy)->priority; + schedparam.sched_priority = policy->priority; break; default: return -1; diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index 18dff3e62..dd18dc777 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -169,15 +169,12 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* case LF_SCHED_FAIR: break; case LF_SCHED_TIMESLICE: { - int priority = ((lf_scheduling_policy_timeslice_t*)policy)->priority; - interval_t slice = ((lf_scheduling_policy_timeslice_t*)policy)->time_slice; - k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - priority); - k_sched_time_slice_set(0, slice / 1000000); + k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - policy->priority); + k_sched_time_slice_set(0, policy->time_slice / 1000000); break; } case LF_SCHED_PRIORITY: { - int priority = ((lf_scheduling_policy_timeslice_t*)policy)->priority; - k_thread_priority_set(thread, 99 - priority); + k_thread_priority_set(thread, 99 - policy->priority); break; } default: From 326bf2b2396d888498ffa1889654b89da7c76ca0 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 8 Mar 2024 17:21:27 +0100 Subject: [PATCH 40/95] lf-ref --- lingua-franca-ref.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lingua-franca-ref.txt b/lingua-franca-ref.txt index 1f7391f92..5c27d6559 100644 --- a/lingua-franca-ref.txt +++ b/lingua-franca-ref.txt @@ -1 +1 @@ -master +run-zephyr-tests From 4a7f67b45426d59c7d29f13eef7ab9e18286851a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 09:59:16 +0100 Subject: [PATCH 41/95] Make initial event/react q size configurable --- core/CMakeLists.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 9621497d6..e4a9f1b6c 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -116,14 +116,18 @@ if(DEFINED _LF_CLOCK_SYNC_ON) endif() endif() +# Unless specified otherwise initial event queue and reaction queue to size 10 +if (NOT DEFINED INITIAL_EVENT_QUEUE_SIZE) + set(INITIAL_EVENT_QUEUE_SIZE 10) +endif() +if (NOT DEFINED INITIAL_REACT_QUEUE_SIZE) + set(INITIAL_REACT_QUEUE_SIZE 10) +endif() -# FIXME: May want these to be application dependent, hence passed as -# parameters to Cmake. -target_compile_definitions(reactor-c PRIVATE INITIAL_EVENT_QUEUE_SIZE=10) -target_compile_definitions(reactor-c PRIVATE INITIAL_REACT_QUEUE_SIZE=10) +target_compile_definitions(reactor-c PRIVATE INITIAL_EVENT_QUEUE_SIZE=${INITIAL_EVENT_QUEUE_SIZE}) +target_compile_definitions(reactor-c PRIVATE INITIAL_REACT_QUEUE_SIZE=${INITIAL_REACT_QUEUE_SIZE}) target_compile_definitions(reactor-c PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) - # Macro for translating a command-line argument into compile definition for # reactor-c lib macro(define X) From aaba8f46f780e9194e77c631750a8ebff171243e Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 10:08:22 +0100 Subject: [PATCH 42/95] Fix NP scheduler comment --- core/threaded/scheduler_NP.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/threaded/scheduler_NP.c b/core/threaded/scheduler_NP.c index 800c9fc2b..01b510477 100644 --- a/core/threaded/scheduler_NP.c +++ b/core/threaded/scheduler_NP.c @@ -109,8 +109,9 @@ int _lf_sched_distribute_ready_reactions(lf_scheduler_t* scheduler) { */ void _lf_sched_notify_workers(lf_scheduler_t* scheduler) { // Calculate the number of workers that we need to wake up, which is the - // Note: All threads are idle. Therefore, there is no need to lock the mutex - // while accessing the index for the current level. + // number of reactions enabled at this level. + // Note: All threads are idle. Therefore, there is no need to lock the mutex while accessing the index for the + // current level. size_t workers_to_awaken = LF_MIN(scheduler->number_of_idle_workers, (size_t)(scheduler->indexes[scheduler->next_reaction_level - 1])); LF_PRINT_DEBUG("Scheduler: Notifying %zu workers.", workers_to_awaken); From 22705a7050478cda393304df17b4fd2f077ee7a6 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 10:14:19 +0100 Subject: [PATCH 43/95] Update lf-ref --- lingua-franca-ref.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lingua-franca-ref.txt b/lingua-franca-ref.txt index 5c27d6559..8b25206ff 100644 --- a/lingua-franca-ref.txt +++ b/lingua-franca-ref.txt @@ -1 +1 @@ -run-zephyr-tests +master \ No newline at end of file From 02bcafe92da3f18f5e47a6e94e2d9707adb37b8d Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 10:14:26 +0100 Subject: [PATCH 44/95] Add back assertions --- include/core/federated/network/net_common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/core/federated/network/net_common.h b/include/core/federated/network/net_common.h index 4d9393f28..eb27d64d6 100644 --- a/include/core/federated/network/net_common.h +++ b/include/core/federated/network/net_common.h @@ -483,6 +483,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST; \ encode_int64(time, &(buffer[1])); \ + assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) @@ -500,6 +501,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST_REPLY; \ encode_int64(time, &(buffer[1])); \ + assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) From 9d8ce9ad3fe4ab2ca5a99d9e8920d0de6874873b Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 10:21:58 +0100 Subject: [PATCH 45/95] federate upstream/downstream are uint16_t not int --- core/federated/RTI/rti_common.h | 4 ++-- core/federated/RTI/rti_remote.c | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/core/federated/RTI/rti_common.h b/core/federated/RTI/rti_common.h index 1c3396749..d4e0c1236 100644 --- a/core/federated/RTI/rti_common.h +++ b/core/federated/RTI/rti_common.h @@ -54,11 +54,11 @@ typedef struct scheduling_node_t { tag_t last_provisionally_granted; // The maximum PTAG that has been provisionally granted (or NEVER if none granted) tag_t next_event; // Most recent NET received from the scheduling node (or NEVER if none received). scheduling_node_state_t state; // State of the scheduling node. - int* upstream; // Array of upstream scheduling node ids. + uint16_t* upstream; // Array of upstream scheduling node ids. interval_t* upstream_delay; // Minimum delay on connections from upstream scheduling nodes. // Here, NEVER encodes no delay. 0LL is a microstep delay. int num_upstream; // Size of the array of upstream scheduling nodes and delays. - int* downstream; // Array of downstream scheduling node ids. + uint16_t* downstream; // Array of downstream scheduling node ids. int num_downstream; // Size of the array of downstream scheduling nodes. execution_mode_t mode; // FAST or REALTIME. minimum_delay_t* min_delays; // Array of minimum delays from upstream nodes, not including this node. diff --git a/core/federated/RTI/rti_remote.c b/core/federated/RTI/rti_remote.c index 24ac7f1dc..743c6eb07 100644 --- a/core/federated/RTI/rti_remote.c +++ b/core/federated/RTI/rti_remote.c @@ -1318,19 +1318,17 @@ static int receive_connection_information(int* socket_id, uint16_t fed_id) { // Allocate memory for the upstream and downstream pointers if (fed->enclave.num_upstream > 0) { - // FIXME: This looks wrong. We are casting an array of uint16_ts to an int*? - fed->enclave.upstream = (int*)malloc(sizeof(uint16_t) * fed->enclave.num_upstream); + fed->enclave.upstream = (uint16_t*)malloc(sizeof(uint16_t) * fed->enclave.num_upstream); // Allocate memory for the upstream delay pointers fed->enclave.upstream_delay = (interval_t*)malloc(sizeof(interval_t) * fed->enclave.num_upstream); } else { - fed->enclave.upstream = (int*)NULL; + fed->enclave.upstream = (uint16_t*)NULL; fed->enclave.upstream_delay = (interval_t*)NULL; } if (fed->enclave.num_downstream > 0) { - // FIXME: This looks wrong. We are casting an array of uint16_ts to an int*? - fed->enclave.downstream = (int*)malloc(sizeof(uint16_t) * fed->enclave.num_downstream); + fed->enclave.downstream = (uint16_t*)malloc(sizeof(uint16_t) * fed->enclave.num_downstream); } else { - fed->enclave.downstream = (int*)NULL; + fed->enclave.downstream = (uint16_t*)NULL; } size_t connections_info_body_size = ((sizeof(uint16_t) + sizeof(int64_t)) * fed->enclave.num_upstream) + From 9cfbbfc7af59f4de6c8ea0d7963f036e8ecb5f5e Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 10:49:57 +0100 Subject: [PATCH 46/95] Check return value from malloc --- core/federated/RTI/rti_remote.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/federated/RTI/rti_remote.c b/core/federated/RTI/rti_remote.c index 743c6eb07..00d167b16 100644 --- a/core/federated/RTI/rti_remote.c +++ b/core/federated/RTI/rti_remote.c @@ -1319,14 +1319,17 @@ static int receive_connection_information(int* socket_id, uint16_t fed_id) { // Allocate memory for the upstream and downstream pointers if (fed->enclave.num_upstream > 0) { fed->enclave.upstream = (uint16_t*)malloc(sizeof(uint16_t) * fed->enclave.num_upstream); + LF_ASSERT_NON_NULL(fed->enclave.upstream); // Allocate memory for the upstream delay pointers fed->enclave.upstream_delay = (interval_t*)malloc(sizeof(interval_t) * fed->enclave.num_upstream); + LF_ASSERT_NON_NULL(fed->enclave.upstream_delay); } else { fed->enclave.upstream = (uint16_t*)NULL; fed->enclave.upstream_delay = (interval_t*)NULL; } if (fed->enclave.num_downstream > 0) { fed->enclave.downstream = (uint16_t*)malloc(sizeof(uint16_t) * fed->enclave.num_downstream); + LF_ASSERT_NON_NULL(fed->enclave.downstream); } else { fed->enclave.downstream = (uint16_t*)NULL; } @@ -1336,6 +1339,7 @@ static int receive_connection_information(int* socket_id, uint16_t fed_id) { unsigned char* connections_info_body = NULL; if (connections_info_body_size > 0) { connections_info_body = (unsigned char*)malloc(connections_info_body_size); + LF_ASSERT_NON_NULL(connections_info_body); read_from_socket_fail_on_error(socket_id, connections_info_body_size, connections_info_body, NULL, "RTI failed to read MSG_TYPE_NEIGHBOR_STRUCTURE message body from federate %d.", fed_id); From 52b5bbc6706bd94d2f94ed7aee2bf08f120fdfd3 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 09:05:16 -0700 Subject: [PATCH 47/95] Schedule events with appropriate tag --- core/modal_models/modes.c | 4 +- core/reactor.c | 2 +- core/reactor_common.c | 189 ++++++++----------------------- core/threaded/reactor_threaded.c | 4 +- core/utils/pqueue.c | 2 +- core/utils/pqueue_support.h | 4 +- include/core/reactor_common.h | 2 +- lib/schedule.c | 42 ++++--- 8 files changed, 82 insertions(+), 167 deletions(-) diff --git a/core/modal_models/modes.c b/core/modal_models/modes.c index 5acf6a0b5..2cc6443d6 100644 --- a/core/modal_models/modes.c +++ b/core/modal_models/modes.c @@ -399,14 +399,14 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] event->trigger != NULL) { // History transition to a different mode // Remaining time that the event would have been waiting before mode was left instant_t local_remaining_delay = - event->time - + event->base.tag.time - (state->next_mode->deactivation_time != 0 ? state->next_mode->deactivation_time : lf_time_start()); tag_t current_logical_tag = env->current_tag; // Reschedule event with original local delay LF_PRINT_DEBUG("Modes: Re-enqueuing event with a suspended delay of " PRINTF_TIME " (previous TTH: " PRINTF_TIME ", Mode suspended at: " PRINTF_TIME ").", - local_remaining_delay, event->time, state->next_mode->deactivation_time); + local_remaining_delay, event->base.tag.time, state->next_mode->deactivation_time); tag_t schedule_tag = {.time = current_logical_tag.time + local_remaining_delay, .microstep = (local_remaining_delay == 0 ? current_logical_tag.microstep + 1 : 0)}; _lf_schedule_at_tag(env, event->trigger, schedule_tag, event->token); diff --git a/core/reactor.c b/core/reactor.c index d53dd2550..f16a46baa 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -250,7 +250,7 @@ int next(environment_t* env) { // Advance current tag to match that of the first event on the queue. // We can now leave the critical section. Any events that will be added // to the queue asynchronously will have a later tag than the current one. - _lf_advance_logical_tag(env, next_tag); + _lf_advance_tag(env, next_tag); // Trigger shutdown reactions if appropriate. if (lf_tag_compare(env->current_tag, env->stop_tag) >= 0) { diff --git a/core/reactor_common.c b/core/reactor_common.c index a02d5cb04..1513228ab 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -233,6 +233,7 @@ void _lf_pop_events(environment_t* env) { event_t* event = (event_t*)pqueue_tag_peek(env->event_q); while (event != NULL && lf_tag_compare(event->base.tag, env->current_tag) == 0) { event = (event_t*)pqueue_tag_pop(env->event_q); + printf("pop events: event's reaction = %s.\n", event->trigger->reactions[0]->name); if (event->is_dummy) { LF_PRINT_DEBUG("Popped dummy event from the event queue."); @@ -336,8 +337,8 @@ void _lf_pop_events(environment_t* env) { lf_recycle_event(env, event); - // // Peek at the next event in the event queue. - // event = (event_t*)pqueue_tag_peek(env->event_q); + // Peek at the next event in the event queue. + event = (event_t*)pqueue_tag_peek(env->event_q); }; // LF_PRINT_DEBUG("There are %zu events deferred to the next microstep.", pqueue_size(env->next_q)); @@ -376,7 +377,8 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) { // && (timer->offset != 0 || timer->period != 0)) { event_t* e = lf_get_new_event(env); e->trigger = timer; - e->time = lf_time_logical(env) + timer->offset; + // e->time = lf_time_logical(env) + timer->offset; + e->base.tag = (tag_t) {.time = lf_time_logical(env) + timer->offset, .microstep = 0}; _lf_add_suspended_event(e); return; } @@ -507,6 +509,7 @@ void lf_replace_token(event_t* event, lf_token_t* token) { trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag_t tag, lf_token_t* token) { assert(env != GLOBAL_ENVIRONMENT); + printf("In _lf_schedule_at_tag\n"); tag_t current_logical_tag = env->current_tag; LF_PRINT_DEBUG("_lf_schedule_at_tag() called with tag " PRINTF_TAG " at tag " PRINTF_TAG ".", tag.time - start_time, @@ -547,135 +550,38 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag e->intended_tag = trigger->intended_tag; #endif + event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, tag); + if (found != NULL) { + switch (trigger->policy) { + case drop: + if (found->token != token) { + _lf_done_using(token); + } + lf_recycle_event(env, e); + return (0); + break; + case replace: + // Replace the payload of the event at the head with our + // current payload. + found->is_dummy = false; + lf_replace_token(found, token); + lf_recycle_event(env, e); + return 0; + break; + default: + // Adding a microstep to the original + // intended tag. + tag.microstep++; + e->base.tag = tag; + if (lf_is_tag_after_stop_tag(env, (tag_t){.time = tag.time, .microstep = tag.microstep})) { + // Scheduling e will incur a microstep after the stop tag, + // which is illegal. + lf_recycle_event(env, e); + return 0; + } + } + } pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); - - // event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, e); - // if (found != NULL) { - // if (tag.microstep == 0u) { - // // The microstep is 0, which means that the event is being scheduled - // // at a future time and at the beginning of the skip list of events - // // at that time. - // // In case the event is a dummy event - // // convert it to a real event. - // found->is_dummy = false; - // switch (trigger->policy) { - // case drop: - // if (found->token != token) { - // _lf_done_using(token); - // } - // lf_recycle_event(env, e); - // return (0); - // break; - // case replace: - // // Replace the payload of the event at the head with our - // // current payload. - // lf_replace_token(found, token); - // lf_recycle_event(env, e); - // return 0; - // break; - // default: - // // Adding a microstep to the original - // // intended tag. - // if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = 1})) { - // // Scheduling e will incur a microstep after the stop tag, - // // which is illegal. - // lf_recycle_event(env, e); - // return 0; - // } - // if (found->next != NULL) { - // lf_print_error("_lf_schedule_at_tag: in-order contract violated."); - // return -1; - // } - // found->next = e; - // } - // } else { - // // We are requesting a microstep greater than 0 - // // where there is already an event for this trigger on the event queue. - // // That event may itself be a dummy event for a real event that is - // // also at a microstep greater than 0. - // // We have to insert our event into the chain or append it - // // to the end of the chain, depending on which microstep is lesser. - // microstep_t microstep_of_found = 0; - // if (tag.time == current_logical_tag.time) { - // // This is a situation where the head of the queue - // // is an event with microstep == current_microstep + 1 - // // which should be reflected in our steps calculation. - // microstep_of_found += current_logical_tag.microstep + 1; // Indicating that - // // the found event - // // is at this microstep. - // } - // // Follow the chain of events until the right point - // // to insert the new event. - // while (microstep_of_found < tag.microstep - 1) { - // if (found->next == NULL) { - // // The chain stops short of where we want to be. - // // If it exactly one microstep short of where we want to be, - // // then we don't need a dummy. Otherwise, we do. - // microstep_t undershot_by = (tag.microstep - 1) - microstep_of_found; - // if (undershot_by > 0) { - // found->next = _lf_create_dummy_events(env, trigger, tag.time, e, undershot_by); - // } else { - // found->next = e; - // } - // return 1; - // } - // found = found->next; - // microstep_of_found++; - // } - // // At this point, microstep_of_found == tag.microstep - 1. - // if (found->next == NULL) { - // found->next = e; - // } else { - // switch (trigger->policy) { - // case drop: - // if (found->next->token != token) { - // _lf_done_using(token); - // } - // lf_recycle_event(env, e); - // return 0; - // break; - // case replace: - // // Replace the payload of the event at the head with our - // // current payload. - // lf_replace_token(found->next, token); - // lf_recycle_event(env, e); - // return 0; - // break; - // default: - // // Adding a microstep to the original - // // intended tag. - // if (lf_is_tag_after_stop_tag(env, (tag_t){.time = found->time, .microstep = microstep_of_found + 1})) { - // // Scheduling e will incur a microstep at timeout, - // // which is illegal. - // lf_recycle_event(env, e); - // return 0; - // } - // if (found->next->next != NULL) { - // lf_print_error("_lf_schedule_at_tag: in-order contract violated."); - // return -1; - // } - // found->next->next = e; - // } - // } - // } - // } else { - // // No existing event queued. - // microstep_t relative_microstep = tag.microstep; - // if (tag.time == current_logical_tag.time) { - // relative_microstep -= current_logical_tag.microstep; - // } - // if ((tag.time == current_logical_tag.time && relative_microstep == 1 && env->execution_started) || - // tag.microstep == 0) { - // // Do not need a dummy event if we are scheduling at 1 microstep - // // in the future at current time or at microstep 0 in a future time. - // // Note that if execution hasn't started, then we have to insert dummy events. - // pqueue_insert(env->event_q, e); - // } else { - // // Create a dummy event. Insert it into the queue, and let its next - // // pointer point to the actual event. - // pqueue_insert(env->event_q, _lf_create_dummy_events(env, trigger, tag.time, e, relative_microstep)); - // } - // } trigger_handle_t return_value = env->_lf_handle++; if (env->_lf_handle < 0) { env->_lf_handle = 1; @@ -759,13 +665,13 @@ trigger_handle_t _lf_insert_reactions_for_trigger(environment_t* env, trigger_t* return 1; } -void _lf_advance_logical_tag(environment_t* env, tag_t next_tag) { +void _lf_advance_tag(environment_t* env, tag_t next_tag) { assert(env != GLOBAL_ENVIRONMENT); -// FIXME: The following checks that _lf_advance_logical_tag() +// FIXME: The following checks that _lf_advance_tag() // is being called correctly. Namely, check if logical time // is being pushed past the head of the event queue. This should -// never happen if _lf_advance_logical_tag() is called correctly. +// never happen if _lf_advance_tag() is called correctly. // This is commented out because it will add considerable overhead // to the ordinary execution of LF programs. Instead, there might // be a need for a target property that enables these kinds of logic @@ -774,17 +680,20 @@ void _lf_advance_logical_tag(environment_t* env, tag_t next_tag) { event_t* next_event = (event_t*)pqueue_tag_peek(env->event_q); if (next_event != NULL) { if (lf_tag_compare(next_tag, next_event->base.tag) > 0) { - lf_print_error_and_exit("_lf_advance_logical_tag(): Attempted to move time to " PRINTF_TAG ", which is " + lf_print_error_and_exit("_lf_advance_tag(): Attempted to move tag to " PRINTF_TAG ", which is " "past the head of the event queue, " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep, next_event->base.tag.time - start_time, next_event->base.tag.microstep); } } #endif - if (lf_tag_compare(env->current_tag, next_tag) <= 0) { + if (lf_tag_compare(env->current_tag, next_tag) < 0) { env->current_tag = next_tag; } else { - lf_print_error_and_exit("_lf_advance_logical_tag(): Attempted to move tag back in tag."); + lf_print_error_and_exit("_lf_advance_tag(): Attempted to move (elapsed) tag to " PRINTF_TAG ", which is " + "earlier than or equal to the (elapsed) current tag, " PRINTF_TAG ".", + next_tag.time - start_time, next_tag.microstep, + env->current_tag.time - start_time, env->current_tag.microstep); } LF_PRINT_LOG("Advanced (elapsed) tag to " PRINTF_TAG " at physical time " PRINTF_TIME, next_tag.time - start_time, env->current_tag.microstep, lf_time_physical_elapsed()); @@ -1269,10 +1178,10 @@ void termination(void) { _lf_terminate_modal_reactors(&env[i]); #endif // If the event queue still has events on it, report that. - if (env[i].event_q != NULL && pqueue_size(env[i].event_q) > 0) { + if (env[i].event_q != NULL && pqueue_tag_size(env[i].event_q) > 0) { lf_print_warning("---- There are %zu unprocessed future events on the event queue.", - pqueue_size(env[i].event_q)); - event_t* event = (event_t*)pqueue_peek(env[i].event_q); + pqueue_tag_size(env[i].event_q)); + event_t* event = (event_t*)pqueue_tag_peek(env[i].event_q); interval_t event_time = event->base.tag.time - start_time; lf_print_warning("---- The first future event has timestamp " PRINTF_TIME " after start time.", event_time); } diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index c871bc3cd..80da46e7d 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -477,7 +477,7 @@ void _lf_next_locked(environment_t* env) { } // At this point, finally, we have an event to process. - _lf_advance_logical_tag(env, next_tag); + _lf_advance_tag(env, next_tag); _lf_start_time_step(env); @@ -487,7 +487,7 @@ void _lf_next_locked(environment_t* env) { _lf_trigger_shutdown_reactions(env); } - // Pop all events from event_q with timestamp equal to env->current_tag.time, + // Pop all events from event_q with timestamp equal to env->current_tag, // extract all the reactions triggered by these events, and // stick them into the reaction queue. _lf_pop_events(env); diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index 9852d847c..9fa7c642f 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -40,5 +40,5 @@ void print_reaction(void* reaction) { void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->base.tag.time, e->trigger, e->token); + LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, e->token); } diff --git a/core/utils/pqueue_support.h b/core/utils/pqueue_support.h index b7c0a08c1..00cd0e7dd 100644 --- a/core/utils/pqueue_support.h +++ b/core/utils/pqueue_support.h @@ -61,7 +61,7 @@ static int reaction_matches(void* next, void* curr) { return (next == curr); } * Report a priority equal to the time of the given event. * Used for sorting pointers to event_t structs in the event queue. */ -static pqueue_pri_t get_event_time(void* a) { return (pqueue_pri_t)(((event_t*)a)->time); } +static pqueue_pri_t get_event_time(void* a) { return (pqueue_pri_t)(((event_t*)a)->base.tag.time); } /** * Report a priority equal to the index of the given reaction. @@ -107,7 +107,7 @@ static void print_reaction(void* reaction) { */ static void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("time: " PRINTF_TIME ", trigger: %p, token: %p", e->time, e->trigger, e->token); + LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, e->token); } // ********** Priority Queue Support End diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index 8c5c320c9..e0401f3e2 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -249,7 +249,7 @@ trigger_handle_t _lf_insert_reactions_for_trigger(environment_t* env, trigger_t* * @param env The environment in which we are executing * @param next_tag The tag step to advance to. */ -void _lf_advance_logical_tag(environment_t* env, tag_t next_tag); +void _lf_advance_tag(environment_t* env, tag_t next_tag); /** * @brief Pop all events from event_q with tag equal to current tag. diff --git a/lib/schedule.c b/lib/schedule.c index ecb4b163b..4b817cdc2 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -157,8 +157,8 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int } tag_t intended_tag = (tag_t){.time = env->current_tag.time + delay, .microstep = 0}; - LF_PRINT_DEBUG("lf_schedule_trigger: env->current_tag.time = " PRINTF_TIME ". Total logical delay = " PRINTF_TIME "", - env->current_tag.time, delay); + LF_PRINT_DEBUG("lf_schedule_trigger: env->current_tag = " PRINTF_TAG ". Total logical delay = " PRINTF_TIME "", + env->current_tag.time, env->current_tag.microstep, delay); interval_t min_spacing = trigger->period; event_t* e = lf_get_new_event(env); @@ -204,11 +204,10 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int e->intended_tag = trigger->intended_tag; #endif - // Check for conflicts (a queued event with the same trigger and time). + // Check for conflicts (a queued event with the same trigger and tag). if (min_spacing <= 0) { // No minimum spacing defined. - e->base.tag = intended_tag; - event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, e); + event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, intended_tag); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; @@ -226,7 +225,9 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int } // // Hook the event into the list. // found->next = e; + e->base.tag = intended_tag; trigger->last_tag = intended_tag; + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); return (0); // FIXME: return value } // If there are not conflicts, schedule as usual. If intended time is @@ -254,25 +255,26 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int return (0); case replace: LF_PRINT_DEBUG("Policy is replace. Replacing the previous event."); - // If the event with the previous tag is still on the event - // queue, then replace the token. To find this event, we have - // to construct a dummy event_t struct. - event_t* dummy = lf_get_new_event(env); - // dummy->next = NULL; - dummy->trigger = trigger; - dummy->base.tag = trigger->last_tag; - event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, dummy); + // // If the event with the previous tag is still on the event + // // queue, then replace the token. To find this event, we have + // // to construct a dummy event_t struct. + // event_t* dummy = lf_get_new_event(env); + // // dummy->next = NULL; + // dummy->trigger = trigger; + // dummy->base.tag = trigger->last_tag; + // event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, dummy); + event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, trigger->last_tag); if (found != NULL) { // Recycle the existing token and the new event // and update the token of the existing event. lf_replace_token(found, token); lf_recycle_event(env, e); - lf_recycle_event(env, dummy); + // lf_recycle_event(env, dummy); // Leave the last_tag the same. return (0); } - lf_recycle_event(env, dummy); + // lf_recycle_event(env, dummy); // If the preceding event _has_ been handled, then adjust // the tag to defer the event. @@ -298,13 +300,16 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int intended_tag.time = env->current_tag.time; } #endif + if (intended_tag.time == env->current_tag.time) { + // Increment microstep. + intended_tag.microstep = env->current_tag.microstep + 1; + } // Set the tag of the event. e->base.tag = intended_tag; // Do not schedule events if if the event time is past the stop time // (current microsteps are checked earlier). - // FIXME: Maybe this tag itself should be compared? LF_PRINT_DEBUG("Comparing event with elapsed time " PRINTF_TIME " against stop time " PRINTF_TIME ".", e->base.tag.time - lf_time_start(), env->stop_tag.time - lf_time_start()); if (e->base.tag.time > env->stop_tag.time) { @@ -319,16 +324,17 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int trigger->last_tag = intended_tag; // Queue the event. + // FIXME: Modify the comment below. // NOTE: There is no need for an explicit microstep because // when this is called, all events at the current tag // (time and microstep) have been pulled from the queue, // and any new events added at this tag will go into the reaction_q // rather than the event_q, so anything put in the event_q with this // same time will automatically be executed at the next microstep. - LF_PRINT_LOG("Inserting event in the event queue with elapsed time " PRINTF_TIME ".", e->base.tag.time - lf_time_start()); + LF_PRINT_LOG("Inserting event in the event queue with elapsed tag " PRINTF_TAG ".", e->base.tag.time - lf_time_start(), e->base.tag.microstep); pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); - tracepoint_schedule(env, trigger, e->time - env->current_tag.time); + tracepoint_schedule(env, trigger, e->base.tag.time - env->current_tag.time); // FIXME: make a record of handle and implement unschedule. // NOTE: Rather than wrapping around to get a negative number, From 280b2130485313e147d6b5ba73b95ef88b99483c Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 12 Mar 2024 18:29:29 +0100 Subject: [PATCH 48/95] Address warning in rti test --- test/RTI/rti_common_test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/RTI/rti_common_test.c b/test/RTI/rti_common_test.c index b0fc2d21c..3d2c73af9 100644 --- a/test/RTI/rti_common_test.c +++ b/test/RTI/rti_common_test.c @@ -49,7 +49,8 @@ void set_scheduling_node(int id, int num_upstream, int num_downstream, int* upst // If there is any upstream nodes, store IDs and delays from the upstream nodes into the structure. if (test_rti.scheduling_nodes[id]->num_upstream > 0) { - test_rti.scheduling_nodes[id]->upstream = (int*)calloc(test_rti.scheduling_nodes[id]->num_upstream, sizeof(int)); + test_rti.scheduling_nodes[id]->upstream = + (uint16_t*)calloc(test_rti.scheduling_nodes[id]->num_upstream, sizeof(uint16_t)); test_rti.scheduling_nodes[id]->upstream_delay = (interval_t*)calloc(test_rti.scheduling_nodes[id]->num_upstream, sizeof(interval_t)); for (int i = 0; i < test_rti.scheduling_nodes[id]->num_upstream; i++) { @@ -60,7 +61,7 @@ void set_scheduling_node(int id, int num_upstream, int num_downstream, int* upst // If there is any downstream nodes, store IDs of the downstream nodes into the structure. if (test_rti.scheduling_nodes[id]->num_downstream > 0) { test_rti.scheduling_nodes[id]->downstream = - (int*)calloc(test_rti.scheduling_nodes[id]->num_downstream, sizeof(int)); + (uint16_t*)calloc(test_rti.scheduling_nodes[id]->num_downstream, sizeof(uint16_t)); for (int i = 0; i < test_rti.scheduling_nodes[id]->num_downstream; i++) { test_rti.scheduling_nodes[id]->downstream[i] = downstream[i]; } From 8e6226e66610197dbed25ba0b76059c573e9dda9 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 12:59:41 -0700 Subject: [PATCH 49/95] Apply clang-format --- core/federated/federate.c | 6 +++--- core/modal_models/modes.c | 6 +++--- core/reactor.c | 2 +- core/reactor_common.c | 14 +++++++------- core/utils/pqueue.c | 3 ++- core/utils/pqueue_support.h | 3 ++- include/core/lf_types.h | 4 ++-- lib/schedule.c | 23 ++++++++++++----------- 8 files changed, 32 insertions(+), 29 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 90e6ed16f..d21918904 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1289,7 +1289,7 @@ static void handle_provisional_tag_advance_grant() { PTAG.microstep); // Dummy event points to a NULL trigger. event_t* dummy = _lf_create_dummy_events(env, NULL, PTAG); - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) dummy); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)dummy); } LF_MUTEX_UNLOCK(&env->mutex); @@ -2404,9 +2404,9 @@ tag_t lf_send_next_event_tag(environment_t* env, tag_t tag, bool wait_for_reply) // Create a dummy event that will force this federate to advance time and subsequently // enable progress for downstream federates. Increment the time by ADVANCE_MESSAGE_INTERVAL // to prevent too frequent dummy events. - tag_t dummy_event_tag = (tag_t) {.time = tag.time + ADVANCE_MESSAGE_INTERVAL, .microstep = tag.microstep}; + tag_t dummy_event_tag = (tag_t){.time = tag.time + ADVANCE_MESSAGE_INTERVAL, .microstep = tag.microstep}; event_t* dummy = _lf_create_dummy_events(env, NULL, dummy_event_tag); - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) dummy); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)dummy); } LF_PRINT_DEBUG("Inserted a dummy event for logical time " PRINTF_TIME ".", tag.time - lf_time_start()); diff --git a/core/modal_models/modes.c b/core/modal_models/modes.c index 2cc6443d6..4f8a6e1c2 100644 --- a/core/modal_models/modes.c +++ b/core/modal_models/modes.c @@ -508,7 +508,7 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] LF_PRINT_DEBUG("Modes: Pulling %zu events from the event queue to suspend them. %d events are now suspended.", delayed_removal_count, _lf_suspended_events_num); for (size_t i = 0; i < delayed_removal_count; i++) { - pqueue_tag_remove(env->event_q, (pqueue_tag_element_t*) (delayed_removal[i])); + pqueue_tag_remove(env->event_q, (pqueue_tag_element_t*)(delayed_removal[i])); } free(delayed_removal); @@ -518,8 +518,8 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] if (env->modes->triggered_reactions_request) { // Insert a dummy event in the event queue for the next microstep to make // sure startup/reset reactions (if any) are triggered as soon as possible. - tag_t dummy_event_tag = (tag_t) {.time = env->current_tag.time, .microstep = 1}; - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) _lf_create_dummy_events(env, NULL, dummy_event_tag)); + tag_t dummy_event_tag = (tag_t){.time = env->current_tag.time, .microstep = 1}; + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)_lf_create_dummy_events(env, NULL, dummy_event_tag)); } } } diff --git a/core/reactor.c b/core/reactor.c index f16a46baa..5c431a651 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -237,7 +237,7 @@ int next(environment_t* env) { LF_PRINT_LOG("Next event (elapsed) tag is " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep); // Wait until physical time >= event.time. int finished_sleep = wait_until(env, next_tag.time); - LF_PRINT_LOG("Next event (elapsed) tag is " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep); + LF_PRINT_LOG("Next event (elapsed) tag is " PRINTF_TAG ".", next_tag.time - start_time, next_tag.microstep); if (finished_sleep != 0) { LF_PRINT_DEBUG("***** wait_until was interrupted."); // Sleep was interrupted. This could happen when a physical action diff --git a/core/reactor_common.c b/core/reactor_common.c index 1513228ab..afb08eb2a 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -378,7 +378,7 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) { event_t* e = lf_get_new_event(env); e->trigger = timer; // e->time = lf_time_logical(env) + timer->offset; - e->base.tag = (tag_t) {.time = lf_time_logical(env) + timer->offset, .microstep = 0}; + e->base.tag = (tag_t){.time = lf_time_logical(env) + timer->offset, .microstep = 0}; _lf_add_suspended_event(e); return; } @@ -403,9 +403,9 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) { // Recycle event_t structs, if possible. event_t* e = lf_get_new_event(env); e->trigger = timer; - e->base.tag = (tag_t) {.time = lf_time_logical(env) + delay, .microstep = 0}; + e->base.tag = (tag_t){.time = lf_time_logical(env) + delay, .microstep = 0}; // NOTE: No lock is being held. Assuming this only happens at startup. - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); tracepoint_schedule(env, timer, delay); // Trace even though schedule is not called. } @@ -464,7 +464,7 @@ void _lf_trigger_shutdown_reactions(environment_t* env) { void lf_recycle_event(environment_t* env, event_t* e) { assert(env != GLOBAL_ENVIRONMENT); - e->base.tag = (tag_t) {.time = 0LL, .microstep = 0}; + e->base.tag = (tag_t){.time = 0LL, .microstep = 0}; // e->time = 0LL; e->trigger = NULL; // e->pos = 0; @@ -581,7 +581,7 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag } } } - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); trigger_handle_t return_value = env->_lf_handle++; if (env->_lf_handle < 0) { env->_lf_handle = 1; @@ -692,8 +692,8 @@ void _lf_advance_tag(environment_t* env, tag_t next_tag) { } else { lf_print_error_and_exit("_lf_advance_tag(): Attempted to move (elapsed) tag to " PRINTF_TAG ", which is " "earlier than or equal to the (elapsed) current tag, " PRINTF_TAG ".", - next_tag.time - start_time, next_tag.microstep, - env->current_tag.time - start_time, env->current_tag.microstep); + next_tag.time - start_time, next_tag.microstep, env->current_tag.time - start_time, + env->current_tag.microstep); } LF_PRINT_LOG("Advanced (elapsed) tag to " PRINTF_TAG " at physical time " PRINTF_TIME, next_tag.time - start_time, env->current_tag.microstep, lf_time_physical_elapsed()); diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index 9fa7c642f..0187a37ca 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -40,5 +40,6 @@ void print_reaction(void* reaction) { void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, e->token); + LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, + e->token); } diff --git a/core/utils/pqueue_support.h b/core/utils/pqueue_support.h index 00cd0e7dd..f0840e791 100644 --- a/core/utils/pqueue_support.h +++ b/core/utils/pqueue_support.h @@ -107,7 +107,8 @@ static void print_reaction(void* reaction) { */ static void print_event(void* event) { event_t* e = (event_t*)event; - LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, e->token); + LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, e->trigger, + e->token); } // ********** Priority Queue Support End diff --git a/include/core/lf_types.h b/include/core/lf_types.h index 0135762c8..856c8b695 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -200,8 +200,8 @@ struct event_t { // instant_t time; // Time of release. trigger_t* trigger; // Associated trigger, NULL if this is a dummy event. // size_t pos; // Position in the priority queue. - lf_token_t* token; // Pointer to the token wrapping the value. - bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. + lf_token_t* token; // Pointer to the token wrapping the value. + bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. #ifdef FEDERATED tag_t intended_tag; // The intended tag. #endif diff --git a/lib/schedule.c b/lib/schedule.c index 4b817cdc2..14dbc06ee 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -164,7 +164,7 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int event_t* e = lf_get_new_event(env); // Initialize the next pointer. -// e->next = NULL; + // e->next = NULL; // Set the payload. e->token = token; @@ -211,11 +211,11 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; - // // Skip to the last node in the linked list. - // while (found->next != NULL) { - // found = found->next; - // intended_tag.microstep++; - // } + // // Skip to the last node in the linked list. + // while (found->next != NULL) { + // found = found->next; + // intended_tag.microstep++; + // } if (lf_is_tag_after_stop_tag(env, intended_tag)) { LF_PRINT_DEBUG("Attempt to schedule an event after stop_tag was rejected."); // Scheduling an event will incur a microstep @@ -223,11 +223,11 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int lf_recycle_event(env, e); return 0; } - // // Hook the event into the list. - // found->next = e; + // // Hook the event into the list. + // found->next = e; e->base.tag = intended_tag; trigger->last_tag = intended_tag; - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); return (0); // FIXME: return value } // If there are not conflicts, schedule as usual. If intended time is @@ -331,8 +331,9 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // and any new events added at this tag will go into the reaction_q // rather than the event_q, so anything put in the event_q with this // same time will automatically be executed at the next microstep. - LF_PRINT_LOG("Inserting event in the event queue with elapsed tag " PRINTF_TAG ".", e->base.tag.time - lf_time_start(), e->base.tag.microstep); - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*) e); + LF_PRINT_LOG("Inserting event in the event queue with elapsed tag " PRINTF_TAG ".", + e->base.tag.time - lf_time_start(), e->base.tag.microstep); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); tracepoint_schedule(env, trigger, e->base.tag.time - env->current_tag.time); From 31a5b1b1085a2aeb6cee93a461908bea8bc40a1f Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 14:14:17 -0700 Subject: [PATCH 50/95] Let pqueue_tag be able to compare payloads of elements --- core/environment.c | 2 +- core/reactor_common.c | 1 - core/utils/pqueue_tag.c | 9 +++++++++ include/core/utils/pqueue_tag.h | 19 +++++++++++++++++++ lib/schedule.c | 2 +- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/core/environment.c b/core/environment.c index bf3bb9e02..10c989880 100644 --- a/core/environment.c +++ b/core/environment.c @@ -243,7 +243,7 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke // Initialize our priority queues. // env->event_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_reverse_order, get_event_time, get_event_position, // set_event_position, event_matches, print_event); - env->event_q = pqueue_tag_init(INITIAL_EVENT_QUEUE_SIZE); + env->event_q = pqueue_tag_init_customize(INITIAL_EVENT_QUEUE_SIZE, event_matches); env->recycle_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, set_event_position, event_matches, print_event); // env->next_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, diff --git a/core/reactor_common.c b/core/reactor_common.c index afb08eb2a..495a440b5 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -233,7 +233,6 @@ void _lf_pop_events(environment_t* env) { event_t* event = (event_t*)pqueue_tag_peek(env->event_q); while (event != NULL && lf_tag_compare(event->base.tag, env->current_tag) == 0) { event = (event_t*)pqueue_tag_pop(env->event_q); - printf("pop events: event's reaction = %s.\n", event->trigger->reactions[0]->name); if (event->is_dummy) { LF_PRINT_DEBUG("Popped dummy event from the event queue."); diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 9406ca1ca..1c2efefe4 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -80,6 +80,11 @@ pqueue_tag_t* pqueue_tag_init(size_t initial_size) { pqueue_tag_set_position, pqueue_tag_matches, pqueue_tag_print_element); } +pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_eq_elem_f eqelem) { + return (pqueue_tag_t*)pqueue_init(initial_size, pqueue_tag_compare, pqueue_tag_get_priority, pqueue_tag_get_position, + pqueue_tag_set_position, eqelem, pqueue_tag_print_element); +} + void pqueue_tag_free(pqueue_tag_t* q) { for (int i = 1; i < q->size; i++) { if (q->d[i] != NULL && ((pqueue_tag_element_t*)q->d[i])->is_dynamic) { @@ -108,6 +113,10 @@ pqueue_tag_element_t* pqueue_tag_find_with_tag(pqueue_tag_t* q, tag_t t) { return pqueue_find_equal((pqueue_t*)q, (void*)&element, (pqueue_pri_t)&forever); } +pqueue_tag_element_t* pqueue_tag_find_equal_same_tag(pqueue_tag_t* q, pqueue_tag_element_t* e) { + return pqueue_find_equal_same_priority((pqueue_t*)q, (void*)e); +} + int pqueue_tag_insert_if_no_match(pqueue_tag_t* q, tag_t t) { if (pqueue_tag_find_with_tag(q, t) == NULL) { return pqueue_tag_insert_tag(q, t); diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index d69de5e56..6f5a1ea68 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -69,6 +69,17 @@ typedef pqueue_t pqueue_tag_t; */ pqueue_tag_t* pqueue_tag_init(size_t initial_size); +/** + * @brief Create a priority queue sorted by tags and has a customized payload. + * + * @param eqelem the callback function to check equivalence of entries + * + * The elements of the priority queue will be of type pqueue_tag_element_t. + * The caller should call pqueue_tag_free() when finished with the queue. + * @return A dynamically allocated priority queue or NULL if memory allocation fails. + */ +pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_eq_elem_f eqelem); + /** * @brief Free all memory used by the queue including elements that are marked dynamic. * @@ -124,6 +135,14 @@ int pqueue_tag_insert_if_no_match(pqueue_tag_t* q, tag_t t); */ pqueue_tag_element_t* pqueue_tag_find_with_tag(pqueue_tag_t* q, tag_t t); +/** + * @brief Return the first item with the same tag that matches the supplied element or NULL if there is none. + * @param q The queue. + * @param e The element. + * @return An entry with the specified tag or NULL if there isn't one. + */ +pqueue_tag_element_t* pqueue_tag_find_equal_same_tag(pqueue_tag_t* q, pqueue_tag_element_t* e); + /** * @brief Return highest-ranking item (the one with the least tag) without removing it. * @param q The queue. diff --git a/lib/schedule.c b/lib/schedule.c index 14dbc06ee..3781ef285 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -207,7 +207,7 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Check for conflicts (a queued event with the same trigger and tag). if (min_spacing <= 0) { // No minimum spacing defined. - event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, intended_tag); + event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; From 1d4d05c61cb6b57adbbf965b56927428de09aed6 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 16:19:33 -0700 Subject: [PATCH 51/95] Allow the priority comparison function to return 0 if received priorites are same --- core/reactor_common.c | 4 +-- core/utils/pqueue.c | 2 +- core/utils/pqueue_base.c | 18 ++++++------ core/utils/pqueue_tag.c | 2 +- include/core/utils/pqueue_base.h | 2 +- include/core/utils/pqueue_tag.h | 2 +- lib/schedule.c | 47 +++++++++++--------------------- 7 files changed, 31 insertions(+), 46 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index 495a440b5..8c24c33da 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1181,8 +1181,8 @@ void termination(void) { lf_print_warning("---- There are %zu unprocessed future events on the event queue.", pqueue_tag_size(env[i].event_q)); event_t* event = (event_t*)pqueue_tag_peek(env[i].event_q); - interval_t event_time = event->base.tag.time - start_time; - lf_print_warning("---- The first future event has timestamp " PRINTF_TIME " after start time.", event_time); + lf_print_warning("---- The first future event has timestamp " PRINTF_TAG " after start tag.", + event->base.tag.time - start_time, event->base.tag.microstep); } // Print elapsed times. // If these are negative, then the program failed to start up. diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index 0187a37ca..cdee19e7d 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -13,7 +13,7 @@ #include "util.h" #include "lf_types.h" -int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return (thiz > that); } +int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 1 ? (thiz > that) : 0 ? (thiz == that) : -1; } int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 0; } diff --git a/core/utils/pqueue_base.c b/core/utils/pqueue_base.c index 30d84286e..144cbd68d 100644 --- a/core/utils/pqueue_base.c +++ b/core/utils/pqueue_base.c @@ -60,7 +60,7 @@ void* find_equal(pqueue_t* q, void* e, int pos, pqueue_pri_t max) { void* curr = q->d[pos]; // Stop the recursion when we've surpassed the maximum priority. - if (!curr || q->cmppri(q->getpri(curr), max)) { + if (!curr || q->cmppri(q->getpri(curr), max) == 1) { return NULL; } @@ -93,11 +93,11 @@ void* find_equal_same_priority(pqueue_t* q, void* e, int pos) { // Stop the recursion once we've surpassed the priority of the element // we're looking for. - if (!curr || q->cmppri(q->getpri(curr), q->getpri(e))) { + if (!curr || q->cmppri(q->getpri(curr), q->getpri(e)) == 1) { return NULL; } - if (q->getpri(curr) == q->getpri(e) && q->eqelem(curr, e)) { + if (q->cmppri(q->getpri(curr), q->getpri(e)) == 0 && q->eqelem(curr, e)) { return curr; } else { rval = find_equal_same_priority(q, e, LF_LEFT(pos)); @@ -157,7 +157,7 @@ static size_t maxchild(pqueue_t* q, size_t i) { if (child_node >= q->size) return 0; - if ((child_node + 1) < q->size && (q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node + 1])))) + if ((child_node + 1) < q->size && (q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node + 1])) == 1)) child_node++; /* use right child instead of left */ return child_node; @@ -168,7 +168,7 @@ static size_t bubble_up(pqueue_t* q, size_t i) { void* moving_node = q->d[i]; pqueue_pri_t moving_pri = q->getpri(moving_node); - for (parent_node = LF_PARENT(i); ((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri)); + for (parent_node = LF_PARENT(i); ((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri) == 1); i = parent_node, parent_node = LF_PARENT(i)) { q->d[i] = q->d[parent_node]; q->setpos(q->d[i], i); @@ -184,7 +184,7 @@ static void percolate_down(pqueue_t* q, size_t i) { void* moving_node = q->d[i]; pqueue_pri_t moving_pri = q->getpri(moving_node); - while ((child_node = maxchild(q, i)) && q->cmppri(moving_pri, q->getpri(q->d[child_node]))) { + while ((child_node = maxchild(q, i)) && (q->cmppri(moving_pri, q->getpri(q->d[child_node])) == 1)) { q->d[i] = q->d[child_node]; q->setpos(q->d[i], i); i = child_node; @@ -227,7 +227,7 @@ int pqueue_remove(pqueue_t* q, void* d) { return 0; // Nothing to remove size_t posn = q->getpos(d); q->d[posn] = q->d[--q->size]; - if (q->cmppri(q->getpri(d), q->getpri(q->d[posn]))) + if (q->cmppri(q->getpri(d), q->getpri(q->d[posn])) == 1) bubble_up(q, posn); else percolate_down(q, posn); @@ -320,7 +320,7 @@ static int subtree_is_valid(pqueue_t* q, int pos) { if ((size_t)left_pos < q->size) { /* has a left child */ - if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_LEFT(pos)]))) + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_LEFT(pos)])) == 1) return 0; if (!subtree_is_valid(q, LF_LEFT(pos))) return 0; @@ -332,7 +332,7 @@ static int subtree_is_valid(pqueue_t* q, int pos) { } if ((size_t)right_pos < q->size) { /* has a right child */ - if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_RIGHT(pos)]))) + if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[LF_RIGHT(pos)])) == 1) return 0; if (!subtree_is_valid(q, LF_RIGHT(pos))) return 0; diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 1c2efefe4..53d2375fd 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -33,7 +33,7 @@ static pqueue_pri_t pqueue_tag_get_priority(void* element) { return (pqueue_pri_ * @param priority2 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. */ static int pqueue_tag_compare(pqueue_pri_t priority1, pqueue_pri_t priority2) { - return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag) > 0); + return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag)); } /** diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 8c9fc8f2c..0656abad8 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -81,7 +81,7 @@ typedef struct pqueue_t { * @param n the initial estimate of the number of queue items for which memory * should be preallocated * @param cmppri The callback function to run to compare two elements - * This callback should return 0 for 'lower' and non-zero + * This callback should return -1 for 'lower', 0 for 'same', and 1 * for 'higher', or vice versa if reverse priority is desired * @param getpri the callback function to run to set a score to an element * @param getpos the callback function to get the current element's position diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index 6f5a1ea68..51bff8d46 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -71,7 +71,7 @@ pqueue_tag_t* pqueue_tag_init(size_t initial_size); /** * @brief Create a priority queue sorted by tags and has a customized payload. - * + * * @param eqelem the callback function to check equivalence of entries * * The elements of the priority queue will be of type pqueue_tag_element_t. diff --git a/lib/schedule.c b/lib/schedule.c index 3781ef285..f588cefaf 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -207,15 +207,11 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Check for conflicts (a queued event with the same trigger and tag). if (min_spacing <= 0) { // No minimum spacing defined. + e->base.tag = intended_tag; event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { intended_tag.microstep++; - // // Skip to the last node in the linked list. - // while (found->next != NULL) { - // found = found->next; - // intended_tag.microstep++; - // } if (lf_is_tag_after_stop_tag(env, intended_tag)) { LF_PRINT_DEBUG("Attempt to schedule an event after stop_tag was rejected."); // Scheduling an event will incur a microstep @@ -223,8 +219,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int lf_recycle_event(env, e); return 0; } - // // Hook the event into the list. - // found->next = e; e->base.tag = intended_tag; trigger->last_tag = intended_tag; pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); @@ -255,26 +249,24 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int return (0); case replace: LF_PRINT_DEBUG("Policy is replace. Replacing the previous event."); - // // If the event with the previous tag is still on the event - // // queue, then replace the token. To find this event, we have - // // to construct a dummy event_t struct. - // event_t* dummy = lf_get_new_event(env); - // // dummy->next = NULL; - // dummy->trigger = trigger; - // dummy->base.tag = trigger->last_tag; - // event_t* found = (event_t*)pqueue_find_equal_same_priority(env->event_q, dummy); - event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, trigger->last_tag); + // If the event with the previous tag is still on the event + // queue, then replace the token. To find this event, we have + // to construct a dummy event_t struct. + event_t* dummy = lf_get_new_event(env); + dummy->trigger = trigger; + dummy->base.tag = trigger->last_tag; + event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)dummy); if (found != NULL) { // Recycle the existing token and the new event // and update the token of the existing event. lf_replace_token(found, token); lf_recycle_event(env, e); - // lf_recycle_event(env, dummy); + lf_recycle_event(env, dummy); // Leave the last_tag the same. return (0); } - // lf_recycle_event(env, dummy); + lf_recycle_event(env, dummy); // If the preceding event _has_ been handled, then adjust // the tag to defer the event. @@ -308,12 +300,12 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Set the tag of the event. e->base.tag = intended_tag; - // Do not schedule events if if the event time is past the stop time - // (current microsteps are checked earlier). - LF_PRINT_DEBUG("Comparing event with elapsed time " PRINTF_TIME " against stop time " PRINTF_TIME ".", - e->base.tag.time - lf_time_start(), env->stop_tag.time - lf_time_start()); - if (e->base.tag.time > env->stop_tag.time) { - LF_PRINT_DEBUG("lf_schedule_trigger: event time is past the timeout. Discarding event."); + // Do not schedule events if if the event time is past the stop tag. + LF_PRINT_DEBUG("Comparing event with elapsed tag " PRINTF_TAG " against stop tag " PRINTF_TAG ".", + e->base.tag.time - lf_time_start(), e->base.tag.microstep, env->stop_tag.time - lf_time_start(), + env->stop_tag.microstep); + if (lf_is_tag_after_stop_tag(env, intended_tag)) { + LF_PRINT_DEBUG("lf_schedule_trigger: event tag is past the timeout. Discarding event."); _lf_done_using(token); lf_recycle_event(env, e); return (0); @@ -324,13 +316,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int trigger->last_tag = intended_tag; // Queue the event. - // FIXME: Modify the comment below. - // NOTE: There is no need for an explicit microstep because - // when this is called, all events at the current tag - // (time and microstep) have been pulled from the queue, - // and any new events added at this tag will go into the reaction_q - // rather than the event_q, so anything put in the event_q with this - // same time will automatically be executed at the next microstep. LF_PRINT_LOG("Inserting event in the event queue with elapsed tag " PRINTF_TAG ".", e->base.tag.time - lf_time_start(), e->base.tag.microstep); pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); From 2ccd7cb99bead62063fb98c03882f23952efe209 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 16:49:43 -0700 Subject: [PATCH 52/95] Cleanup codes --- core/environment.c | 5 ----- core/reactor.c | 6 ------ core/reactor_common.c | 37 +------------------------------- core/threaded/reactor_threaded.c | 9 +------- core/utils/pqueue_tag.c | 2 ++ include/core/environment.h | 3 +-- include/core/lf_types.h | 11 ++++------ include/core/utils/pqueue_tag.h | 12 +++++++++-- 8 files changed, 19 insertions(+), 66 deletions(-) diff --git a/core/environment.c b/core/environment.c index 10c989880..1ec79f773 100644 --- a/core/environment.c +++ b/core/environment.c @@ -167,7 +167,6 @@ void environment_free(environment_t* env) { free(env->is_present_fields_abbreviated); pqueue_tag_free(env->event_q); pqueue_free(env->recycle_q); - // pqueue_free(env->next_q); environment_free_threaded(env); environment_free_single_threaded(env); @@ -241,13 +240,9 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke env->_lf_handle = 1; // Initialize our priority queues. - // env->event_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_reverse_order, get_event_time, get_event_position, - // set_event_position, event_matches, print_event); env->event_q = pqueue_tag_init_customize(INITIAL_EVENT_QUEUE_SIZE, event_matches); env->recycle_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, set_event_position, event_matches, print_event); - // env->next_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, - // set_event_position, event_matches, print_event); // Initialize functionality depending on target properties. environment_init_threaded(env, num_workers); diff --git a/core/reactor.c b/core/reactor.c index 5c431a651..ce6269753 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -221,12 +221,6 @@ int next(environment_t* env) { } } else { next_tag = event->base.tag; - // // Deduce the microstep - // if (next_tag.time == env->current_tag.time) { - // next_tag.microstep = env->current_tag.microstep + 1; - // } else { - // next_tag.microstep = 0; - // } } if (lf_is_tag_after_stop_tag(env, next_tag)) { diff --git a/core/reactor_common.c b/core/reactor_common.c index 8c24c33da..ad7bfc1c0 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -236,10 +236,6 @@ void _lf_pop_events(environment_t* env) { if (event->is_dummy) { LF_PRINT_DEBUG("Popped dummy event from the event queue."); - // if (event->next != NULL) { - // LF_PRINT_DEBUG("Putting event from the event queue for the next microstep."); - // pqueue_insert(env->next_q, event->next); - // } lf_recycle_event(env, event); // Peek at the next event in the event queue. event = (event_t*)pqueue_tag_peek(env->event_q); @@ -328,25 +324,11 @@ void _lf_pop_events(environment_t* env) { // Mark the trigger present. event->trigger->status = present; - // // If this event points to a next event, insert it into the next queue. - // if (event->next != NULL) { - // // Insert the next event into the next queue. - // pqueue_insert(env->next_q, event->next); - // } - lf_recycle_event(env, event); // Peek at the next event in the event queue. event = (event_t*)pqueue_tag_peek(env->event_q); }; - - // LF_PRINT_DEBUG("There are %zu events deferred to the next microstep.", pqueue_size(env->next_q)); - - // // After populating the reaction queue, see if there are things on the - // // next queue to put back into the event queue. - // while (pqueue_peek(env->next_q) != NULL) { - // pqueue_insert(env->event_q, pqueue_pop(env->next_q)); - // } } event_t* lf_get_new_event(environment_t* env) { @@ -376,7 +358,6 @@ void _lf_initialize_timer(environment_t* env, trigger_t* timer) { // && (timer->offset != 0 || timer->period != 0)) { event_t* e = lf_get_new_event(env); e->trigger = timer; - // e->time = lf_time_logical(env) + timer->offset; e->base.tag = (tag_t){.time = lf_time_logical(env) + timer->offset, .microstep = 0}; _lf_add_suspended_event(e); return; @@ -464,15 +445,12 @@ void _lf_trigger_shutdown_reactions(environment_t* env) { void lf_recycle_event(environment_t* env, event_t* e) { assert(env != GLOBAL_ENVIRONMENT); e->base.tag = (tag_t){.time = 0LL, .microstep = 0}; - // e->time = 0LL; e->trigger = NULL; - // e->pos = 0; e->token = NULL; e->is_dummy = false; #ifdef FEDERATED_DECENTRALIZED e->intended_tag = (tag_t){.time = NEVER, .microstep = 0u}; #endif - // e->next = NULL; pqueue_insert(env->recycle_q, e); } @@ -482,18 +460,6 @@ event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t t dummy->is_dummy = true; dummy->trigger = trigger; - // while (offset > 0) { - // if (offset == 1) { - // dummy->next = next; - // break; - // } - // dummy->next = lf_get_new_event(env); - // dummy = dummy->next; - // dummy->time = time; - // dummy->is_dummy = true; - // dummy->trigger = trigger; - // offset--; - // } return dummy; } @@ -508,7 +474,6 @@ void lf_replace_token(event_t* event, lf_token_t* token) { trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag_t tag, lf_token_t* token) { assert(env != GLOBAL_ENVIRONMENT); - printf("In _lf_schedule_at_tag\n"); tag_t current_logical_tag = env->current_tag; LF_PRINT_DEBUG("_lf_schedule_at_tag() called with tag " PRINTF_TAG " at tag " PRINTF_TAG ".", tag.time - start_time, @@ -549,7 +514,7 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag e->intended_tag = trigger->intended_tag; #endif - event_t* found = (event_t*)pqueue_tag_find_with_tag(env->event_q, tag); + event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); if (found != NULL) { switch (trigger->policy) { case drop: diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 80da46e7d..fa8861515 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -288,13 +288,6 @@ tag_t get_next_event_tag(environment_t* env) { } next_tag = event->base.tag; - // if (next_tag.time == env->current_tag.time) { - // LF_PRINT_DEBUG("Earliest event matches current time. Incrementing microstep. Event is dummy: %d.", - // event->is_dummy); - // next_tag.microstep = env->current_tag.microstep + 1; - // } else { - // next_tag.microstep = 0; - // } } // If a timeout tag was given, adjust the next_tag from the @@ -974,7 +967,7 @@ void lf_print_snapshot(environment_t* env) { // accessible here LF_PRINT_DEBUG("Event queue size: %zu. Contents:", pqueue_tag_size(env->event_q)); // FIXME: There is no pqueue_tag_dump now - // pqueue_dump(env->event_q, print_reaction); + pqueue_tag_dump(env->event_q); LF_PRINT_DEBUG(">>> END Snapshot"); } } diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 53d2375fd..68e921e72 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -158,3 +158,5 @@ void pqueue_tag_remove_up_to(pqueue_tag_t* q, tag_t t) { head = pqueue_tag_peek_tag(q); } } + +void pqueue_tag_dump(pqueue_tag_t* q) { pqueue_dump((pqueue_t*)q, pqueue_tag_print_element); } \ No newline at end of file diff --git a/include/core/environment.h b/include/core/environment.h index 01b388d40..00084b8a6 100644 --- a/include/core/environment.h +++ b/include/core/environment.h @@ -73,9 +73,8 @@ typedef struct environment_t { int id; tag_t current_tag; tag_t stop_tag; - pqueue_t* event_q; + pqueue_tag_t* event_q; pqueue_t* recycle_q; - // pqueue_t* next_q; bool** is_present_fields; int is_present_fields_size; bool** is_present_fields_abbreviated; diff --git a/include/core/lf_types.h b/include/core/lf_types.h index 856c8b695..d70447159 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -196,16 +196,13 @@ typedef struct event_t event_t; /** Event activation record to push onto the event queue. */ struct event_t { - pqueue_tag_element_t base; // Elements of pqueue_tag - // instant_t time; // Time of release. - trigger_t* trigger; // Associated trigger, NULL if this is a dummy event. - // size_t pos; // Position in the priority queue. - lf_token_t* token; // Pointer to the token wrapping the value. - bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. + pqueue_tag_element_t base; // Elements of pqueue_tag. It contains tag of release and position in the priority queue. + trigger_t* trigger; // Associated trigger, NULL if this is a dummy event. + lf_token_t* token; // Pointer to the token wrapping the value. + bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. #ifdef FEDERATED tag_t intended_tag; // The intended tag. #endif - // event_t* next; // Pointer to the next event lined up in superdense time. }; /** diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index 51bff8d46..1a525c676 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -70,9 +70,9 @@ typedef pqueue_t pqueue_tag_t; pqueue_tag_t* pqueue_tag_init(size_t initial_size); /** - * @brief Create a priority queue sorted by tags and has a customized payload. + * @brief Create a priority queue sorted by tags and has a payload that requires a particular comparison function. * - * @param eqelem the callback function to check equivalence of entries + * @param eqelem the callback function to check equivalence of payloads. * * The elements of the priority queue will be of type pqueue_tag_element_t. * The caller should call pqueue_tag_free() when finished with the queue. @@ -194,4 +194,12 @@ void pqueue_tag_remove(pqueue_tag_t* q, pqueue_tag_element_t* e); */ void pqueue_tag_remove_up_to(pqueue_tag_t* q, tag_t t); +/** + * Dump the queue and it's internal structure. + * @internal + * debug function only + * @param q the queue + */ +void pqueue_tag_dump(pqueue_tag_t* q); + #endif // PQUEUE_TAG_H From ca62f29a3d5f64cd65a28bf32ed3585bce43f979 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 12 Mar 2024 19:00:48 -0700 Subject: [PATCH 53/95] Add a function for finding an element in a priority queue with the priority --- core/federated/federate.c | 3 --- core/modal_models/modes.c | 11 --------- core/utils/pqueue.c | 2 +- core/utils/pqueue_base.c | 39 ++++++++++++++++++++++++++++++-- core/utils/pqueue_tag.c | 7 +++--- include/core/utils/pqueue_base.h | 22 ++++++++++++------ 6 files changed, 56 insertions(+), 28 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index d1ff5160c..6a373bf4d 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1252,9 +1252,6 @@ static void handle_provisional_tag_advance_grant() { // (which it should be). Do not do this if the federate has not fully // started yet. - // instant_t dummy_event_time = PTAG.time; - // microstep_t dummy_event_microstep = PTAG.microstep; - if (lf_tag_compare(env->current_tag, PTAG) == 0) { // The current tag can equal the PTAG if we are at the start time // or if this federate has been able to advance time to the current diff --git a/core/modal_models/modes.c b/core/modal_models/modes.c index 4f8a6e1c2..9529e8632 100644 --- a/core/modal_models/modes.c +++ b/core/modal_models/modes.c @@ -410,17 +410,6 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] tag_t schedule_tag = {.time = current_logical_tag.time + local_remaining_delay, .microstep = (local_remaining_delay == 0 ? current_logical_tag.microstep + 1 : 0)}; _lf_schedule_at_tag(env, event->trigger, schedule_tag, event->token); - - // Also schedule events stacked up in super dense time. - event_t* e = event; - while (e->next != NULL) { - schedule_tag.microstep++; - _lf_schedule_at_tag(env, e->next->trigger, schedule_tag, e->next->token); - event_t* tmp = e->next; - e = tmp->next; - // A fresh event was created by schedule, hence, recycle old one - lf_recycle_event(env, tmp); - } } // A fresh event was created by schedule, hence, recycle old one lf_recycle_event(env, event); diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index cdee19e7d..8ae122fc3 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -13,7 +13,7 @@ #include "util.h" #include "lf_types.h" -int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 1 ? (thiz > that) : 0 ? (thiz == that) : -1; } +int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return (thiz > that) ? 1 : (thiz < that) ? -1 : 0; } int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 0; } diff --git a/core/utils/pqueue_base.c b/core/utils/pqueue_base.c index 144cbd68d..1580efde7 100644 --- a/core/utils/pqueue_base.c +++ b/core/utils/pqueue_base.c @@ -76,6 +76,39 @@ void* find_equal(pqueue_t* q, void* e, int pos, pqueue_pri_t max) { return NULL; } +void* find_same_priority(pqueue_t* q, void* e, int pos) { + if (pos < 0) { + lf_print_error_and_exit("find_same_priority() called with a negative pos index."); + } + + // Stop the recursion when we've reached the end of the + // queue. This has to be done before accessing the queue + // to avoid segmentation fault. + if (!q || (size_t)pos >= q->size) { + return NULL; + } + + void* rval; + void* curr = q->d[pos]; + + // Stop the recursion once we've surpassed the priority of the element + // we're looking for. + if (!curr || q->cmppri(q->getpri(curr), q->getpri(e)) == 1) { + return NULL; + } + + if (q->cmppri(q->getpri(curr), q->getpri(e)) == 0) { + return curr; + } else { + rval = find_same_priority(q, e, LF_LEFT(pos)); + if (rval) + return rval; + else + return find_same_priority(q, e, LF_RIGHT(pos)); + } + return NULL; +} + void* find_equal_same_priority(pqueue_t* q, void* e, int pos) { if (pos < 0) { lf_print_error_and_exit("find_equal_same_priority() called with a negative pos index."); @@ -194,10 +227,12 @@ static void percolate_down(pqueue_t* q, size_t i) { q->setpos(moving_node, i); } -void* pqueue_find_equal_same_priority(pqueue_t* q, void* e) { return find_equal_same_priority(q, e, 1); } - void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max) { return find_equal(q, e, 1, max); } +void* pqueue_find_same_priority(pqueue_t* q, void* e) { return find_same_priority(q, e, 1); } + +void* pqueue_find_equal_same_priority(pqueue_t* q, void* e) { return find_equal_same_priority(q, e, 1); } + int pqueue_insert(pqueue_t* q, void* d) { void** tmp; size_t i; diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 68e921e72..c07d83f51 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -106,11 +106,10 @@ int pqueue_tag_insert_tag(pqueue_tag_t* q, tag_t t) { } pqueue_tag_element_t* pqueue_tag_find_with_tag(pqueue_tag_t* q, tag_t t) { - // Create elements on the stack. These elements are only needed during - // the duration of this function call, so putting them on the stack is OK. + // Create an element on the stack. This element is only needed during + // the duration of this function call, so putting it on the stack is OK. pqueue_tag_element_t element = {.tag = t, .pos = 0, .is_dynamic = false}; - pqueue_tag_element_t forever = {.tag = FOREVER_TAG, .pos = 0, .is_dynamic = false}; - return pqueue_find_equal((pqueue_t*)q, (void*)&element, (pqueue_pri_t)&forever); + return pqueue_find_same_priority((pqueue_t*)q, (void*)&element); } pqueue_tag_element_t* pqueue_tag_find_equal_same_tag(pqueue_tag_t* q, pqueue_tag_element_t* e) { diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 0656abad8..16e58abf0 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -140,23 +140,31 @@ void* pqueue_pop(pqueue_t* q); void pqueue_empty_into(pqueue_t** dest, pqueue_t** src); /** - * Find the highest-ranking item with the same priority that matches the - * supplied entry. + * Find the highest-ranking item with priority up to and including the given + * maximum priority that matches the supplied entry. * @param q the queue * @param e the entry to compare against + * @param max_priority the maximum priority to consider * @return NULL if no matching event has been found, otherwise the entry */ -void* pqueue_find_equal_same_priority(pqueue_t* q, void* e); +void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); /** - * Find the highest-ranking item with priority up to and including the given - * maximum priority that matches the supplied entry. + * Find the highest-ranking item with the same priority. * @param q the queue * @param e the entry to compare against - * @param max_priority the maximum priority to consider * @return NULL if no matching event has been found, otherwise the entry */ -void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); +void* pqueue_find_same_priority(pqueue_t* q, void* e); + +/** + * Find the highest-ranking item with the same priority that matches the + * supplied entry. + * @param q the queue + * @param e the entry to compare against + * @return NULL if no matching event has been found, otherwise the entry + */ +void* pqueue_find_equal_same_priority(pqueue_t* q, void* e); /** * Remove an item from the queue. From 016b314612ceebc30a09aeb3d4d352a79ca7d5b3 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Sun, 17 Mar 2024 10:04:08 +0100 Subject: [PATCH 54/95] Remove redundant check against less-than-zero for uint32 --- core/federated/network/net_util.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/federated/network/net_util.c b/core/federated/network/net_util.c index 568c692de..3ab04c5a2 100644 --- a/core/federated/network/net_util.c +++ b/core/federated/network/net_util.c @@ -413,10 +413,6 @@ void extract_header(unsigned char* buffer, uint16_t* port_id, uint16_t* federate // The next four bytes are the message length. uint32_t local_length_signed = extract_uint32(&(buffer[sizeof(uint16_t) + sizeof(uint16_t)])); - if (local_length_signed < 0) { - lf_print_error_and_exit("Received an invalid message length (%d) from federate %d.", local_length_signed, - *federate_id); - } *length = (size_t)local_length_signed; // printf("DEBUG: Federate receiving message to port %d to federate %d of length %d.\n", port_id, federate_id, From 345f7b0d5ec9916d87d1447109113e93fdaf0be8 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Mon, 18 Mar 2024 16:10:11 +0100 Subject: [PATCH 55/95] Add suggestions from code-revierw --- core/federated/federate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/federated/federate.c b/core/federated/federate.c index f3f2eb85b..881ecce28 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -89,7 +89,9 @@ federate_instance_t _fed = {.socket_TCP_RTI = -1, .has_downstream = false, .received_stop_request_from_rti = false, .last_sent_LTC.time = NEVER, + .last_sent_LTC.microstep = 0u, .last_sent_NET.time = NEVER, + .last_sent_NET.microstep = 0u, .min_delay_from_physical_action_to_federate_output = NEVER}; federation_metadata_t federation_metadata = { From ad6572268b7bfbaaee185d6a6a3cec2179163a9d Mon Sep 17 00:00:00 2001 From: erlingrj Date: Mon, 18 Mar 2024 18:11:55 +0100 Subject: [PATCH 56/95] Just use NEVER_TAG (since we dont do Werror on macOS) --- core/federated/federate.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 881ecce28..36e193d59 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -88,10 +88,8 @@ federate_instance_t _fed = {.socket_TCP_RTI = -1, .has_upstream = false, .has_downstream = false, .received_stop_request_from_rti = false, - .last_sent_LTC.time = NEVER, - .last_sent_LTC.microstep = 0u, - .last_sent_NET.time = NEVER, - .last_sent_NET.microstep = 0u, + .last_sent_LTC = NEVER_TAG, + .last_sent_NET = NEVER_TAG, .min_delay_from_physical_action_to_federate_output = NEVER}; federation_metadata_t federation_metadata = { From 9fff5e22b4e97a3c23c5bf2e3fc050037b7b5a9c Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 19 Mar 2024 18:33:31 +0100 Subject: [PATCH 57/95] Warning-free tag assignment.. --- core/federated/federate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 36e193d59..584e9fc3b 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -88,8 +88,8 @@ federate_instance_t _fed = {.socket_TCP_RTI = -1, .has_upstream = false, .has_downstream = false, .received_stop_request_from_rti = false, - .last_sent_LTC = NEVER_TAG, - .last_sent_NET = NEVER_TAG, + .last_sent_LTC = {.time = NEVER, .microstep = 0u}, + .last_sent_NET = {.time = NEVER, .microstep = 0u}, .min_delay_from_physical_action_to_federate_output = NEVER}; federation_metadata_t federation_metadata = { From 15d82526c3ee86910bc18881f090b77a8c0f21bd Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 20 Mar 2024 15:54:11 +0100 Subject: [PATCH 58/95] Make the zephyr kernel clock the default clock on Zephyr --- .../api/platform/lf_zephyr_board_support.h | 26 +++---------------- .../api/platform/lf_zephyr_support.h | 23 ---------------- low_level_platform/impl/CMakeLists.txt | 1 + .../impl/src/lf_zephyr_clock_counter.c | 1 - 4 files changed, 4 insertions(+), 47 deletions(-) diff --git a/low_level_platform/api/platform/lf_zephyr_board_support.h b/low_level_platform/api/platform/lf_zephyr_board_support.h index 77834e985..b68317f8c 100644 --- a/low_level_platform/api/platform/lf_zephyr_board_support.h +++ b/low_level_platform/api/platform/lf_zephyr_board_support.h @@ -34,55 +34,37 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Default options #define LF_ZEPHYR_THREAD_PRIORITY_DEFAULT 5 #define LF_ZEPHYR_STACK_SIZE_DEFAULT 2048 +#define LF_ZEPHYR_CLOCK_KERNEL -// Unless the user explicitly asks for the kernel clock, then we use a counter -// clock because it is more precise. -#if !defined(LF_ZEPHYR_CLOCK_KERNEL) +#if defined(LF_ZEPHYR_CLOCK_COUNTER) #if defined(CONFIG_SOC_FAMILY_NRF) -#define LF_ZEPHYR_CLOCK_COUNTER #define LF_TIMER DT_NODELABEL(timer1) #define LF_WAKEUP_OVERHEAD_US 100 #define LF_MIN_SLEEP_US 10 #define LF_RUNTIME_OVERHEAD_US 19 #elif defined(CONFIG_BOARD_ATSAMD20_XPRO) #define LF_TIMER DT_NODELABEL(tc4) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_SOC_FAMILY_SAM) #define LF_TIMER DT_NODELABEL(tc0) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_COUNTER_MICROCHIP_MCP7940N) -#define LF_ZEPHYR_CLOCK_COUNTER #define LF_TIMER DT_NODELABEL(extrtc0) #elif defined(CONFIG_COUNTER_RTC0) -#define LF_ZEPHYR_CLOCK_COUNTER #define LF_TIMER DT_NODELABEL(rtc0) #elif defined(CONFIG_COUNTER_RTC_STM32) #define LF_TIMER DT_INST(0, st_stm32_rtc) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER) #define LF_TIMER DT_INST(0, xlnx_xps_timer_1_00_a) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_COUNTER_TMR_ESP32) #define LF_TIMER DT_NODELABEL(timer0) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_COUNTER_MCUX_CTIMER) #define LF_TIMER DT_NODELABEL(ctimer0) -#define LF_ZEPHYR_CLOCK_COUNTER #elif defined(CONFIG_SOC_MIMXRT1176_CM7) #define LF_TIMER DT_NODELABEL(gpt2) -#define LF_ZEPHYR_CLOCK_COUNTER #else // This board does not have support for the counter clock. If the user // explicitly asked for this cock, then throw an error. -#if defined(LF_ZEPHYR_CLOCK_COUNTER) #error "LF_ZEPHYR_CLOCK_COUNTER was requested but it is not supported by the board" -#else -#define LF_ZEPHYR_CLOCK_KERNEL #endif -#endif // BOARD -#endif - -#if defined(LF_ZEPHYR_CLOCK_COUNTER) #ifndef LF_WAKEUP_OVERHEAD_US #define LF_WAKEUP_OVERHEAD_US 0 #endif @@ -99,9 +81,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define LF_TIMER_ALARM_CHANNEL 0 #endif #else -#if !defined(LF_ZEPHYR_CLOCK_KERNEL) -#error Neither hi-res nor lo-res clock specified -#endif +#define LF_ZEPHYR_CLOCK_KERNEL #endif // LF_ZEPHYR_CLOCK_COUNTER #endif diff --git a/low_level_platform/api/platform/lf_zephyr_support.h b/low_level_platform/api/platform/lf_zephyr_support.h index 49172eb21..0f7ab6b4d 100644 --- a/low_level_platform/api/platform/lf_zephyr_support.h +++ b/low_level_platform/api/platform/lf_zephyr_support.h @@ -49,29 +49,6 @@ typedef struct { } lf_cond_t; typedef struct k_thread* lf_thread_t; -/** - * @brief Add `value` to `*ptr` and return original value of `*ptr` - */ -int _zephyr_atomic_fetch_add(int* ptr, int value); -/** - * @brief Add `value` to `*ptr` and return new updated value of `*ptr` - */ -int _zephyr_atomic_add_fetch(int* ptr, int value); - -/** - * @brief Compare and swap for boolaen value. - * If `*ptr` is equal to `value` then overwrite it - * with `newval`. If not do nothing. Retruns true on overwrite. - */ -bool _zephyr_bool_compare_and_swap(bool* ptr, bool value, bool newval); - -/** - * @brief Compare and swap for integers. If `*ptr` is equal - * to `value`, it is updated to `newval`. The function returns - * the original value of `*ptr`. - */ -int _zephyr_val32_compare_and_swap(uint32_t* ptr, int value, int newval); - #endif // !LF_SINGLE_THREADED #endif // LF_ZEPHYR_SUPPORT_H diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 7641dd663..9ce7fc925 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -45,3 +45,4 @@ low_level_platform_define(MODAL_REACTORS) low_level_platform_define(USER_THREADS) low_level_platform_define(NUMBER_OF_WORKERS) low_level_platform_define(NUMBER_OF_WATCHDOGS) +low_level_platform_define(LF_ZEPHYR_CLOCK_COUNTER) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_counter.c b/low_level_platform/impl/src/lf_zephyr_clock_counter.c index fcb285d44..0e455605f 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_counter.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_counter.c @@ -24,7 +24,6 @@ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************/ - /** * @brief This implements the timing-related platform API ontop of the Zephyr * Counter API. The Counter API is a generic interface to a timer peripheral. It From 64f299b05cd5be511a7e6c770d75a5937c9aed85 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 21 Mar 2024 09:05:45 +0100 Subject: [PATCH 59/95] Use Kconfig to enable/disable counter clock for zephyr --- low_level_platform/api/platform/lf_zephyr_board_support.h | 7 ++----- low_level_platform/impl/CMakeLists.txt | 8 +++++--- low_level_platform/impl/src/lf_zephyr_clock_counter.c | 2 +- low_level_platform/impl/src/lf_zephyr_clock_kernel.c | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/low_level_platform/api/platform/lf_zephyr_board_support.h b/low_level_platform/api/platform/lf_zephyr_board_support.h index b68317f8c..92ece79f6 100644 --- a/low_level_platform/api/platform/lf_zephyr_board_support.h +++ b/low_level_platform/api/platform/lf_zephyr_board_support.h @@ -34,9 +34,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Default options #define LF_ZEPHYR_THREAD_PRIORITY_DEFAULT 5 #define LF_ZEPHYR_STACK_SIZE_DEFAULT 2048 -#define LF_ZEPHYR_CLOCK_KERNEL -#if defined(LF_ZEPHYR_CLOCK_COUNTER) +#if defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) #if defined(CONFIG_SOC_FAMILY_NRF) #define LF_TIMER DT_NODELABEL(timer1) #define LF_WAKEUP_OVERHEAD_US 100 @@ -80,8 +79,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef LF_TIMER_ALARM_CHANNEL #define LF_TIMER_ALARM_CHANNEL 0 #endif -#else -#define LF_ZEPHYR_CLOCK_KERNEL -#endif // LF_ZEPHYR_CLOCK_COUNTER +#endif #endif diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 9ce7fc925..3f9443bab 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -18,12 +18,15 @@ set(LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/platform_internal.c ) if(PLATFORM_ZEPHYR) - message("--- Building Zephyr library") + if(${CONFIG_LF_ZEPHYR_CLOCK_COUNTER}) + message("--- Building Zephyr library with Counter clock ") + else() + message("--- Building Zephyr library with Kernel clock ") + endif() zephyr_library_named(lf-low-level-platform-impl) zephyr_library_sources(${LF_LOW_LEVEL_PLATFORM_FILES}) zephyr_library_link_libraries(kernel) else() -message("--- Building non-Zephyr library") add_library(lf-low-level-platform-impl STATIC ${LF_LOW_LEVEL_PLATFORM_FILES}) endif() add_library(lf::low-level-platform-impl ALIAS lf-low-level-platform-impl) @@ -45,4 +48,3 @@ low_level_platform_define(MODAL_REACTORS) low_level_platform_define(USER_THREADS) low_level_platform_define(NUMBER_OF_WORKERS) low_level_platform_define(NUMBER_OF_WATCHDOGS) -low_level_platform_define(LF_ZEPHYR_CLOCK_COUNTER) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_counter.c b/low_level_platform/impl/src/lf_zephyr_clock_counter.c index 0e455605f..227e01dca 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_counter.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_counter.c @@ -1,6 +1,6 @@ #if defined(PLATFORM_ZEPHYR) #include "platform/lf_zephyr_board_support.h" -#if defined(LF_ZEPHYR_CLOCK_COUNTER) +#if defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) /************* Copyright (c) 2023, Norwegian University of Science and Technology. diff --git a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c index 183eebbbe..ddaaa0ca7 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c @@ -1,6 +1,6 @@ #if defined(PLATFORM_ZEPHYR) #include "platform/lf_zephyr_board_support.h" -#if defined(LF_ZEPHYR_CLOCK_KERNEL) +#if !defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) /************* Copyright (c) 2023, Norwegian University of Science and Technology. From e8ddbb6f23296c3324fca0f014764fd524fdd51e Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 21 Mar 2024 09:09:46 +0100 Subject: [PATCH 60/95] Only print out info about building zephyr lib once --- platform/impl/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/platform/impl/CMakeLists.txt b/platform/impl/CMakeLists.txt index eadea7764..cef66b5ef 100644 --- a/platform/impl/CMakeLists.txt +++ b/platform/impl/CMakeLists.txt @@ -2,12 +2,10 @@ set(LF_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/platform.c) if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - message("--- Building Zephyr library") zephyr_library_named(lf-platform-impl) zephyr_library_sources(${LF_PLATFORM_FILES}) zephyr_library_link_libraries(kernel) else() -message("--- Building non-Zephyr library") add_library(lf-platform-impl STATIC) target_sources(lf-platform-impl PUBLIC ${LF_PLATFORM_FILES}) endif() From aa12f1483474a777dd1a8aa48057fc3b742bb1ff Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 21 Mar 2024 09:12:02 +0100 Subject: [PATCH 61/95] Cmake printing --- low_level_platform/impl/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 13dc93813..676756c77 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -49,9 +49,9 @@ list(APPEND LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/platform_i if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") if(${CONFIG_LF_ZEPHYR_CLOCK_COUNTER}) - message("--- Building Zephyr library with Counter clock ") + message(STATUS "Building Zephyr library with Counter clock ") else() - message("--- Building Zephyr library with Kernel clock ") + message(STATUS "Building Zephyr library with Kernel clock ") endif() zephyr_library_named(lf-low-level-platform-impl) zephyr_library_sources(${LF_LOW_LEVEL_PLATFORM_FILES}) From 8158f7c01ee3db93e7094297862b0d454f9cbc15 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Thu, 21 Mar 2024 21:22:35 -0700 Subject: [PATCH 62/95] Update RTI dockerfile to match file layout change This could harm reproducibility and could increase the size of the RTI image. However, reproducibility is actually not much worse than the status quo which was still copying whole directories. Also, the amount of extra stuff copied is small. In the long run this will keep us from running into further problems as we continue to refactor this repo without testing the dockerized RTI build in CI (I am assuming that it is not worthwhile to add a test for it in CI) --- core/federated/RTI/rti.Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/federated/RTI/rti.Dockerfile b/core/federated/RTI/rti.Dockerfile index 7b30bfa2d..e70e34584 100644 --- a/core/federated/RTI/rti.Dockerfile +++ b/core/federated/RTI/rti.Dockerfile @@ -1,7 +1,6 @@ # Docker file for building the image of the rti FROM alpine:latest -COPY core /lingua-franca/core -COPY include /lingua-franca/include +COPY . /lingua-franca WORKDIR /lingua-franca/core/federated/RTI RUN set -ex && apk add --no-cache gcc musl-dev cmake make && \ mkdir container && \ From 3698799bdf9b12fa2279478245e09898f4fe75ae Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 22 Mar 2024 22:38:47 +0100 Subject: [PATCH 63/95] Make the Zephyr Kernel Clock the default timing service. Also does following improvements: - Use timed wait on semaphore instead of a busy-wait for sleeping - Use Zephyr API for getting a monotonically increasing time. --- .../api/platform/lf_zephyr_board_support.h | 2 +- low_level_platform/impl/CMakeLists.txt | 3 +- .../impl/src/lf_zephyr_clock_counter.c | 2 +- .../impl/src/lf_zephyr_clock_kernel.c | 68 +++++++++++-------- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/low_level_platform/api/platform/lf_zephyr_board_support.h b/low_level_platform/api/platform/lf_zephyr_board_support.h index 92ece79f6..2b6b77e09 100644 --- a/low_level_platform/api/platform/lf_zephyr_board_support.h +++ b/low_level_platform/api/platform/lf_zephyr_board_support.h @@ -35,7 +35,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define LF_ZEPHYR_THREAD_PRIORITY_DEFAULT 5 #define LF_ZEPHYR_STACK_SIZE_DEFAULT 2048 -#if defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) +#if defined(LF_ZEPHYR_CLOCK_COUNTER) #if defined(CONFIG_SOC_FAMILY_NRF) #define LF_TIMER DT_NODELABEL(timer1) #define LF_WAKEUP_OVERHEAD_US 100 diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 676756c77..2322266ec 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -48,7 +48,7 @@ endif() list(APPEND LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/platform_internal.c) if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") - if(${CONFIG_LF_ZEPHYR_CLOCK_COUNTER}) + if(${LF_ZEPHYR_CLOCK_COUNTER}) message(STATUS "Building Zephyr library with Counter clock ") else() message(STATUS "Building Zephyr library with Kernel clock ") @@ -85,3 +85,4 @@ low_level_platform_define(MODAL_REACTORS) low_level_platform_define(USER_THREADS) low_level_platform_define(NUMBER_OF_WORKERS) low_level_platform_define(NUMBER_OF_WATCHDOGS) +low_level_platform_define(LF_ZEPHYR_CLOCK_COUNTER) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_counter.c b/low_level_platform/impl/src/lf_zephyr_clock_counter.c index 227e01dca..0e455605f 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_counter.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_counter.c @@ -1,6 +1,6 @@ #if defined(PLATFORM_ZEPHYR) #include "platform/lf_zephyr_board_support.h" -#if defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) +#if defined(LF_ZEPHYR_CLOCK_COUNTER) /************* Copyright (c) 2023, Norwegian University of Science and Technology. diff --git a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c index ddaaa0ca7..d5e435bfc 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c @@ -1,6 +1,6 @@ #if defined(PLATFORM_ZEPHYR) #include "platform/lf_zephyr_board_support.h" -#if !defined(CONFIG_LF_ZEPHYR_CLOCK_COUNTER) +#if !defined(LF_ZEPHYR_CLOCK_COUNTER) /************* Copyright (c) 2023, Norwegian University of Science and Technology. @@ -41,52 +41,62 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "low_level_platform.h" #include "logging_macros.h" -static int64_t epoch_duration_nsec; -static volatile int64_t last_epoch_nsec = 0; +// Convert Zephyr ticks into an interval_t. According to Zephyr docs the +// ticks are 100Hz for QEMU emulations, and normally a multiple of 10. +#if CONFIG_SYS_CLOCK_TICKS_PER_SEC == 100 +#define TICKS_TO_NSEC(ticks) MSEC(10 * ticks) +#elif CONFIG_SYS_CLOCK_TICKS_PER_SEC == 1000 +#define TICKS_TO_NSEC(ticks) MSEC(ticks) +#elif CONFIG_SYS_CLOCK_TICKS_PER_SEC == 10000 +#define TICKS_TO_NSEC(ticks) USEC(100 * ticks) +#elif CONFIG_SYS_CLOCK_TICKS_PER_SEC == 100000 +#define TICKS_TO_NSEC(ticks) USEC(10 * ticks) +#elif CONFIG_SYS_CLOCK_TICKS_PER_SEC == 1000000 +#define TICKS_TO_NSEC(ticks) USEC(1 * ticks) +#elif CONFIG_SYS_CLOCK_TICKS_PER_SEC == 10000000 +#define TICKS_TO_NSEC(ticks) NSEC(100 * ticks) +#else +#define TICKS_TO_NSEC(ticks) ((SECONDS(1) / CONFIG_SYS_CLOCK_TICKS_PER_SEC) * ticks) +#endif + static uint32_t timer_freq; static volatile bool async_event = false; +// Statically create an initialize the semaphore used for sleeping. +K_SEM_DEFINE(sleeping_sem, 0, 1) + void _lf_initialize_clock() { - timer_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + timer_freq = CONFIG_SYS_CLOCK_TICKS_PER_SEC; LF_PRINT_LOG("--- Using LF Zephyr Kernel Clock with a frequency of %u Hz\n", timer_freq); - last_epoch_nsec = 0; - epoch_duration_nsec = ((1LL << 32) * SECONDS(1)) / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; } -/** - * Detect wraps by storing the previous clock readout. When a clock readout is - * less than the previous we have had a wrap. This only works of `_lf_clock_gettime` - * is invoked at least once per epoch. - */ +/** Uses Zephyr's monotonic increasing uptime count. */ int _lf_clock_gettime(instant_t* t) { - static uint32_t last_read_cycles = 0; - uint32_t now_cycles = k_cycle_get_32(); - if (now_cycles < last_read_cycles) { - last_epoch_nsec += epoch_duration_nsec; - } - *t = (SECOND(1) / CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) * now_cycles + last_epoch_nsec; - last_read_cycles = now_cycles; + interval_t uptime = k_uptime_ticks(); + *t = TICKS_TO_NSEC(uptime); return 0; } -/** - * Interruptable sleep is implemented using busy-waiting. - */ +/** Interruptable sleep is implemented by a taking a semaphore with a timeout. */ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { async_event = false; + interval_t duration = wakeup - lf_time_physical(); + if (wakeup <= 0) { + return 0; + } + if (lf_critical_section_exit(env)) { lf_print_error_and_exit("Failed to exit critical section."); } - instant_t now; - do { - _lf_clock_gettime(&now); - } while ((now < wakeup) && !async_event); + + int res = k_sem_take(sleeping_sem, K_NSEC(duration)); + if (lf_critical_section_enter(env)) { lf_print_error_and_exit("Failed to exit critical section."); } - if (async_event) { + if (res < 0 || async_event == true) { async_event = false; return -1; } else { @@ -95,11 +105,13 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { } /** - * Asynchronous events are notified by setting a flag which breaks the sleeping - * thread out of the busy-wait. + * Asynchronous events are notified by signalling a semaphore which will wakeup + * the runtime if it is sleeping, and setting a flag to indicate what has + * happened. */ int _lf_single_threaded_notify_of_event() { async_event = true; + k_sem_give(sleeping_sem); return 0; } From 189b95376aa194c46d367137ca53b3ea5671fd6b Mon Sep 17 00:00:00 2001 From: erlingrj Date: Fri, 22 Mar 2024 23:03:37 +0100 Subject: [PATCH 64/95] FIx some minor issues --- low_level_platform/impl/src/lf_zephyr_clock_kernel.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c index d5e435bfc..2f191cc90 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c @@ -67,7 +67,7 @@ K_SEM_DEFINE(sleeping_sem, 0, 1) void _lf_initialize_clock() { timer_freq = CONFIG_SYS_CLOCK_TICKS_PER_SEC; - LF_PRINT_LOG("--- Using LF Zephyr Kernel Clock with a frequency of %u Hz\n", timer_freq); + lf_print("--- Using LF Zephyr Kernel Clock with a frequency of %u Hz", timer_freq); } /** Uses Zephyr's monotonic increasing uptime count. */ @@ -90,7 +90,7 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { lf_print_error_and_exit("Failed to exit critical section."); } - int res = k_sem_take(sleeping_sem, K_NSEC(duration)); + int res = k_sem_take(&sleeping_sem, K_NSEC(duration)); if (lf_critical_section_enter(env)) { lf_print_error_and_exit("Failed to exit critical section."); @@ -111,7 +111,7 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { */ int _lf_single_threaded_notify_of_event() { async_event = true; - k_sem_give(sleeping_sem); + k_sem_give(&sleeping_sem); return 0; } From 82cc2765aa7861fa30119b5656e8266ecdbb8f1a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Sat, 23 Mar 2024 09:00:33 +0100 Subject: [PATCH 65/95] Remove unused variable --- low_level_platform/impl/src/lf_zephyr_clock_counter.c | 1 - 1 file changed, 1 deletion(-) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_counter.c b/low_level_platform/impl/src/lf_zephyr_clock_counter.c index 0e455605f..42f3de0e7 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_counter.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_counter.c @@ -42,7 +42,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. static int64_t epoch_duration_nsec; static int64_t epoch_duration_usec; -static uint32_t counter_max_ticks; static volatile int64_t last_epoch_nsec = 0; static uint32_t counter_freq; static volatile bool async_event = false; From 4df720a7d4aad89c09d9cbb5219636b8d65b3833 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Sat, 23 Mar 2024 09:00:37 +0100 Subject: [PATCH 66/95] Fix typo --- low_level_platform/impl/src/lf_zephyr_clock_kernel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c index 2f191cc90..8c1f5ac1a 100644 --- a/low_level_platform/impl/src/lf_zephyr_clock_kernel.c +++ b/low_level_platform/impl/src/lf_zephyr_clock_kernel.c @@ -82,7 +82,7 @@ int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup) { async_event = false; interval_t duration = wakeup - lf_time_physical(); - if (wakeup <= 0) { + if (duration <= 0) { return 0; } From 2a3c2575be15f62b1229f8d8967b03d7fb16887a Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sat, 23 Mar 2024 19:09:46 -0700 Subject: [PATCH 67/95] Address minor werr issue in net_common --- include/core/federated/network/net_common.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/core/federated/network/net_common.h b/include/core/federated/network/net_common.h index 2079f113b..cf34d5920 100644 --- a/include/core/federated/network/net_common.h +++ b/include/core/federated/network/net_common.h @@ -483,7 +483,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST; \ encode_int64(time, &(buffer[1])); \ - assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) @@ -501,7 +500,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_REQUEST_REPLY; \ encode_int64(time, &(buffer[1])); \ - assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) @@ -518,7 +516,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. do { \ buffer[0] = MSG_TYPE_STOP_GRANTED; \ encode_int64(time, &(buffer[1])); \ - assert(microstep >= 0); \ encode_int32((int32_t)microstep, &(buffer[1 + sizeof(instant_t)])); \ } while (0) From 7fa757a498662eaea0fa872f343bc2d97a4814fa Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Mon, 1 Apr 2024 16:47:11 -0700 Subject: [PATCH 68/95] Allow the mac default test --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39267f34f..98493876b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} - all-platforms: ${{ !github.event.pull_request.draft || contains( github.event.pull_request.labels.*.name, 'mac') || contains( github.event.pull_request.labels.*.name, 'windows') }} + all-platforms: true lf-python: needs: [fetch-lf] From a3584f30edcbd8f855d31488b4d31638f9d5f340 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Tue, 2 Apr 2024 20:21:49 -0700 Subject: [PATCH 69/95] Correctly pile up super dense time --- lib/schedule.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/schedule.c b/lib/schedule.c index c63469aa2..6950dce61 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -149,7 +149,8 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int if (!trigger->is_timer) { delay += trigger->offset; } - tag_t intended_tag = (tag_t){.time = env->current_tag.time + delay, .microstep = 0}; + tag_t intended_tag = lf_delay_tag(env->current_tag, delay); + printf("intended tag = " PRINTF_TAG ".\n", intended_tag.time, intended_tag.microstep); LF_PRINT_DEBUG("lf_schedule_trigger: env->current_tag = " PRINTF_TAG ". Total logical delay = " PRINTF_TIME "", env->current_tag.time, env->current_tag.microstep, delay); @@ -173,6 +174,7 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int if (trigger->is_physical) { // Get the current physical time and assign it as the intended time. intended_tag.time = lf_time_physical() + delay; + intended_tag.microstep = 0; } else { // FIXME: We need to verify that we are executing within a reaction? // See reactor_threaded. @@ -205,7 +207,11 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int event_t* found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); // Check for conflicts. Let events pile up in super dense time. if (found != NULL) { - intended_tag.microstep++; + while (found != NULL) { + intended_tag.microstep++; + e->base.tag = intended_tag; + found = (event_t*)pqueue_tag_find_equal_same_tag(env->event_q, (pqueue_tag_element_t*)e); + } if (lf_is_tag_after_stop_tag(env, intended_tag)) { LF_PRINT_DEBUG("Attempt to schedule an event after stop_tag was rejected."); // Scheduling an event will incur a microstep @@ -213,7 +219,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int lf_recycle_event(env, e); return 0; } - e->base.tag = intended_tag; trigger->last_tag = intended_tag; pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)e); return (0); // FIXME: return value @@ -286,9 +291,9 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int intended_tag.time = env->current_tag.time; } #endif - if (intended_tag.time == env->current_tag.time) { + if (lf_tag_compare(intended_tag, env->current_tag) == 0) { // Increment microstep. - intended_tag.microstep = env->current_tag.microstep + 1; + intended_tag.microstep++; } // Set the tag of the event. From 0200a84418299a0eb5ea5c35626e15c0dd6630e2 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 3 Apr 2024 08:06:09 -0700 Subject: [PATCH 70/95] Revert change to CI and minor fix --- .github/workflows/ci.yml | 2 +- lib/schedule.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98493876b..39267f34f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} - all-platforms: true + all-platforms: ${{ !github.event.pull_request.draft || contains( github.event.pull_request.labels.*.name, 'mac') || contains( github.event.pull_request.labels.*.name, 'windows') }} lf-python: needs: [fetch-lf] diff --git a/lib/schedule.c b/lib/schedule.c index 6950dce61..e50274e0c 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -158,9 +158,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int event_t* e = lf_get_new_event(env); - // Initialize the next pointer. - // e->next = NULL; - // Set the payload. e->token = token; @@ -299,7 +296,7 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int // Set the tag of the event. e->base.tag = intended_tag; - // Do not schedule events if if the event time is past the stop tag. + // Do not schedule events if the event time is past the stop tag. LF_PRINT_DEBUG("Comparing event with elapsed tag " PRINTF_TAG " against stop tag " PRINTF_TAG ".", e->base.tag.time - lf_time_start(), e->base.tag.microstep, env->stop_tag.time - lf_time_start(), env->stop_tag.microstep); From 53dacf064145eedad4c5da6b3f6dd0987e741b6f Mon Sep 17 00:00:00 2001 From: erlingrj Date: Tue, 9 Apr 2024 17:40:40 +0200 Subject: [PATCH 71/95] Fix mistake when resolving merge conflicts --- low_level_platform/impl/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 44c9e9366..237b2a01f 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -13,14 +13,12 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") set(LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_clock_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_syscall_support.c ${CMAKE_CURRENT_LIST_DIR}/src/lf_linux_support.c ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_gcc_clang.c ) elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") set(LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_clock_support.c - ${CMAKE_CURRENT_LIST_DIR}/src/lf_unix_syscall_support.c ${CMAKE_CURRENT_LIST_DIR}/src/lf_macos_support.c ${CMAKE_CURRENT_LIST_DIR}/src/lf_atomic_gcc_clang.c ) From 1bd320f000f6a9010c2cf90be7bd7cdcb55d5112 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 10 Apr 2024 12:03:35 -0700 Subject: [PATCH 72/95] Update comments to align with the code --- core/utils/pqueue_tag.c | 3 ++- include/core/utils/pqueue_base.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 061801b99..76f138f20 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -27,7 +27,8 @@ static pqueue_pri_t pqueue_tag_get_priority(void* element) { return (pqueue_pri_ /** * @brief Callback comparison function for the tag-based priority queue. - * Return 0 if the first argument is less than second and 1 otherwise. + * Return -1 if the first argument is less than second, 0 if the two arguments are the same, + * and 1 otherwise. * This function is of type pqueue_cmp_pri_f. * @param priority1 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. * @param priority2 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 16e58abf0..418f2f88e 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -150,7 +150,8 @@ void pqueue_empty_into(pqueue_t** dest, pqueue_t** src); void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); /** - * Find the highest-ranking item with the same priority. + * Find the item with the same priority. This function does not care about + * the element. * @param q the queue * @param e the entry to compare against * @return NULL if no matching event has been found, otherwise the entry @@ -158,8 +159,7 @@ void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); void* pqueue_find_same_priority(pqueue_t* q, void* e); /** - * Find the highest-ranking item with the same priority that matches the - * supplied entry. + * Find the item with the same priority that matches the supplied entry. * @param q the queue * @param e the entry to compare against * @return NULL if no matching event has been found, otherwise the entry From 5ec3325168c0db29e2966cb7a53ae77523d9b43e Mon Sep 17 00:00:00 2001 From: Byeonggil Jun <78055940+byeonggiljun@users.noreply.github.com> Date: Wed, 10 Apr 2024 17:00:23 -0700 Subject: [PATCH 73/95] Apply suggestions from code review Co-authored-by: Edward A. Lee --- core/utils/pqueue_base.c | 2 +- core/utils/pqueue_tag.c | 2 +- include/core/utils/pqueue_base.h | 6 +++--- include/core/utils/pqueue_tag.h | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/core/utils/pqueue_base.c b/core/utils/pqueue_base.c index 1580efde7..c0abb0619 100644 --- a/core/utils/pqueue_base.c +++ b/core/utils/pqueue_base.c @@ -76,7 +76,7 @@ void* find_equal(pqueue_t* q, void* e, int pos, pqueue_pri_t max) { return NULL; } -void* find_same_priority(pqueue_t* q, void* e, int pos) { +static void* find_same_priority(pqueue_t* q, void* e, int pos) { if (pos < 0) { lf_print_error_and_exit("find_same_priority() called with a negative pos index."); } diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 76f138f20..7cb33c4be 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -159,4 +159,4 @@ void pqueue_tag_remove_up_to(pqueue_tag_t* q, tag_t t) { } } -void pqueue_tag_dump(pqueue_tag_t* q) { pqueue_dump((pqueue_t*)q, pqueue_tag_print_element); } \ No newline at end of file +void pqueue_tag_dump(pqueue_tag_t* q) { pqueue_dump((pqueue_t*)q, pqueue_tag_print_element); } diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 418f2f88e..5039fe282 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -150,8 +150,7 @@ void pqueue_empty_into(pqueue_t** dest, pqueue_t** src); void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); /** - * Find the item with the same priority. This function does not care about - * the element. + * Return an entry with the same priority as the specified entry or NULL if there is no such entry. * @param q the queue * @param e the entry to compare against * @return NULL if no matching event has been found, otherwise the entry @@ -159,7 +158,8 @@ void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); void* pqueue_find_same_priority(pqueue_t* q, void* e); /** - * Find the item with the same priority that matches the supplied entry. + * Return an entry with the same priority (determined by `cmppri`) that matches the supplied entry (determined + * by `eqelem`) or `NULL` if there is no such entry. * @param q the queue * @param e the entry to compare against * @return NULL if no matching event has been found, otherwise the entry diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index 1a525c676..35190db71 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -70,7 +70,7 @@ typedef pqueue_t pqueue_tag_t; pqueue_tag_t* pqueue_tag_init(size_t initial_size); /** - * @brief Create a priority queue sorted by tags and has a payload that requires a particular comparison function. + * @brief Create a priority queue sorted by tags and has a payload that requires a particular equivalence checker function. * * @param eqelem the callback function to check equivalence of payloads. * @@ -136,7 +136,8 @@ int pqueue_tag_insert_if_no_match(pqueue_tag_t* q, tag_t t); pqueue_tag_element_t* pqueue_tag_find_with_tag(pqueue_tag_t* q, tag_t t); /** - * @brief Return the first item with the same tag that matches the supplied element or NULL if there is none. + * @brief Return an item with the same tag (`cmppri` returns 0) that matches the supplied element + * (`eqelem` returns non-zero) or NULL if there is none. * @param q The queue. * @param e The element. * @return An entry with the specified tag or NULL if there isn't one. From 3b5027518529609a20ec4ad0cf3be1cf3c25ed02 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 10 Apr 2024 17:08:04 -0700 Subject: [PATCH 74/95] Add an authorship and remove unused functions --- core/utils/pqueue_base.c | 43 +++--------- core/utils/pqueue_support.h | 115 ------------------------------- include/core/utils/pqueue_base.h | 18 +++-- 3 files changed, 17 insertions(+), 159 deletions(-) delete mode 100644 core/utils/pqueue_support.h diff --git a/core/utils/pqueue_base.c b/core/utils/pqueue_base.c index c0abb0619..5d602e1de 100644 --- a/core/utils/pqueue_base.c +++ b/core/utils/pqueue_base.c @@ -29,6 +29,15 @@ * - The provided pqueue_eq_elem_f implementation is used to test and * search for equal elements present in the queue; and * - Removed capability to reassign priorities. + * + * Modified by Byeonggil Jun (Apr, 2024). + * Changes: + * - Made the pqueue_cmp_pri_f function return do the three-way comparison + * rather than the two-way comparison. + * - The changed pqueue_cmp_pri_f function is used to check the equality of + * two elements in the pqueue_find_equal_same_priority function. + * - Remove the pqueue_find_equal function. + * */ #include @@ -44,38 +53,6 @@ #define LF_RIGHT(i) (((i) << 1) + 1) #define LF_PARENT(i) ((i) >> 1) -void* find_equal(pqueue_t* q, void* e, int pos, pqueue_pri_t max) { - if (pos < 0) { - lf_print_error_and_exit("find_equal() called with a negative pos index."); - } - - // Stop the recursion when we've reached the end of the - // queue. This has to be done before accessing the queue - // to avoid segmentation fault. - if (!q || (size_t)pos >= q->size) { - return NULL; - } - - void* rval; - void* curr = q->d[pos]; - - // Stop the recursion when we've surpassed the maximum priority. - if (!curr || q->cmppri(q->getpri(curr), max) == 1) { - return NULL; - } - - if (q->eqelem(curr, e)) { - return curr; - } else { - rval = find_equal(q, e, LF_LEFT(pos), max); - if (rval) - return rval; - else - return find_equal(q, e, LF_RIGHT(pos), max); - } - return NULL; -} - static void* find_same_priority(pqueue_t* q, void* e, int pos) { if (pos < 0) { lf_print_error_and_exit("find_same_priority() called with a negative pos index."); @@ -227,8 +204,6 @@ static void percolate_down(pqueue_t* q, size_t i) { q->setpos(moving_node, i); } -void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max) { return find_equal(q, e, 1, max); } - void* pqueue_find_same_priority(pqueue_t* q, void* e) { return find_same_priority(q, e, 1); } void* pqueue_find_equal_same_priority(pqueue_t* q, void* e) { return find_equal_same_priority(q, e, 1); } diff --git a/core/utils/pqueue_support.h b/core/utils/pqueue_support.h deleted file mode 100644 index 2c462262e..000000000 --- a/core/utils/pqueue_support.h +++ /dev/null @@ -1,115 +0,0 @@ -/************* -Copyright (c) 2022, The University of California at Berkeley. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -***************/ - -/** - * @file pqueue_support.h - * @author Edward A. Lee - * @author Marten Lohstroh - * @brief Header-only support functions for pqueue. - */ - -#ifndef PQUEUE_SUPPORT_H -#define PQUEUE_SUPPORT_H - -#include "../reactor.h" - -// ********** Priority Queue Support Start - -/** - * Return whether the first and second argument are given in reverse order. - */ -static int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that) { return (thiz > that); } - -/** - * Return false (0) regardless of reaction order. - */ -static int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return false; } - -/** - * Return whether or not the given events have matching triggers. - */ -static int event_matches(void* next, void* curr) { return (((event_t*)next)->trigger == ((event_t*)curr)->trigger); } - -/** - * Return whether or not the given reaction_t pointers - * point to the same struct. - */ -static int reaction_matches(void* next, void* curr) { return (next == curr); } - -/** - * Report a priority equal to the time of the given event. - * Used for sorting pointers to event_t structs in the event queue. - */ -static pqueue_pri_t get_event_time(void* a) { return (pqueue_pri_t)(((event_t*)a)->base.tag.time); } - -/** - * Report a priority equal to the index of the given reaction. - * Used for sorting pointers to reaction_t structs in the - * blocked and executing queues. - */ -static pqueue_pri_t get_reaction_index(void* a) { return ((reaction_t*)a)->index; } - -/** - * Return the given event's position in the queue. - */ -static size_t get_event_position(void* a) { return ((event_t*)a)->pos; } - -/** - * Return the given reaction's position in the queue. - */ -static size_t get_reaction_position(void* a) { return ((reaction_t*)a)->pos; } - -/** - * Set the given event's position in the queue. - */ -static void set_event_position(void* a, size_t pos) { ((event_t*)a)->pos = pos; } - -/** - * Return the given reaction's position in the queue. - */ -static void set_reaction_position(void* a, size_t pos) { ((reaction_t*)a)->pos = pos; } - -/** - * Print some information about the given reaction. - * - * DEBUG function only. - */ -static void print_reaction(void* reaction) { - reaction_t* r = (reaction_t*)reaction; - LF_PRINT_DEBUG("%s: chain_id:%llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, (void*)r); -} - -/** - * Print some information about the given event. - * - * DEBUG function only. - */ -static void print_event(void* event) { - event_t* e = (event_t*)event; - LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, - (void*)e->trigger, (void*)e->token); -} - -// ********** Priority Queue Support End -#endif diff --git a/include/core/utils/pqueue_base.h b/include/core/utils/pqueue_base.h index 5039fe282..b913ab64f 100644 --- a/include/core/utils/pqueue_base.h +++ b/include/core/utils/pqueue_base.h @@ -30,6 +30,14 @@ * search for equal elements present in the queue; and * - Removed capability to reassign priorities. * + * Modified by Byeonggil Jun (Apr, 2024). + * Changes: + * - Made the pqueue_cmp_pri_f function return do the three-way comparison + * rather than the two-way comparison. + * - The changed pqueue_cmp_pri_f function is used to check the equality of + * two elements in the pqueue_find_equal_same_priority function. + * - Remove the pqueue_find_equal function. + * * @brief Priority Queue function declarations used as a base for Lingua Franca priority queues. * * @{ @@ -139,16 +147,6 @@ void* pqueue_pop(pqueue_t* q); */ void pqueue_empty_into(pqueue_t** dest, pqueue_t** src); -/** - * Find the highest-ranking item with priority up to and including the given - * maximum priority that matches the supplied entry. - * @param q the queue - * @param e the entry to compare against - * @param max_priority the maximum priority to consider - * @return NULL if no matching event has been found, otherwise the entry - */ -void* pqueue_find_equal(pqueue_t* q, void* e, pqueue_pri_t max_priority); - /** * Return an entry with the same priority as the specified entry or NULL if there is no such entry. * @param q the queue From 4b8d42dd65662087ae0b3db77a5cb844ae115446 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 10 Apr 2024 17:48:31 -0700 Subject: [PATCH 75/95] Make `pqueue_tag_init_customize` more flexible and remove some callback functions for event --- core/environment.c | 8 ++++---- core/reactor_common.c | 4 ++-- core/utils/pqueue.c | 12 +++++------- core/utils/pqueue_tag.c | 23 ++++++++--------------- include/core/environment.h | 2 +- include/core/utils/pqueue.h | 21 +-------------------- include/core/utils/pqueue_tag.h | 17 +++++++++++++++-- 7 files changed, 36 insertions(+), 51 deletions(-) diff --git a/core/environment.c b/core/environment.c index 23061e5ce..8fae82f4c 100644 --- a/core/environment.c +++ b/core/environment.c @@ -185,7 +185,7 @@ void environment_free(environment_t* env) { free(env->is_present_fields); free(env->is_present_fields_abbreviated); pqueue_tag_free(env->event_q); - pqueue_free(env->recycle_q); + pqueue_tag_free(env->recycle_q); environment_free_threaded(env); environment_free_single_threaded(env); @@ -260,9 +260,9 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke env->_lf_handle = 1; // Initialize our priority queues. - env->event_q = pqueue_tag_init_customize(INITIAL_EVENT_QUEUE_SIZE, event_matches); - env->recycle_q = pqueue_init(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, get_event_time, get_event_position, - set_event_position, event_matches, print_event); + env->event_q = pqueue_tag_init_customize(INITIAL_EVENT_QUEUE_SIZE, pqueue_tag_compare, event_matches, print_event); + env->recycle_q = + pqueue_tag_init_customize(INITIAL_EVENT_QUEUE_SIZE, in_no_particular_order, event_matches, print_event); // Initialize functionality depending on target properties. environment_init_threaded(env, num_workers); diff --git a/core/reactor_common.c b/core/reactor_common.c index 097e27aae..00b76b8c4 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -334,7 +334,7 @@ void _lf_pop_events(environment_t* env) { event_t* lf_get_new_event(environment_t* env) { assert(env != GLOBAL_ENVIRONMENT); // Recycle event_t structs, if possible. - event_t* e = (event_t*)pqueue_pop(env->recycle_q); + event_t* e = (event_t*)pqueue_tag_pop(env->recycle_q); if (e == NULL) { e = (event_t*)calloc(1, sizeof(struct event_t)); if (e == NULL) @@ -451,7 +451,7 @@ void lf_recycle_event(environment_t* env, event_t* e) { #ifdef FEDERATED_DECENTRALIZED e->intended_tag = (tag_t){.time = NEVER, .microstep = 0u}; #endif - pqueue_insert(env->recycle_q, e); + pqueue_tag_insert(env->recycle_q, (pqueue_tag_element_t*)e); } event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag) { diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index c2f051534..00c3724f8 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -2,10 +2,14 @@ * @file pqueue.c * @author Marten Lohstroh * @author Edward A. Lee + * @author Byeonggil Jun * @copyright (c) 2020-2023, The University of California at Berkeley. * License: BSD 2-clause * - * @brief Priority queue definitions for the event queue and reaction queue. + * @brief Priority queue definitions for queues where the priority is a number that can be compared with ordinary + * numerical comparisons. + * + * This is used for the reaction queue. The event queue uses a `tag_t` struct for its priority, so it cannot use this. */ #include "low_level_platform.h" @@ -25,16 +29,10 @@ int event_matches(void* event1, void* event2) { return (((event_t*)event1)->trig int reaction_matches(void* a, void* b) { return (a == b); } -pqueue_pri_t get_event_time(void* event) { return (pqueue_pri_t)(((event_t*)event)->base.tag.time); } - pqueue_pri_t get_reaction_index(void* reaction) { return ((reaction_t*)reaction)->index; } -size_t get_event_position(void* event) { return ((event_t*)event)->base.pos; } - size_t get_reaction_position(void* reaction) { return ((reaction_t*)reaction)->pos; } -void set_event_position(void* event, size_t pos) { ((event_t*)event)->base.pos = pos; } - void set_reaction_position(void* reaction, size_t pos) { ((reaction_t*)reaction)->pos = pos; } void print_reaction(void* reaction) { diff --git a/core/utils/pqueue_tag.c b/core/utils/pqueue_tag.c index 7cb33c4be..24899374b 100644 --- a/core/utils/pqueue_tag.c +++ b/core/utils/pqueue_tag.c @@ -25,18 +25,6 @@ */ static pqueue_pri_t pqueue_tag_get_priority(void* element) { return (pqueue_pri_t)element; } -/** - * @brief Callback comparison function for the tag-based priority queue. - * Return -1 if the first argument is less than second, 0 if the two arguments are the same, - * and 1 otherwise. - * This function is of type pqueue_cmp_pri_f. - * @param priority1 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. - * @param priority2 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. - */ -static int pqueue_tag_compare(pqueue_pri_t priority1, pqueue_pri_t priority2) { - return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag)); -} - /** * @brief Callback function to determine whether two elements are equivalent. * Return 1 if the tags contained by given elements are identical, 0 otherwise. @@ -76,14 +64,19 @@ static void pqueue_tag_print_element(void* element) { ////////////////// // Functions defined in pqueue_tag.h. +int pqueue_tag_compare(pqueue_pri_t priority1, pqueue_pri_t priority2) { + return (lf_tag_compare(((pqueue_tag_element_t*)priority1)->tag, ((pqueue_tag_element_t*)priority2)->tag)); +} + pqueue_tag_t* pqueue_tag_init(size_t initial_size) { return (pqueue_tag_t*)pqueue_init(initial_size, pqueue_tag_compare, pqueue_tag_get_priority, pqueue_tag_get_position, pqueue_tag_set_position, pqueue_tag_matches, pqueue_tag_print_element); } -pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_eq_elem_f eqelem) { - return (pqueue_tag_t*)pqueue_init(initial_size, pqueue_tag_compare, pqueue_tag_get_priority, pqueue_tag_get_position, - pqueue_tag_set_position, eqelem, pqueue_tag_print_element); +pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_cmp_pri_f cmppri, pqueue_eq_elem_f eqelem, + pqueue_print_entry_f prt) { + return (pqueue_tag_t*)pqueue_init(initial_size, cmppri, pqueue_tag_get_priority, pqueue_tag_get_position, + pqueue_tag_set_position, eqelem, prt); } void pqueue_tag_free(pqueue_tag_t* q) { diff --git a/include/core/environment.h b/include/core/environment.h index 00084b8a6..a776dee95 100644 --- a/include/core/environment.h +++ b/include/core/environment.h @@ -74,7 +74,7 @@ typedef struct environment_t { tag_t current_tag; tag_t stop_tag; pqueue_tag_t* event_q; - pqueue_t* recycle_q; + pqueue_tag_t* recycle_q; bool** is_present_fields; int is_present_fields_size; bool** is_present_fields_abbreviated; diff --git a/include/core/utils/pqueue.h b/include/core/utils/pqueue.h index e317acbcd..eed4083e2 100644 --- a/include/core/utils/pqueue.h +++ b/include/core/utils/pqueue.h @@ -2,6 +2,7 @@ * @file pqueue.h * @author Marten Lohstroh * @author Edward A. Lee + * @author Byeonggil Jun * @copyright (c) 2020-2023, The University of California at Berkeley. * License: BSD 2-clause * @@ -41,13 +42,6 @@ int event_matches(void* event1, void* event2); */ int reaction_matches(void* a, void* b); -/** - * Report a priority equal to the time of the given event. - * This is used for sorting pointers to event_t structs in the event queue. - * @param a A pointer to an event_t. - */ -pqueue_pri_t get_event_time(void* event); - /** * Report a priority equal to the index of the given reaction. * Used for sorting pointers to reaction_t structs in the @@ -56,25 +50,12 @@ pqueue_pri_t get_event_time(void* event); */ pqueue_pri_t get_reaction_index(void* reaction_t); -/** - * Return the given event's position in the queue. - * @param event A pointer to an event_t. - */ -size_t get_event_position(void* event); - /** * Return the given reaction's position in the queue. * @param reaction A pointer to a reaction_t. */ size_t get_reaction_position(void* reaction); -/** - * Set the given event's position in the queue. - * @param event A pointer to an event_t - * @param pos The position. - */ -void set_event_position(void* event, size_t pos); - /** * Set the given reaction's position in the queue. * @param event A pointer to a reaction_t. diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index 35190db71..1866c2194 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -60,6 +60,16 @@ typedef struct { */ typedef pqueue_t pqueue_tag_t; +/** + * @brief Callback comparison function for the tag-based priority queue. + * Return -1 if the first argument is less than second, 0 if the two arguments are the same, + * and 1 otherwise. + * This function is of type pqueue_cmp_pri_f. + * @param priority1 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. + * @param priority2 A pointer to a pqueue_tag_element_t, cast to pqueue_pri_t. + */ +int pqueue_tag_compare(pqueue_pri_t priority1, pqueue_pri_t priority2); + /** * @brief Create a priority queue sorted by tags. * @@ -70,15 +80,18 @@ typedef pqueue_t pqueue_tag_t; pqueue_tag_t* pqueue_tag_init(size_t initial_size); /** - * @brief Create a priority queue sorted by tags and has a payload that requires a particular equivalence checker function. + * @brief Create a priority queue that stores elements with a particular payload. * + * @param cmppri the callback function to compare priorities * @param eqelem the callback function to check equivalence of payloads. + * @param prt the callback function to print elements * * The elements of the priority queue will be of type pqueue_tag_element_t. * The caller should call pqueue_tag_free() when finished with the queue. * @return A dynamically allocated priority queue or NULL if memory allocation fails. */ -pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_eq_elem_f eqelem); +pqueue_tag_t* pqueue_tag_init_customize(size_t initial_size, pqueue_cmp_pri_f cmppri, pqueue_eq_elem_f eqelem, + pqueue_print_entry_f prt); /** * @brief Free all memory used by the queue including elements that are marked dynamic. From 5c966b50a131053c738a93ffd7329b020277aa49 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 10 Apr 2024 21:33:45 -0700 Subject: [PATCH 76/95] Minor fix --- include/core/reactor_common.h | 4 +++- include/core/utils/pqueue_tag.h | 2 +- lib/schedule.c | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index e0401f3e2..0dbd508b5 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -195,7 +195,9 @@ void _lf_trigger_startup_reactions(environment_t* env); void _lf_trigger_shutdown_reactions(environment_t* env); /** - * Create dummy events to be used as spacers in the event queue. + * @brief Create a dummy event with the specified tag. + * + * A dummy event is an event with no triggers that can be put on the event queue to trigger a tag advance to the specified tag. * @param env Environment in which we are executing. * @param trigger The eventual event to be triggered. * @param tag The tag of that event. diff --git a/include/core/utils/pqueue_tag.h b/include/core/utils/pqueue_tag.h index 1866c2194..e06e074be 100644 --- a/include/core/utils/pqueue_tag.h +++ b/include/core/utils/pqueue_tag.h @@ -1,5 +1,5 @@ /** - * @file tag_pqueue.h + * @file pqueue_tag.h * @author Byeonggil Jun * @author Edward A. Lee * @copyright (c) 2023, The University of California at Berkeley diff --git a/lib/schedule.c b/lib/schedule.c index e50274e0c..5aa9fd528 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -150,7 +150,6 @@ trigger_handle_t lf_schedule_trigger(environment_t* env, trigger_t* trigger, int delay += trigger->offset; } tag_t intended_tag = lf_delay_tag(env->current_tag, delay); - printf("intended tag = " PRINTF_TAG ".\n", intended_tag.time, intended_tag.microstep); LF_PRINT_DEBUG("lf_schedule_trigger: env->current_tag = " PRINTF_TAG ". Total logical delay = " PRINTF_TIME "", env->current_tag.time, env->current_tag.microstep, delay); From 739b696d0728fd4cf79ea3b5749c82984d9aaf57 Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Wed, 10 Apr 2024 21:45:53 -0700 Subject: [PATCH 77/95] Remove the `is_dummy` flag from the `event_q` structure Now, we can know that an event is a dummy event if the trigger is NULL --- core/federated/federate.c | 4 ++-- core/modal_models/modes.c | 4 ++-- core/reactor_common.c | 9 +++------ include/core/lf_types.h | 1 - include/core/reactor_common.h | 6 +++--- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 920f5b4f6..510c50cdd 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1288,7 +1288,7 @@ static void handle_provisional_tag_advance_grant() { env->current_tag.time - start_time, env->current_tag.microstep, PTAG.time - start_time, PTAG.microstep); // Dummy event points to a NULL trigger. - event_t* dummy = _lf_create_dummy_events(env, NULL, PTAG); + event_t* dummy = _lf_create_dummy_events(env, PTAG); pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)dummy); } @@ -2404,7 +2404,7 @@ tag_t lf_send_next_event_tag(environment_t* env, tag_t tag, bool wait_for_reply) // enable progress for downstream federates. Increment the time by ADVANCE_MESSAGE_INTERVAL // to prevent too frequent dummy events. tag_t dummy_event_tag = (tag_t){.time = tag.time + ADVANCE_MESSAGE_INTERVAL, .microstep = tag.microstep}; - event_t* dummy = _lf_create_dummy_events(env, NULL, dummy_event_tag); + event_t* dummy = _lf_create_dummy_events(env, dummy_event_tag); pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)dummy); } diff --git a/core/modal_models/modes.c b/core/modal_models/modes.c index 9529e8632..922d02f9e 100644 --- a/core/modal_models/modes.c +++ b/core/modal_models/modes.c @@ -56,7 +56,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Forward declaration of functions and variables supplied by reactor_common.c void _lf_trigger_reaction(environment_t* env, reaction_t* reaction, int worker_number); -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag); +event_t* _lf_create_dummy_events(environment_t* env, tag_t tag); // ---------------------------------------------------------------------------- @@ -508,7 +508,7 @@ void _lf_process_mode_changes(environment_t* env, reactor_mode_state_t* states[] // Insert a dummy event in the event queue for the next microstep to make // sure startup/reset reactions (if any) are triggered as soon as possible. tag_t dummy_event_tag = (tag_t){.time = env->current_tag.time, .microstep = 1}; - pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)_lf_create_dummy_events(env, NULL, dummy_event_tag)); + pqueue_tag_insert(env->event_q, (pqueue_tag_element_t*)_lf_create_dummy_events(env, dummy_event_tag)); } } } diff --git a/core/reactor_common.c b/core/reactor_common.c index 00b76b8c4..33e5582f5 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -234,7 +234,7 @@ void _lf_pop_events(environment_t* env) { while (event != NULL && lf_tag_compare(event->base.tag, env->current_tag) == 0) { event = (event_t*)pqueue_tag_pop(env->event_q); - if (event->is_dummy) { + if (event->trigger == NULL) { LF_PRINT_DEBUG("Popped dummy event from the event queue."); lf_recycle_event(env, event); // Peek at the next event in the event queue. @@ -447,19 +447,17 @@ void lf_recycle_event(environment_t* env, event_t* e) { e->base.tag = (tag_t){.time = 0LL, .microstep = 0}; e->trigger = NULL; e->token = NULL; - e->is_dummy = false; #ifdef FEDERATED_DECENTRALIZED e->intended_tag = (tag_t){.time = NEVER, .microstep = 0u}; #endif pqueue_tag_insert(env->recycle_q, (pqueue_tag_element_t*)e); } -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag) { +event_t* _lf_create_dummy_events(environment_t* env, tag_t tag) { event_t* dummy = lf_get_new_event(env); dummy->base.tag = tag; - dummy->is_dummy = true; - dummy->trigger = trigger; + dummy->trigger = NULL; return dummy; } @@ -527,7 +525,6 @@ trigger_handle_t _lf_schedule_at_tag(environment_t* env, trigger_t* trigger, tag case replace: // Replace the payload of the event at the head with our // current payload. - found->is_dummy = false; lf_replace_token(found, token); lf_recycle_event(env, e); return 0; diff --git a/include/core/lf_types.h b/include/core/lf_types.h index d70447159..75a61e405 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -199,7 +199,6 @@ struct event_t { pqueue_tag_element_t base; // Elements of pqueue_tag. It contains tag of release and position in the priority queue. trigger_t* trigger; // Associated trigger, NULL if this is a dummy event. lf_token_t* token; // Pointer to the token wrapping the value. - bool is_dummy; // Flag to indicate whether this event is merely a placeholder or an actual event. #ifdef FEDERATED tag_t intended_tag; // The intended tag. #endif diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index 0dbd508b5..8086ed7db 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -197,13 +197,13 @@ void _lf_trigger_shutdown_reactions(environment_t* env); /** * @brief Create a dummy event with the specified tag. * - * A dummy event is an event with no triggers that can be put on the event queue to trigger a tag advance to the specified tag. + * A dummy event is an event with no triggers that can be put on the event queue to trigger a tag advance to the + * specified tag. * @param env Environment in which we are executing. - * @param trigger The eventual event to be triggered. * @param tag The tag of that event. * @return A pointer to the dummy event. */ -event_t* _lf_create_dummy_events(environment_t* env, trigger_t* trigger, tag_t tag); +event_t* _lf_create_dummy_events(environment_t* env, tag_t tag); /** * @brief Schedule an event at a specific tag (time, microstep). From d10375d34f39395ed0a6c760e75826a76cf213fe Mon Sep 17 00:00:00 2001 From: Byeonggil Jun Date: Thu, 11 Apr 2024 08:59:57 -0700 Subject: [PATCH 78/95] Move some callback functions for the event queue to environment.c --- core/environment.c | 53 ++++++++++++++++++++++++++++--------- core/utils/pqueue.c | 8 ------ include/core/utils/pqueue.h | 19 +++---------- 3 files changed, 45 insertions(+), 35 deletions(-) diff --git a/core/environment.c b/core/environment.c index 8fae82f4c..4523c4721 100644 --- a/core/environment.c +++ b/core/environment.c @@ -38,6 +38,31 @@ #include "scheduler.h" #endif +////////////////// +// Local functions, not intended for use outside this file. + +/** + * @brief Callback function to determine whether two events have the same trigger. + * This function is used by event queue and recycle. + * Return 1 if the triggers are identical, 0 otherwise. + * @param event1 A pointer to an event. + * @param event2 A pointer to an event. + */ +static int event_matches(void* event1, void* event2) { + return (((event_t*)event1)->trigger == ((event_t*)event2)->trigger); +} + +/** + * @brief Callback function to print information about an event. + * This function is used by event queue and recycle. + * @param element A pointer to an event. + */ +static void print_event(void* event) { + event_t* e = (event_t*)event; + LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, + (void*)e->trigger, (void*)e->token); +} + /** * @brief Initialize the threaded part of the environment struct. */ @@ -58,6 +83,7 @@ static void environment_init_threaded(environment_t* env, int num_workers) { (void)num_workers; #endif } + /** * @brief Initialize the single-threaded-specific parts of the environment struct. */ @@ -127,18 +153,6 @@ static void environment_init_federated(environment_t* env, int num_is_present_fi #endif } -void environment_init_tags(environment_t* env, instant_t start_time, interval_t duration) { - env->current_tag = (tag_t){.time = start_time, .microstep = 0u}; - - tag_t stop_tag = FOREVER_TAG_INITIALIZER; - if (duration >= 0LL) { - // A duration has been specified. Calculate the stop time. - stop_tag.time = env->current_tag.time + duration; - stop_tag.microstep = 0; - } - env->stop_tag = stop_tag; -} - static void environment_free_threaded(environment_t* env) { #if !defined(LF_SINGLE_THREADED) free(env->thread_ids); @@ -176,6 +190,9 @@ static void environment_free_federated(environment_t* env) { #endif } +////////////////// +// Functions defined in environment.h. + void environment_free(environment_t* env) { free(env->name); free(env->timer_triggers); @@ -193,6 +210,18 @@ void environment_free(environment_t* env) { environment_free_federated(env); } +void environment_init_tags(environment_t* env, instant_t start_time, interval_t duration) { + env->current_tag = (tag_t){.time = start_time, .microstep = 0u}; + + tag_t stop_tag = FOREVER_TAG_INITIALIZER; + if (duration >= 0LL) { + // A duration has been specified. Calculate the stop time. + stop_tag.time = env->current_tag.time + duration; + stop_tag.microstep = 0; + } + env->stop_tag = stop_tag; +} + int environment_init(environment_t* env, const char* name, int id, int num_workers, int num_timers, int num_startup_reactions, int num_shutdown_reactions, int num_reset_reactions, int num_is_present_fields, int num_modes, int num_state_resets, int num_watchdogs, diff --git a/core/utils/pqueue.c b/core/utils/pqueue.c index 00c3724f8..b2bf05090 100644 --- a/core/utils/pqueue.c +++ b/core/utils/pqueue.c @@ -25,8 +25,6 @@ int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that) { return 0; } -int event_matches(void* event1, void* event2) { return (((event_t*)event1)->trigger == ((event_t*)event2)->trigger); } - int reaction_matches(void* a, void* b) { return (a == b); } pqueue_pri_t get_reaction_index(void* reaction) { return ((reaction_t*)reaction)->index; } @@ -39,9 +37,3 @@ void print_reaction(void* reaction) { reaction_t* r = (reaction_t*)reaction; LF_PRINT_DEBUG("%s: chain_id: %llu, index: %llx, reaction: %p", r->name, r->chain_id, r->index, reaction); } - -void print_event(void* event) { - event_t* e = (event_t*)event; - LF_PRINT_DEBUG("tag: " PRINTF_TAG ", trigger: %p, token: %p", e->base.tag.time, e->base.tag.microstep, - (void*)e->trigger, (void*)e->token); -} diff --git a/include/core/utils/pqueue.h b/include/core/utils/pqueue.h index eed4083e2..448b94462 100644 --- a/include/core/utils/pqueue.h +++ b/include/core/utils/pqueue.h @@ -6,7 +6,10 @@ * @copyright (c) 2020-2023, The University of California at Berkeley. * License: BSD 2-clause * - * @brief Priority queue declarations for the event queue and reaction queue. + * @brief Priority queue definitions for queues where the priority is a number that can be compared with ordinary + * numerical comparisons. + * + * This is used for the reaction queue. The event queue uses a `tag_t` struct for its priority, so it cannot use this. */ #ifndef PQUEUE_H @@ -28,13 +31,6 @@ int in_reverse_order(pqueue_pri_t thiz, pqueue_pri_t that); */ int in_no_particular_order(pqueue_pri_t thiz, pqueue_pri_t that); -/** - * Return 1 if the two events have the same trigger. - * @param event1 A pointer to an event_t. - * @param event2 A pointer to an event_t. - */ -int event_matches(void* event1, void* event2); - /** * Return 1 if the two arguments are identical pointers. * @param a First argument. @@ -70,11 +66,4 @@ void set_reaction_position(void* reaction, size_t pos); */ void print_reaction(void* reaction); -/** - * Print some information about the given event. - * This only prints something if logging is set to DEBUG. - * @param event A pointer to an event_t. - */ -void print_event(void* event); - #endif /* PQUEUE_H */ From fac0e503d8abf3ab8b64cf3ffeccadfe90e24fb5 Mon Sep 17 00:00:00 2001 From: "Erling R. Jellum" Date: Thu, 4 Apr 2024 03:44:34 -0700 Subject: [PATCH 79/95] Improve federate connect timout. - Use a timeout rather than a retry count - Add a CHECK_TIMEOUT macro for checking for timeouts --- core/federated/federate.c | 26 ++++++++++----------- include/core/federated/federate.h | 2 +- include/core/federated/network/net_common.h | 6 ++--- tag/api/tag.h | 3 +++ 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 510c50cdd..0a6b24ace 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1678,7 +1678,6 @@ void lf_terminate_execution(environment_t* env) { void lf_connect_to_federate(uint16_t remote_federate_id) { int result = -1; - int count_retries = 0; // Ask the RTI for port number of the remote federate. // The buffer is used for both sending and receiving replies. @@ -1686,7 +1685,7 @@ void lf_connect_to_federate(uint16_t remote_federate_id) { unsigned char buffer[sizeof(int32_t) + INET_ADDRSTRLEN + 1]; int port = -1; struct in_addr host_ip_addr; - int count_tries = 0; + instant_t start_connect = lf_time_physical(); while (port == -1 && !_lf_termination_executed) { buffer[0] = MSG_TYPE_ADDRESS_QUERY; // NOTE: Sending messages in little endian. @@ -1724,7 +1723,7 @@ void lf_connect_to_federate(uint16_t remote_federate_id) { // remote federate has not yet sent an MSG_TYPE_ADDRESS_ADVERTISEMENT message to the RTI. // Sleep for some time before retrying. if (port == -1) { - if (count_tries++ >= CONNECT_MAX_RETRIES) { + if (CHECK_TIMEOUT(start_connect, CONNECT_TIMEOUT)) { lf_print_error_and_exit("TIMEOUT obtaining IP/port for federate %d from the RTI.", remote_federate_id); } // Wait ADDRESS_QUERY_RETRY_INTERVAL nanoseconds. @@ -1745,8 +1744,8 @@ void lf_connect_to_federate(uint16_t remote_federate_id) { LF_PRINT_LOG("Received address %s port %d for federate %d from RTI.", hostname, uport, remote_federate_id); #endif - // Iterate until we either successfully connect or exceed the number of - // attempts given by CONNECT_MAX_RETRIES. + // Iterate until we either successfully connect or we exceed the CONNECT_TIMEOUT + start_connect = lf_time_physical(); int socket_id = -1; while (result < 0 && !_lf_termination_executed) { // Create an IPv4 socket for TCP (not UDP) communication over IP (0). @@ -1772,12 +1771,11 @@ void lf_connect_to_federate(uint16_t remote_federate_id) { // Note that this should not really happen since the remote federate should be // accepting socket connections. But possibly it will be busy (in process of accepting // another socket connection?). Hence, we retry. - count_retries++; - if (count_retries > CONNECT_MAX_RETRIES) { - // If the remote federate is not accepting the connection after CONNECT_MAX_RETRIES + if (CHECK_TIMEOUT(start_connect, CONNECT_TIMEOUT)) { + // If the remote federate is not accepting the connection after CONNECT_TIMEOUT // treat it as a soft error condition and return. - lf_print_error("Failed to connect to federate %d after %d retries. Giving up.", remote_federate_id, - CONNECT_MAX_RETRIES); + lf_print_error("Failed to connect to federate %d with timeout: " PRINTF_TIME ". Giving up.", remote_federate_id, + CONNECT_TIMEOUT); return; } lf_print_warning("Could not connect to federate %d. Will try again every" PRINTF_TIME "nanoseconds.\n", @@ -1859,10 +1857,10 @@ void lf_connect_to_rti(const char* hostname, int port) { _fed.socket_TCP_RTI = create_real_time_tcp_socket_errexit(); int result = -1; - int count_retries = 0; struct addrinfo* res = NULL; - while (count_retries++ < CONNECT_MAX_RETRIES && !_lf_termination_executed) { + instant_t connect_start = lf_time_physical(); + while (CHECK_TIMEOUT(connect_start, CONNECT_TIMEOUT) && !_lf_termination_executed) { if (res != NULL) { // This is a repeated attempt. if (_fed.socket_TCP_RTI >= 0) @@ -1884,7 +1882,7 @@ void lf_connect_to_rti(const char* hostname, int port) { // Reconstruct the address info. rti_address(hostname, uport, &res); } - lf_print("Trying RTI again on port %d (attempt %d).", uport, count_retries); + lf_print("Trying RTI again on port %d.", uport); } else { // This is the first attempt. rti_address(hostname, uport, &res); @@ -1975,7 +1973,7 @@ void lf_connect_to_rti(const char* hostname, int port) { } } if (result < 0) { - lf_print_error_and_exit("Failed to connect to RTI after %d tries.", CONNECT_MAX_RETRIES); + lf_print_error_and_exit("Failed to connect to RTI with timeout: " PRINTF_TIME, CONNECT_TIMEOUT); } freeaddrinfo(res); /* No longer needed */ diff --git a/include/core/federated/federate.h b/include/core/federated/federate.h index 922a735cf..1c1028c23 100644 --- a/include/core/federated/federate.h +++ b/include/core/federated/federate.h @@ -244,7 +244,7 @@ void lf_connect_to_federate(uint16_t); * This will return the socket descriptor for the connection. * If port_number is 0, then start at DEFAULT_PORT and increment * the port number on each attempt. If an attempt fails, wait CONNECT_RETRY_INTERVAL - * and try again. If it fails after CONNECT_MAX_RETRIES, the program exits. + * and try again. If it fails after CONNECT_TIMEOUT, the program exits. * If it succeeds, it sets the _fed.socket_TCP_RTI global variable to refer to * the socket for communicating with the RTI. * @param hostname A hostname, such as "localhost". diff --git a/include/core/federated/network/net_common.h b/include/core/federated/network/net_common.h index cf34d5920..202592aa8 100644 --- a/include/core/federated/network/net_common.h +++ b/include/core/federated/network/net_common.h @@ -205,10 +205,10 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** * Bound on the number of retries to connect to the RTI. - * A federate will retry every CONNECT_RETRY_INTERVAL seconds - * this many times before giving up. + * A federate will retry every CONNECT_RETRY_INTERVAL seconds until + * CONNECTION_TIMEOUT expires. */ -#define CONNECT_MAX_RETRIES 100 +#define CONNECT_TIMEOUT MINUTES(1) /** * Maximum number of port addresses that a federate will try to connect to the RTI on. diff --git a/tag/api/tag.h b/tag/api/tag.h index 2ad4cc73c..2e271b249 100644 --- a/tag/api/tag.h +++ b/tag/api/tag.h @@ -47,6 +47,9 @@ #define ZERO_TAG \ (tag_t) { .time = 0LL, .microstep = 0u } +// Check whether a timeout duration has elapsed +#define CHECK_TIMEOUT(start, duration) (((start) + (duration)) > lf_time_physical()) + // Convenience for converting times #define BILLION ((instant_t)1000000000LL) From 7ffb1fea438e36ebf16ee1046deab9f358e75e25 Mon Sep 17 00:00:00 2001 From: "Erling R. Jellum" Date: Thu, 4 Apr 2024 03:56:48 -0700 Subject: [PATCH 80/95] Fix some typos --- core/federated/federate.c | 4 ++-- tag/api/tag.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 0a6b24ace..38d69f167 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -1859,8 +1859,8 @@ void lf_connect_to_rti(const char* hostname, int port) { int result = -1; struct addrinfo* res = NULL; - instant_t connect_start = lf_time_physical(); - while (CHECK_TIMEOUT(connect_start, CONNECT_TIMEOUT) && !_lf_termination_executed) { + instant_t start_connect = lf_time_physical(); + while (!CHECK_TIMEOUT(start_connect, CONNECT_TIMEOUT) && !_lf_termination_executed) { if (res != NULL) { // This is a repeated attempt. if (_fed.socket_TCP_RTI >= 0) diff --git a/tag/api/tag.h b/tag/api/tag.h index 2e271b249..c903aaf53 100644 --- a/tag/api/tag.h +++ b/tag/api/tag.h @@ -47,8 +47,8 @@ #define ZERO_TAG \ (tag_t) { .time = 0LL, .microstep = 0u } -// Check whether a timeout duration has elapsed -#define CHECK_TIMEOUT(start, duration) (((start) + (duration)) > lf_time_physical()) +// Returns true if timeout has elapsed. +#define CHECK_TIMEOUT(start, duration) (lf_time_physical() > ((start) + (duration))) // Convenience for converting times #define BILLION ((instant_t)1000000000LL) From cf961d50f0880d8370956c5d19e51da65e54c5c9 Mon Sep 17 00:00:00 2001 From: Chanhee Lee Date: Sat, 13 Apr 2024 20:12:05 -0700 Subject: [PATCH 81/95] Fix a negative value acceptance as the number of federates Invoke error returns when negative values are given as the number of federates and delete unreachable code found by the code coverage with unit test cases in Rust RTI. Signed-off-by: Chanhee Lee --- core/federated/RTI/main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/federated/RTI/main.c b/core/federated/RTI/main.c index e57327c6c..ed8f0b639 100644 --- a/core/federated/RTI/main.c +++ b/core/federated/RTI/main.c @@ -225,7 +225,7 @@ int process_args(int argc, const char* argv[]) { } i++; long num_federates = strtol(argv[i], NULL, 10); - if (num_federates == 0L || num_federates == LONG_MAX || num_federates == LONG_MIN) { + if (num_federates <= 0L || num_federates == LONG_MAX || num_federates == LONG_MIN) { lf_print_error("--number_of_federates needs a valid positive integer argument."); usage(argc, argv); return 0; @@ -272,11 +272,6 @@ int process_args(int argc, const char* argv[]) { return 0; } } - if (rti.base.number_of_scheduling_nodes == 0) { - lf_print_error("--number_of_federates needs a valid positive integer argument."); - usage(argc, argv); - return 0; - } return 1; } int main(int argc, const char* argv[]) { From 069cca44fc502cba522c8b4c90aecea4f33fccdb Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 14:45:34 +0200 Subject: [PATCH 82/95] Zephyr doesnt support fair scheduler --- low_level_platform/impl/src/lf_zephyr_support.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index dd18dc777..41751ecd5 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -166,17 +166,17 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { // Update the policy switch (policy->policy) { - case LF_SCHED_FAIR: break; case LF_SCHED_TIMESLICE: { k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - policy->priority); - k_sched_time_slice_set(0, policy->time_slice / 1000000); + k_sched_time_slice_set(0, policy->time_slice / MSEC(1)); break; } case LF_SCHED_PRIORITY: { k_thread_priority_set(thread, 99 - policy->priority); break; } + case LF_SCHED_FAIR: default: return -1; break; From de1e2a212b4eedab458b21e62ee5d81f18daaef1 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 14:49:32 +0200 Subject: [PATCH 83/95] Improve docs --- low_level_platform/api/low_level_platform.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 1a7208214..e7754f3f3 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -108,8 +108,7 @@ int lf_mutex_lock(lf_mutex_t* mutex); int lf_available_cores(); /** - * Returns the thread ID of the calling thread - * + * Returns the lf_thread_t of the calling thread. */ lf_thread_t lf_thread_self(); @@ -118,7 +117,6 @@ lf_thread_t lf_thread_self(); * getting passed arguments. The new handle is stored in thread_id. * * @return 0 on success, platform-specific error number otherwise. - * */ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* arguments); @@ -138,15 +136,13 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum */ int lf_thread_join(lf_thread_t thread, void** thread_return); -// The following API introduce the ability to change how the LF workers are sheduled -// by the underlying thread scheduling. This API is still experimental and future -// changes are expected. - +/** + * Thread scheduling API. + */ #define LF_SCHED_MAX_PRIORITY 99 #define LF_SCHED_MIN_PRIORITY 0 /** * @brief The thread scheduling policies. - * */ typedef enum { LF_SCHED_FAIR, // Non real-time scheduling policy. Corresponds to SCHED_OTHER From 73affa6a97f183ea25616047a35fc7a2ce121635 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 14:57:43 +0200 Subject: [PATCH 84/95] Small fixes --- core/platform/lf_windows_support.c | 296 ------------------ low_level_platform/api/low_level_platform.h | 3 - .../impl/src/lf_linux_support.c | 1 + .../impl/src/lf_macos_support.c | 3 + .../impl/src/lf_windows_support.c | 9 + .../impl/src/lf_zephyr_support.c | 3 + 6 files changed, 16 insertions(+), 299 deletions(-) delete mode 100644 core/platform/lf_windows_support.c diff --git a/core/platform/lf_windows_support.c b/core/platform/lf_windows_support.c deleted file mode 100644 index e6e7906fd..000000000 --- a/core/platform/lf_windows_support.c +++ /dev/null @@ -1,296 +0,0 @@ -#ifdef PLATFORM_Windows -/* Windows API support for the C target of Lingua Franca. */ - -/************* -Copyright (c) 2021, The University of California at Berkeley. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -***************/ - -/** Windows API support for the C target of Lingua Franca. - * - * @author{Soroush Bateni } - * - * All functions return 0 on success. - * - * @see https://gist.github.com/Soroosh129/127d1893fa4c1da6d3e1db33381bb273 - */ - -#include // Order in which windows.h is included does matter! -#include -#include -#include -#include - -#include "lf_windows_support.h" -#include "platform.h" -#include "tag.h" -#include "util.h" - -/** - * Indicate whether or not the underlying hardware - * supports Windows' high-resolution counter. It should - * always be supported for Windows Xp and later. - */ -int _lf_use_performance_counter = 0; - -/** - * The denominator to convert the performance counter - * to nanoseconds. - */ -double _lf_frequency_to_ns = 1.0; - -void _lf_initialize_clock() { - // Check if the performance counter is available - LARGE_INTEGER performance_frequency; - _lf_use_performance_counter = QueryPerformanceFrequency(&performance_frequency); - if (_lf_use_performance_counter) { - _lf_frequency_to_ns = (double)performance_frequency.QuadPart / BILLION; - } else { - lf_print_error("High resolution performance counter is not supported on this machine."); - _lf_frequency_to_ns = 0.01; - } -} - -/** - * Fetch the value of the physical clock (see lf_windows_support.h) and store it in t. - * The timestamp value in 't' will be based on QueryPerformanceCounter, adjusted to - * reflect time passed in nanoseconds, on most modern Windows systems. - * - * @return 0 for success, or -1 for failure. In case of failure, errno will be - * set to EINVAL or EFAULT. - */ -int _lf_clock_gettime(instant_t* t) { - // Adapted from gclib/GResUsage.cpp - // (https://github.com/gpertea/gclib/blob/8aee376774ccb2f3bd3f8e3bf1c9df1528ac7c5b/GResUsage.cpp) - // License: https://github.com/gpertea/gclib/blob/master/LICENSE.txt - int result = -1; - if (t == NULL) { - // The t argument address references invalid memory - errno = EFAULT; - return result; - } - LARGE_INTEGER windows_time; - if (_lf_use_performance_counter) { - int result = QueryPerformanceCounter(&windows_time); - if (result == 0) { - lf_print_error("_lf_clock_gettime(): Failed to read the value of the physical clock."); - return result; - } - } else { - FILETIME f; - GetSystemTimeAsFileTime(&f); - windows_time.QuadPart = f.dwHighDateTime; - windows_time.QuadPart <<= 32; - windows_time.QuadPart |= f.dwLowDateTime; - } - *t = (instant_t)((double)windows_time.QuadPart / _lf_frequency_to_ns); - return (0); -} - -/** - * Pause execution for a number of nanoseconds. - * - * @return 0 for success, or -1 for failure. In case of failure, errno will be - * set to - * - EINTR: The sleep was interrupted by a signal handler - * - EINVAL: All other errors - */ -int lf_sleep(interval_t sleep_duration) { - /* Declarations */ - HANDLE timer; /* Timer handle */ - LARGE_INTEGER li; /* Time defintion */ - /* Create timer */ - if (!(timer = CreateWaitableTimer(NULL, TRUE, NULL))) { - return FALSE; - } - /** - * Set timer properties. - * A negative number indicates relative time to wait. - * The requested sleep duration must be in number of 100 nanoseconds. - */ - li.QuadPart = -1 * (sleep_duration / 100); - if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) { - CloseHandle(timer); - return FALSE; - } - /* Start & wait for timer */ - WaitForSingleObject(timer, INFINITE); - /* Clean resources */ - CloseHandle(timer); - /* Slept without problems */ - return TRUE; -} - -int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { - interval_t sleep_duration = wakeup_time - lf_time_physical(); - - if (sleep_duration <= 0) { - return 0; - } else { - return lf_sleep(sleep_duration); - } -} - -int lf_nanosleep(interval_t sleep_duration) { return lf_sleep(sleep_duration); } - -#if defined(LF_SINGLE_THREADED) -#include "lf_os_single_threaded_support.c" -#endif - -#if !defined(LF_SINGLE_THREADED) -int lf_available_cores() { - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; -} - -int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* arguments) { - uintptr_t handle = _beginthreadex(NULL, 0, lf_thread, arguments, 0, NULL); - *thread = (HANDLE)handle; - if (handle == 0) { - return errno; - } else { - return 0; - } -} - -/** - * Make calling thread wait for termination of the thread. The - * exit status of the thread is stored in thread_return, if thread_return - * is not NULL. - * - * @return 0 on success, EINVAL otherwise. - */ -int lf_thread_join(lf_thread_t thread, void** thread_return) { - DWORD retvalue = WaitForSingleObject(thread, INFINITE); - if (retvalue == WAIT_FAILED) { - return EINVAL; - } - return 0; -} - -lf_thread_t lf_thread_self() { return GetCurrentThread(); } - -int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } - -int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } - -int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { return -1; } - -int lf_mutex_init(_lf_critical_section_t* critical_section) { - // Set up a recursive mutex - InitializeCriticalSection((PCRITICAL_SECTION)critical_section); - if (critical_section != NULL) { - return 0; - } else { - return 1; - } -} - -/** - * Lock a critical section. - * - * From https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-entercriticalsection: - * "This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait operation on the critical section times out. - * The timeout interval is specified by the following registry value: - * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\CriticalSectionTimeout. - * Do not handle a possible deadlock exception; instead, debug the application." - * - * @return 0 - */ -int lf_mutex_lock(_lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. It can - // raise a EXCEPTION_POSSIBLE_DEADLOCK. See synchapi.h. - EnterCriticalSection((PCRITICAL_SECTION)critical_section); - return 0; -} - -int lf_mutex_unlock(_lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. - LeaveCriticalSection((PCRITICAL_SECTION)critical_section); - return 0; -} - -int lf_cond_init(lf_cond_t* cond, _lf_critical_section_t* critical_section) { - // The following Windows API does not return a value. - cond->critical_section = critical_section; - InitializeConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; -} - -int lf_cond_broadcast(lf_cond_t* cond) { - // The following Windows API does not return a value. - WakeAllConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; -} - -int lf_cond_signal(lf_cond_t* cond) { - // The following Windows API does not return a value. - WakeConditionVariable((PCONDITION_VARIABLE)&cond->condition); - return 0; -} - -int lf_cond_wait(lf_cond_t* cond) { - // According to synchapi.h, the following Windows API returns 0 on failure, - // and non-zero on success. - int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, INFINITE); - switch (return_value) { - case 0: - // Error - return 1; - break; - - default: - // Success - return 0; - break; - } -} - -int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { - // Convert the absolute time to a relative time. - interval_t wait_duration = wakeup_time - lf_time_physical(); - if (wait_duration <= 0) { - // physical time has already caught up sufficiently and we do not need to wait anymore - return 0; - } - - // convert ns to ms and round up to closest full integer - DWORD wait_duration_ms = (wait_duration + 999999LL) / 1000000LL; - - int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, wait_duration_ms); - if (return_value == 0) { - // Error - if (GetLastError() == ERROR_TIMEOUT) { - return LF_TIMEOUT; - } - return -1; - } - - // Success - return 0; -} -#endif - -#endif diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index e7754f3f3..c0b5da1ac 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -136,9 +136,6 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum */ int lf_thread_join(lf_thread_t thread, void** thread_return); -/** - * Thread scheduling API. - */ #define LF_SCHED_MAX_PRIORITY 99 #define LF_SCHED_MIN_PRIORITY 0 /** diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 66b532054..7ce71c1f5 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -43,6 +43,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "lf_os_single_threaded_support.c" #else #include "lf_POSIX_threads_support.c" + int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { // First verify that we have num_cores>cpu_number if (lf_available_cores() <= cpu_number) { diff --git a/low_level_platform/impl/src/lf_macos_support.c b/low_level_platform/impl/src/lf_macos_support.c index 0a50e2f3d..d6b59c4c9 100644 --- a/low_level_platform/impl/src/lf_macos_support.c +++ b/low_level_platform/impl/src/lf_macos_support.c @@ -39,6 +39,9 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #else #include "lf_POSIX_threads_support.c" +/** + * Real-time scheduling API not implemented for macOS. + */ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } diff --git a/low_level_platform/impl/src/lf_windows_support.c b/low_level_platform/impl/src/lf_windows_support.c index 1cdadc43c..a0f1fe4dc 100644 --- a/low_level_platform/impl/src/lf_windows_support.c +++ b/low_level_platform/impl/src/lf_windows_support.c @@ -187,6 +187,15 @@ int lf_thread_join(lf_thread_t thread, void** thread_return) { return 0; } +/** + * Real-time scheduling API not implemented for Windows. + */ +int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return -1; } + +int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } + +int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { return -1; } + int lf_mutex_init(_lf_critical_section_t* critical_section) { // Set up a recursive mutex InitializeCriticalSection((PCRITICAL_SECTION)critical_section); diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index 41751ecd5..b1dc8b5eb 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -158,6 +158,9 @@ lf_thread_t lf_thread_self() { return k_current_get(); } int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return k_thread_cpu_pin(thread, cpu_number); } +/** + * Real-time scheduling API + */ int lf_thread_set_priority(lf_thread_t thread, int priority) { k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - priority); return 0; From 3c69bdc0434eb47201401ed3c366b4fcc84a89ec Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 14:58:16 +0200 Subject: [PATCH 85/95] Doxs --- low_level_platform/api/low_level_platform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index c0b5da1ac..52dd9162b 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -108,7 +108,7 @@ int lf_mutex_lock(lf_mutex_t* mutex); int lf_available_cores(); /** - * Returns the lf_thread_t of the calling thread. + * @brief Returns the lf_thread_t of the calling thread. */ lf_thread_t lf_thread_self(); From 4378ce75aa93c676118e802c9a7ea64db662285a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 15:29:55 +0200 Subject: [PATCH 86/95] Document _GNU_SOURCE --- low_level_platform/impl/src/lf_linux_support.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 7ce71c1f5..9fc22e1ac 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -30,9 +30,10 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @author{Soroush Bateni } * @author{Marten Lohstroh } + * @author{Erling Jellum } */ -#define _GNU_SOURCE +#define _GNU_SOURCE // Needed to get access to Linux thread-scheduling API #include "platform/lf_linux_support.h" #include "low_level_platform.h" #include "tag.h" From 88ae0b350502dad15a0a81c0e142e44841aec255 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Wed, 17 Apr 2024 15:30:24 +0200 Subject: [PATCH 87/95] Remove unused import --- low_level_platform/impl/src/lf_linux_support.c | 1 - 1 file changed, 1 deletion(-) diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 9fc22e1ac..20c82b490 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -36,7 +36,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _GNU_SOURCE // Needed to get access to Linux thread-scheduling API #include "platform/lf_linux_support.h" #include "low_level_platform.h" -#include "tag.h" #include "platform/lf_unix_clock_support.h" From 5d45424613555cb5c751a24a3459f9bbda828469 Mon Sep 17 00:00:00 2001 From: erling Date: Thu, 18 Apr 2024 10:59:01 +0200 Subject: [PATCH 88/95] Apply suggestions from code review Co-authored-by: Marten Lohstroh --- low_level_platform/api/low_level_platform.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 52dd9162b..06f4dfea7 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -108,7 +108,7 @@ int lf_mutex_lock(lf_mutex_t* mutex); int lf_available_cores(); /** - * @brief Returns the lf_thread_t of the calling thread. + * @brief Return the lf_thread_t of the calling thread. */ lf_thread_t lf_thread_self(); @@ -154,7 +154,7 @@ typedef struct { } lf_scheduling_policy_t; /** - * This pins a lf_thread to a specific CPU + * @brief Pin a thread to a specific CPU. * * @param thread The thread * @param cpu_number the CPU ID @@ -163,7 +163,8 @@ typedef struct { int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); /** - * Sets the priority of a thread. Priority ranges from 0 to 99 where a higher + * @brief Set the priority of a thread. + * Priority ranges from 0 to 99 where a higher * number indicates higher priority. Setting the priority of a thread only * makes sense if the thread is scheduled with LF_SCHED_TIMESLICE or LF_THREAD_PRIORITY * @@ -174,7 +175,7 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); int lf_thread_set_priority(lf_thread_t thread, int priority); /** - * Sets the scheduling policy of a thread. + * @brief Set the scheduling policy of a thread. * * @return int 0 on success, platform-specific error number otherwise. */ From 32c64a71c3f9a0166a01d834cde86240efb399b7 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 11:43:19 +0200 Subject: [PATCH 89/95] Address review feedback --- core/utils/util.c | 10 ++++++ include/core/utils/util.h | 5 +++ low_level_platform/api/low_level_platform.h | 8 ++++- .../impl/src/lf_linux_support.c | 32 +++++++++++++++++-- .../impl/src/lf_zephyr_support.c | 20 +++++++++--- test/general/utils/map_test.c | 11 +++++++ 6 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 test/general/utils/map_test.c diff --git a/core/utils/util.c b/core/utils/util.c index 881b6dc05..78f5d66d3 100644 --- a/core/utils/util.c +++ b/core/utils/util.c @@ -213,3 +213,13 @@ void lf_register_print_function(print_message_function_t* function, int log_leve print_message_function = function; print_message_level = log_level; } + +int map(int value, int in_min, int in_max, int out_min, int out_max) { + // Check if value is within the input range + if (value < in_min || value > in_max) { + return -1; + } + + // Perform the linear mapping + return out_min + ((out_max - out_min) / (in_max - in_min)) * (value - in_min); +} diff --git a/include/core/utils/util.h b/include/core/utils/util.h index 2d9998a72..927894eea 100644 --- a/include/core/utils/util.h +++ b/include/core/utils/util.h @@ -194,4 +194,9 @@ void lf_vprint_error_and_exit(const char* format, va_list args) ATTRIBUTE_FORMAT */ #define LF_CRITICAL_SECTION_EXIT(env) LF_ASSERT(!lf_critical_section_exit(env), "Could not exit critical section") +/** + * @brief Maps an integer from one range to another. + */ +int map(int value, int in_min, int in_max, int out_min, int out_max); + #endif /* UTIL_H */ diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 52dd9162b..64caa467f 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -136,6 +136,7 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum */ int lf_thread_join(lf_thread_t thread, void** thread_return); +// Worker priorities range from 0 to 99 where 99 is the highest priority. #define LF_SCHED_MAX_PRIORITY 99 #define LF_SCHED_MIN_PRIORITY 0 /** @@ -174,7 +175,12 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number); int lf_thread_set_priority(lf_thread_t thread, int priority); /** - * Sets the scheduling policy of a thread. + * Sets the scheduling policy of a thread. This is based on the scheduling + * concept from Linux explained here: https://man7.org/linux/man-pages/man7/sched.7.html + * A scheduling policy is specific to a thread/worker. We have three policies + * LF_SCHED_PRIORITY which corresponds to SCHED_FIFO on Linux. + * LF_SCHED_TIMESLICE which corresponds to SCHED_RR on Linux. + * LF_SCHED_FAIR which corresponds to SCHED_OTHER on Linux. * * @return int 0 on success, platform-specific error number otherwise. */ diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 20c82b490..d276d4222 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -36,6 +36,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _GNU_SOURCE // Needed to get access to Linux thread-scheduling API #include "platform/lf_linux_support.h" #include "low_level_platform.h" +#include "util.h" #include "platform/lf_unix_clock_support.h" @@ -58,7 +59,29 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); } -int lf_thread_set_priority(lf_thread_t thread, int priority) { return pthread_setschedprio(thread, priority); } +int lf_thread_set_priority(lf_thread_t thread, int priority) { + int posix_policy, min_pri, max_pri, final_priority; + struct sched_param schedparam; + + if (priority > LF_SCHED_MAX_PRIORITY || priority < LF_SCHED_MIN_PRIORITY) { + return -1; + } + + // Get the current scheduling policy + if (pthread_getschedparam(thread, &posix_policy, &schedparam) != 0) { + return -1; + } + + min_pri = sched_get_priority_min(posix_policy); + max_pri = sched_get_priority_max(posix_policy); + if (min_pri == -1 || max_pri == -1) { + return -1; + } + + final_priority = map(priority, LF_SCHED_MIN_PRIORITY, LF_SCHED_MAX_PRIORITY, min_pri, max_pri); + + return pthread_setschedprio(thread, final_priority); +} int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* policy) { int posix_policy; @@ -76,11 +99,9 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* break; case LF_SCHED_TIMESLICE: posix_policy = SCHED_RR; - schedparam.sched_priority = policy->priority; break; case LF_SCHED_PRIORITY: posix_policy = SCHED_FIFO; - schedparam.sched_priority = policy->priority; break; default: return -1; @@ -92,6 +113,11 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* return -3; } + // Set the priority + if (lf_thread_set_priority(thread, policy->priority) != 0) { + return -1; + } + return 0; } #endif diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index b1dc8b5eb..8317caf3c 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -35,6 +35,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "platform/lf_zephyr_board_support.h" #include "low_level_platform.h" #include "tag.h" +#include "util.h" #include @@ -162,7 +163,12 @@ int lf_thread_set_cpu(lf_thread_t thread, int cpu_number) { return k_thread_cpu_ * Real-time scheduling API */ int lf_thread_set_priority(lf_thread_t thread, int priority) { - k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - priority); + int final_priority; + if (priority > LF_SCHED_MAX_PRIORITY || priority < LF_SCHED_MIN_PRIORITY) { + return -1; + } + final_priority = map(priority, LF_SCHED_MIN_PRIORITY, LF_SCHED_MAX_PRIORITY, CONFIG_NUM_PREEMPT_PRIORITIES - 1, 0); + k_thread_priority_set(thread, final_priority); return 0; } @@ -171,12 +177,18 @@ int lf_thread_set_scheduling_policy(lf_thread_t thread, lf_scheduling_policy_t* switch (policy->policy) { break; case LF_SCHED_TIMESLICE: { - k_thread_priority_set(thread, LF_SCHED_MAX_PRIORITY - policy->priority); - k_sched_time_slice_set(0, policy->time_slice / MSEC(1)); + // This sets timeslicing for all threads on all priorities. I.e. it is not + // set on a per-thread basis. + k_sched_time_slice_set(policy->time_slice / MSEC(1), 0); + if (lf_thread_set_priority(thread, policy->priority) != 0) { + return -1; + } break; } case LF_SCHED_PRIORITY: { - k_thread_priority_set(thread, 99 - policy->priority); + if (lf_thread_set_priority(thread, policy->priority) != 0) { + return -1; + } break; } case LF_SCHED_FAIR: diff --git a/test/general/utils/map_test.c b/test/general/utils/map_test.c new file mode 100644 index 000000000..e6c8356c6 --- /dev/null +++ b/test/general/utils/map_test.c @@ -0,0 +1,11 @@ + +#include +#include +#include +#include "util.h" + +int main(int argc, char* argv[]) { + assert(map(5, 0, 10, 0, 100) == 50); + assert(map(5, 0, 99, 0, 99) == 5); + assert(map(3, 0, 10, 50, 0) == 35); +} \ No newline at end of file From 9473ace2adac4b8e17d6cf48ef81018205d56224 Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 12:55:42 +0200 Subject: [PATCH 90/95] Move map function to platform --- core/utils/util.c | 10 -------- include/core/utils/util.h | 5 ---- low_level_platform/impl/CMakeLists.txt | 3 ++- .../impl/include/lf_platform_util.h | 8 ++++++ .../impl/src/lf_platform_util.c | 25 +++++++++++++++++++ .../impl/src/platform_internal.c | 13 ---------- test/general/utils/map_test.c | 11 -------- 7 files changed, 35 insertions(+), 40 deletions(-) create mode 100644 low_level_platform/impl/include/lf_platform_util.h create mode 100644 low_level_platform/impl/src/lf_platform_util.c delete mode 100644 low_level_platform/impl/src/platform_internal.c delete mode 100644 test/general/utils/map_test.c diff --git a/core/utils/util.c b/core/utils/util.c index 78f5d66d3..881b6dc05 100644 --- a/core/utils/util.c +++ b/core/utils/util.c @@ -213,13 +213,3 @@ void lf_register_print_function(print_message_function_t* function, int log_leve print_message_function = function; print_message_level = log_level; } - -int map(int value, int in_min, int in_max, int out_min, int out_max) { - // Check if value is within the input range - if (value < in_min || value > in_max) { - return -1; - } - - // Perform the linear mapping - return out_min + ((out_max - out_min) / (in_max - in_min)) * (value - in_min); -} diff --git a/include/core/utils/util.h b/include/core/utils/util.h index 927894eea..2d9998a72 100644 --- a/include/core/utils/util.h +++ b/include/core/utils/util.h @@ -194,9 +194,4 @@ void lf_vprint_error_and_exit(const char* format, va_list args) ATTRIBUTE_FORMAT */ #define LF_CRITICAL_SECTION_EXIT(env) LF_ASSERT(!lf_critical_section_exit(env), "Could not exit critical section") -/** - * @brief Maps an integer from one range to another. - */ -int map(int value, int in_min, int in_max, int out_min, int out_max); - #endif /* UTIL_H */ diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 5e44765eb..8fca6c1af 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -43,7 +43,7 @@ else() message(FATAL_ERROR "Your platform is not supported! The C target supports Linux, MacOS, Windows, Zephyr, Nrf52 and RP2040.") endif() -list(APPEND LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/platform_internal.c) +list(APPEND LF_LOW_LEVEL_PLATFORM_FILES ${CMAKE_CURRENT_LIST_DIR}/src/lf_platform_util.c) if(${CMAKE_SYSTEM_NAME} STREQUAL "Zephyr") if(${LF_ZEPHYR_CLOCK_COUNTER}) @@ -68,6 +68,7 @@ lf_enable_compiler_warnings(lf-low-level-platform-impl) target_link_libraries(lf-low-level-platform-impl PRIVATE lf::low-level-platform-api) target_link_libraries(lf-low-level-platform-impl PUBLIC lf-logging-api) +target_include_directories(lf-low-level-platform-impl PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) target_compile_definitions(lf-low-level-platform-impl PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) message(STATUS "Applying preprocessor definitions to platform...") diff --git a/low_level_platform/impl/include/lf_platform_util.h b/low_level_platform/impl/include/lf_platform_util.h new file mode 100644 index 000000000..f56ed10f8 --- /dev/null +++ b/low_level_platform/impl/include/lf_platform_util.h @@ -0,0 +1,8 @@ +#ifndef PLATFORM_INTERNAL_H +#define PLATFORM_INTERNAL_H +/** + * @brief Maps a priority into a destination priority range. + */ +int map_priorities(int priority, int dest_min, int dest_max); + +#endif \ No newline at end of file diff --git a/low_level_platform/impl/src/lf_platform_util.c b/low_level_platform/impl/src/lf_platform_util.c new file mode 100644 index 000000000..a64a82461 --- /dev/null +++ b/low_level_platform/impl/src/lf_platform_util.c @@ -0,0 +1,25 @@ +#include "low_level_platform.h" +#include "lf_platform_util.h" + +int map_priorities(int priority, int dest_min, int dest_max) { + // Check if priority is within the legal range + if (priority < LF_SCHED_MIN_PRIORITY || priority > LF_SCHED_MAX_PRIORITY) { + return -1; + } + + // Perform the linear mapping + return dest_min + + ((dest_max - dest_min) / (LF_SCHED_MAX_PRIORITY - LF_SCHED_MIN_PRIORITY)) * (priority - LF_SCHED_MIN_PRIORITY); +} + +#ifndef PLATFORM_ZEPHYR // on Zephyr, this is handled separately +#ifndef LF_SINGLE_THREADED +static int _lf_worker_thread_count = 0; + +static thread_local int lf_thread_id_var = -1; + +int lf_thread_id() { return lf_thread_id_var; } + +void initialize_lf_thread_id() { lf_thread_id_var = lf_atomic_fetch_add32(&_lf_worker_thread_count, 1); } +#endif +#endif diff --git a/low_level_platform/impl/src/platform_internal.c b/low_level_platform/impl/src/platform_internal.c deleted file mode 100644 index fc14c9f22..000000000 --- a/low_level_platform/impl/src/platform_internal.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "low_level_platform.h" - -#ifndef PLATFORM_ZEPHYR // on Zephyr, this is handled separately -#ifndef LF_SINGLE_THREADED -static int _lf_worker_thread_count = 0; - -static thread_local int lf_thread_id_var = -1; - -int lf_thread_id() { return lf_thread_id_var; } - -void initialize_lf_thread_id() { lf_thread_id_var = lf_atomic_fetch_add32(&_lf_worker_thread_count, 1); } -#endif -#endif diff --git a/test/general/utils/map_test.c b/test/general/utils/map_test.c deleted file mode 100644 index e6c8356c6..000000000 --- a/test/general/utils/map_test.c +++ /dev/null @@ -1,11 +0,0 @@ - -#include -#include -#include -#include "util.h" - -int main(int argc, char* argv[]) { - assert(map(5, 0, 10, 0, 100) == 50); - assert(map(5, 0, 99, 0, 99) == 5); - assert(map(3, 0, 10, 50, 0) == 35); -} \ No newline at end of file From 9c38a73ceccf5d48ad74b52cb4839e3d9305e98f Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 16:07:20 +0200 Subject: [PATCH 91/95] Fixes --- low_level_platform/api/low_level_platform.h | 7 ++++--- low_level_platform/impl/src/lf_linux_support.c | 9 ++++++--- low_level_platform/impl/src/lf_zephyr_support.c | 9 +++++++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/low_level_platform/api/low_level_platform.h b/low_level_platform/api/low_level_platform.h index 9c996dae1..2867aa0f4 100644 --- a/low_level_platform/api/low_level_platform.h +++ b/low_level_platform/api/low_level_platform.h @@ -74,6 +74,10 @@ int lf_critical_section_exit(environment_t* env); #define LF_TIMEOUT 1 +// Worker priorities range from 0 to 99 where 99 is the highest priority. +#define LF_SCHED_MAX_PRIORITY 99 +#define LF_SCHED_MIN_PRIORITY 0 + // To support the single-threaded runtime, we need the following functions. They // are not required by the threaded runtime and is thus hidden behind a #ifdef. #if defined(LF_SINGLE_THREADED) @@ -136,9 +140,6 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum */ int lf_thread_join(lf_thread_t thread, void** thread_return); -// Worker priorities range from 0 to 99 where 99 is the highest priority. -#define LF_SCHED_MAX_PRIORITY 99 -#define LF_SCHED_MIN_PRIORITY 0 /** * @brief The thread scheduling policies. */ diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index d276d4222..1fc954d3c 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -25,7 +25,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************/ -/** +/**i * @brief Platform support for the Linux operating system. * * @author{Soroush Bateni } @@ -36,7 +36,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _GNU_SOURCE // Needed to get access to Linux thread-scheduling API #include "platform/lf_linux_support.h" #include "low_level_platform.h" -#include "util.h" +#include "lf_platform_util.h" #include "platform/lf_unix_clock_support.h" @@ -78,7 +78,10 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { return -1; } - final_priority = map(priority, LF_SCHED_MIN_PRIORITY, LF_SCHED_MAX_PRIORITY, min_pri, max_pri); + final_priority = map_priorities(priority, min_pri, max_pri); + if (final_priority < 0) { + return -1; + } return pthread_setschedprio(thread, final_priority); } diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index 8317caf3c..9728adf2b 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -35,7 +35,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "platform/lf_zephyr_board_support.h" #include "low_level_platform.h" #include "tag.h" -#include "util.h" +#include "lf_platform_util.h" #include @@ -167,7 +167,12 @@ int lf_thread_set_priority(lf_thread_t thread, int priority) { if (priority > LF_SCHED_MAX_PRIORITY || priority < LF_SCHED_MIN_PRIORITY) { return -1; } - final_priority = map(priority, LF_SCHED_MIN_PRIORITY, LF_SCHED_MAX_PRIORITY, CONFIG_NUM_PREEMPT_PRIORITIES - 1, 0); + + final_priority = map_priorities(priority, CONFIG_NUM_PREEMPT_PRIORITIES - 1, 0); + if (final_priority < 0) { + return -1; + } + k_thread_priority_set(thread, final_priority); return 0; } From 0143217babeb91e9fd2eb3b1a0598db6bf76eaec Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 16:20:54 +0200 Subject: [PATCH 92/95] Details --- low_level_platform/impl/include/lf_platform_util.h | 4 ++-- test/Tests.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/low_level_platform/impl/include/lf_platform_util.h b/low_level_platform/impl/include/lf_platform_util.h index f56ed10f8..0874f4cdf 100644 --- a/low_level_platform/impl/include/lf_platform_util.h +++ b/low_level_platform/impl/include/lf_platform_util.h @@ -1,5 +1,5 @@ -#ifndef PLATFORM_INTERNAL_H -#define PLATFORM_INTERNAL_H +#ifndef LF_PLATFORM_UTIL_H +#define LF_PLATFORM_UTIL_H /** * @brief Maps a priority into a destination priority range. */ diff --git a/test/Tests.cmake b/test/Tests.cmake index 4130b7c09..2ec3a90ba 100644 --- a/test/Tests.cmake +++ b/test/Tests.cmake @@ -62,7 +62,7 @@ if (NOT DEFINED LF_SINGLE_THREADED) ${RTI_DIR}/rti_remote.c ${CoreLibPath}/tracepoint.c ${LF_PLATFORM_FILE} - ${LF_ROOT}/low_level_platform/impl/src/platform_internal.c + ${LF_ROOT}/low_level_platform/impl/src/lf_platform_util.c ${LF_ROOT}/low_level_platform/impl/src/lf_atomic_gcc_clang.c ${LF_ROOT}/low_level_platform/impl/src/lf_unix_clock_support.c ${CoreLibPath}/utils/util.c From e1859210f11a21ee160f6cac15a1ff688fd2da8e Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 18:54:01 +0200 Subject: [PATCH 93/95] Update include path of Tests --- test/Tests.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Tests.cmake b/test/Tests.cmake index 2ec3a90ba..8e6807518 100644 --- a/test/Tests.cmake +++ b/test/Tests.cmake @@ -75,6 +75,7 @@ if (NOT DEFINED LF_SINGLE_THREADED) ) add_test(NAME rti_common_test COMMAND rti_common_test) target_include_directories(rti_common_test PUBLIC ${RTI_DIR}) + target_include_directories(rti_common_test PUBLIC ${LF_ROOT}/low_level_platform/impl/include) target_include_directories(rti_common_test PUBLIC ${IncludeDir}) target_include_directories(rti_common_test PUBLIC ${IncludeDir}/federated) target_include_directories(rti_common_test PUBLIC ${IncludeDir}/modal_models) From 5c69e354ab32728bb189a52eb49e7c0041b2604c Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 22:38:05 +0200 Subject: [PATCH 94/95] Move lf_platform_util.h to the public api folder --- .../{impl/include => api/platform}/lf_platform_util.h | 0 low_level_platform/impl/CMakeLists.txt | 1 - test/Tests.cmake | 1 - 3 files changed, 2 deletions(-) rename low_level_platform/{impl/include => api/platform}/lf_platform_util.h (100%) diff --git a/low_level_platform/impl/include/lf_platform_util.h b/low_level_platform/api/platform/lf_platform_util.h similarity index 100% rename from low_level_platform/impl/include/lf_platform_util.h rename to low_level_platform/api/platform/lf_platform_util.h diff --git a/low_level_platform/impl/CMakeLists.txt b/low_level_platform/impl/CMakeLists.txt index 8fca6c1af..5f6244664 100644 --- a/low_level_platform/impl/CMakeLists.txt +++ b/low_level_platform/impl/CMakeLists.txt @@ -68,7 +68,6 @@ lf_enable_compiler_warnings(lf-low-level-platform-impl) target_link_libraries(lf-low-level-platform-impl PRIVATE lf::low-level-platform-api) target_link_libraries(lf-low-level-platform-impl PUBLIC lf-logging-api) -target_include_directories(lf-low-level-platform-impl PRIVATE ${CMAKE_CURRENT_LIST_DIR}/include) target_compile_definitions(lf-low-level-platform-impl PUBLIC PLATFORM_${CMAKE_SYSTEM_NAME}) message(STATUS "Applying preprocessor definitions to platform...") diff --git a/test/Tests.cmake b/test/Tests.cmake index 8e6807518..2ec3a90ba 100644 --- a/test/Tests.cmake +++ b/test/Tests.cmake @@ -75,7 +75,6 @@ if (NOT DEFINED LF_SINGLE_THREADED) ) add_test(NAME rti_common_test COMMAND rti_common_test) target_include_directories(rti_common_test PUBLIC ${RTI_DIR}) - target_include_directories(rti_common_test PUBLIC ${LF_ROOT}/low_level_platform/impl/include) target_include_directories(rti_common_test PUBLIC ${IncludeDir}) target_include_directories(rti_common_test PUBLIC ${IncludeDir}/federated) target_include_directories(rti_common_test PUBLIC ${IncludeDir}/modal_models) From 591f428b3347d8732aa53b23e11510534392e89a Mon Sep 17 00:00:00 2001 From: erlingrj Date: Thu, 18 Apr 2024 22:43:06 +0200 Subject: [PATCH 95/95] Update include paths --- low_level_platform/impl/src/lf_linux_support.c | 2 +- low_level_platform/impl/src/lf_platform_util.c | 2 +- low_level_platform/impl/src/lf_zephyr_support.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/low_level_platform/impl/src/lf_linux_support.c b/low_level_platform/impl/src/lf_linux_support.c index 1fc954d3c..716d6c1c9 100644 --- a/low_level_platform/impl/src/lf_linux_support.c +++ b/low_level_platform/impl/src/lf_linux_support.c @@ -35,8 +35,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define _GNU_SOURCE // Needed to get access to Linux thread-scheduling API #include "platform/lf_linux_support.h" +#include "platform/lf_platform_util.h" #include "low_level_platform.h" -#include "lf_platform_util.h" #include "platform/lf_unix_clock_support.h" diff --git a/low_level_platform/impl/src/lf_platform_util.c b/low_level_platform/impl/src/lf_platform_util.c index a64a82461..317e696bd 100644 --- a/low_level_platform/impl/src/lf_platform_util.c +++ b/low_level_platform/impl/src/lf_platform_util.c @@ -1,5 +1,5 @@ #include "low_level_platform.h" -#include "lf_platform_util.h" +#include "platform/lf_platform_util.h" int map_priorities(int priority, int dest_min, int dest_max) { // Check if priority is within the legal range diff --git a/low_level_platform/impl/src/lf_zephyr_support.c b/low_level_platform/impl/src/lf_zephyr_support.c index 9728adf2b..f3470edbb 100644 --- a/low_level_platform/impl/src/lf_zephyr_support.c +++ b/low_level_platform/impl/src/lf_zephyr_support.c @@ -33,9 +33,9 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "platform/lf_zephyr_support.h" #include "platform/lf_zephyr_board_support.h" +#include "platform/lf_platform_util.h" #include "low_level_platform.h" #include "tag.h" -#include "lf_platform_util.h" #include