From b9be7ddf7157aaca6cf798eba0bc37e926949228 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 11:13:21 -0700 Subject: [PATCH 1/8] Various fixes to silence warnings on Windows --- core/environment.c | 7 ++- core/threaded/reactor_threaded.c | 13 ++++- core/utils/lf_semaphore.c | 4 +- core/utils/util.c | 5 +- include/core/lf_token.h | 2 +- include/core/utils/lf_semaphore.h | 6 +-- logging/api/logging_macros.h | 9 +++- .../impl/src/lf_atomic_windows.c | 8 +-- .../impl/src/lf_windows_support.c | 51 +++++++++++++++---- 9 files changed, 79 insertions(+), 26 deletions(-) diff --git a/core/environment.c b/core/environment.c index eb012589b..ae2755a9f 100644 --- a/core/environment.c +++ b/core/environment.c @@ -210,9 +210,12 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke 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 + // Space for the name string with the null terminator. + size_t name_size = strlen(name) + 1; + env->name = malloc(name_size); // +1 for the null terminator LF_ASSERT_NON_NULL(env->name); - strcpy(env->name, name); + // Use strncpy rather than strcpy to avoid compiler warnings. + strncpy(env->name, name, name_size + 1); // +1 ensures the null terminator is copied. env->id = id; env->stop_tag = FOREVER_TAG; diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index df0f271b1..2e96c4073 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -1028,7 +1028,13 @@ int lf_reactor_c_main(int argc, const char* argv[]) { lf_print("---- Start execution ----"); #else struct timespec physical_time_timespec = {start_time / BILLION, start_time % BILLION}; - lf_print("---- Start execution at time %s---- plus %ld nanoseconds", ctime(&physical_time_timespec.tv_sec), + struct tm* time_info = localtime(&physical_time_timespec.tv_sec); + char buffer[80]; // Long enough to hold the formatted time string. + // Use strftime rather than ctime because as of C23, ctime is deprecated. + strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", time_info); + + lf_print("---- Start execution on %s ---- plus %ld nanoseconds", + buffer, physical_time_timespec.tv_nsec); #endif // MINIMAL_STDLIB @@ -1114,7 +1120,10 @@ int lf_reactor_c_main(int argc, const char* argv[]) { } else { int failure = lf_thread_join(env->thread_ids[j], &worker_thread_exit_status); if (failure) { - lf_print_error("Failed to join thread listening for incoming messages: %s", strerror(failure)); + // On Windows (or C23), strerror is deprecated. Use strerror_r instead. + char buffer[80]; // Truncate error message at 80 chars. + strerror_r(failure, buffer, sizeof(buffer)); + lf_print_error("Failed to join thread listening for incoming messages: %s", buffer); } } if (worker_thread_exit_status != NULL) { diff --git a/core/utils/lf_semaphore.c b/core/utils/lf_semaphore.c index 2d0255ecb..3d79f9e4c 100644 --- a/core/utils/lf_semaphore.c +++ b/core/utils/lf_semaphore.c @@ -41,7 +41,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @param count The count to start with. * @return lf_semaphore_t* Can be NULL on error. */ -lf_semaphore_t* lf_semaphore_new(int count) { +lf_semaphore_t* lf_semaphore_new(size_t count) { lf_semaphore_t* semaphore = (lf_semaphore_t*)malloc(sizeof(lf_semaphore_t)); LF_MUTEX_INIT(&semaphore->mutex); LF_COND_INIT(&semaphore->cond, &semaphore->mutex); @@ -55,7 +55,7 @@ lf_semaphore_t* lf_semaphore_new(int count) { * @param semaphore Instance of a semaphore * @param i The count to add. */ -void lf_semaphore_release(lf_semaphore_t* semaphore, int i) { +void lf_semaphore_release(lf_semaphore_t* semaphore, size_t i) { assert(semaphore != NULL); LF_MUTEX_LOCK(&semaphore->mutex); semaphore->count += i; diff --git a/core/utils/util.c b/core/utils/util.c index 62de9fd27..e36c69dd5 100644 --- a/core/utils/util.c +++ b/core/utils/util.c @@ -206,7 +206,10 @@ void lf_print_error_system_failure(const char* format, ...) { va_start(args, format); lf_vprint_error(format, args); va_end(args); - lf_print_error_and_exit("Error %d: %s", errno, strerror(errno)); + // On Windows (or C23), strerror is deprecated. Use strerror_r instead. + char buffer[80]; // Truncate error message at 80 chars. + strerror_r(errno, buffer, sizeof(buffer)); + lf_print_error_and_exit("Error %d: %s", errno, buffer); exit(EXIT_FAILURE); } diff --git a/include/core/lf_token.h b/include/core/lf_token.h index 219538dd3..a9a883812 100644 --- a/include/core/lf_token.h +++ b/include/core/lf_token.h @@ -110,7 +110,7 @@ typedef struct lf_token_t { typedef struct lf_sparse_io_record_t { int size; // -1 if overflowed. 0 if empty. size_t capacity; // Max number of writes to be considered sparse. - size_t present_channels[]; // Array of channel indices that are present. + size_t* present_channels; // Array of channel indices that are present. } lf_sparse_io_record_t; /** diff --git a/include/core/utils/lf_semaphore.h b/include/core/utils/lf_semaphore.h index 73d3e4eb4..341c43cc4 100644 --- a/include/core/utils/lf_semaphore.h +++ b/include/core/utils/lf_semaphore.h @@ -41,7 +41,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include typedef struct { - int count; + size_t count; lf_mutex_t mutex; lf_cond_t cond; } lf_semaphore_t; @@ -52,7 +52,7 @@ typedef struct { * @param count The count to start with. * @return lf_semaphore_t* Can be NULL on error. */ -lf_semaphore_t* lf_semaphore_new(int count); +lf_semaphore_t* lf_semaphore_new(size_t count); /** * @brief Release the 'semaphore' and add 'i' to its count. @@ -60,7 +60,7 @@ lf_semaphore_t* lf_semaphore_new(int count); * @param semaphore Instance of a semaphore * @param i The count to add. */ -void lf_semaphore_release(lf_semaphore_t* semaphore, int i); +void lf_semaphore_release(lf_semaphore_t* semaphore, size_t i); /** * @brief Acquire the 'semaphore'. Will block if count is 0. diff --git a/logging/api/logging_macros.h b/logging/api/logging_macros.h index 6f7ea1eba..c42173601 100644 --- a/logging/api/logging_macros.h +++ b/logging/api/logging_macros.h @@ -12,6 +12,11 @@ #define LOG_LEVEL LOG_LEVEL_INFO #endif +// To prevent warnings "conditional expression is constant", we define static booleans +// here instead of directly testing LOG_LEVEL in the if statements in the macros below. +static bool _lf_log_level_is_log = LOG_LEVEL >= LOG_LEVEL_LOG; +static bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; + /** * A macro used to print useful logging information. It can be enabled * by setting the target property 'logging' to 'LOG' or @@ -31,7 +36,7 @@ */ #define LF_PRINT_LOG(format, ...) \ do { \ - if (LOG_LEVEL >= LOG_LEVEL_LOG) { \ + if (_lf_log_level_is_log) { \ lf_print_log(format, ##__VA_ARGS__); \ } \ } while (0) @@ -54,7 +59,7 @@ */ #define LF_PRINT_DEBUG(format, ...) \ do { \ - if (LOG_LEVEL >= LOG_LEVEL_DEBUG) { \ + if (_lf_log_level_is_debug) { \ lf_print_debug(format, ##__VA_ARGS__); \ } \ } while (0) diff --git a/low_level_platform/impl/src/lf_atomic_windows.c b/low_level_platform/impl/src/lf_atomic_windows.c index 519d225f6..ff5a01750 100644 --- a/low_level_platform/impl/src/lf_atomic_windows.c +++ b/low_level_platform/impl/src/lf_atomic_windows.c @@ -10,18 +10,18 @@ #include "platform/lf_atomic.h" #include -int lf_atomic_fetch_add(int* ptr, int value) { return InterlockedExchangeAdd(ptr, value); } +int lf_atomic_fetch_add(int* ptr, int value) { return InterlockedExchangeAdd((LONG*)ptr, (LONG)value); } int64_t lf_atomic_fetch_add64(int64_t* ptr, int64_t value) { return InterlockedExchangeAdd64(ptr, value); } -int lf_atomic_add_fetch(int* ptr, int value) { return InterlockedAdd(ptr, value); } +int lf_atomic_add_fetch(int* ptr, int value) { return InterlockedAdd((LONG*)ptr, (LONG)value); } int64_t lf_atomic_add_fetch64(int64_t* ptr, int64_t value) { return InterlockedAdd64(ptr, value); } bool lf_atomic_bool_compare_and_swap(int* ptr, int oldval, int newval) { - return (InterlockedCompareExchange(ptr, newval, oldval) == oldval); + return (InterlockedCompareExchange((LONG*)ptr, (LONG)newval, (LONG)oldval) == oldval); } bool lf_atomic_bool_compare_and_swap64(int64_t* ptr, int64_t oldval, int64_t newval) { return (InterlockedCompareExchange64(ptr, newval, oldval) == oldval); } int lf_atomic_val_compare_and_swap(int* ptr, int oldval, int newval) { - return InterlockedCompareExchange(ptr, newval, oldval); + return InterlockedCompareExchange((LONG*)ptr, (LONG)newval, (LONG)oldval); } int64_t lf_atomic_val_compare_and_swap64(int64_t* ptr, int64_t oldval, int64_t newval) { return InterlockedCompareExchange64(ptr, newval, oldval); diff --git a/low_level_platform/impl/src/lf_windows_support.c b/low_level_platform/impl/src/lf_windows_support.c index 61424ac7f..ec60555c0 100644 --- a/low_level_platform/impl/src/lf_windows_support.c +++ b/low_level_platform/impl/src/lf_windows_support.c @@ -39,6 +39,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include // For fprintf() #include "platform/lf_windows_support.h" #include "low_level_platform.h" @@ -64,7 +65,7 @@ void _lf_initialize_clock() { 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."); + fprintf(stderr, "ERROR: High resolution performance counter is not supported on this machine.\n"); _lf_frequency_to_ns = 0.01; } } @@ -89,9 +90,9 @@ int _lf_clock_gettime(instant_t* t) { } LARGE_INTEGER windows_time; if (_lf_use_performance_counter) { - int result = QueryPerformanceCounter(&windows_time); + result = QueryPerformanceCounter(&windows_time); if (result == 0) { - lf_print_error("_lf_clock_gettime(): Failed to read the value of the physical clock."); + fprintf(stderr, "ERROR: _lf_clock_gettime(): Failed to read the value of the physical clock.\n"); return result; } } else { @@ -140,6 +141,7 @@ int lf_sleep(interval_t sleep_duration) { } int _lf_interruptable_sleep_until_locked(environment_t* env, instant_t wakeup_time) { + (void)env; // Suppress unused variable warning. interval_t sleep_duration = wakeup_time - lf_time_physical(); if (sleep_duration <= 0) { @@ -165,7 +167,12 @@ int lf_available_cores() { lf_thread_t lf_thread_self() { return GetCurrentThread(); } 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); + // _beginthreadex requires a function that returns unsigned rather than void*. + // So the following double cast suppresses the warning: + // '_beginthreadex_proc_type' differs in levels of indirection from 'void *(__cdecl *)(void *)' + uintptr_t handle = _beginthreadex(NULL, 0, + (unsigned (__stdcall *)( void * ))(uintptr_t (__stdcall *)( void * )) lf_thread, + arguments, 0, NULL); *thread = (HANDLE)handle; if (handle == 0) { return errno; @@ -183,6 +190,9 @@ 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) { DWORD retvalue = WaitForSingleObject(thread, INFINITE); + if (thread_return != NULL) { + *thread_return = (void*)retvalue; + } if (retvalue == WAIT_FAILED) { return EINVAL; } @@ -192,11 +202,23 @@ int lf_thread_join(lf_thread_t thread, void** thread_return) { /** * Real-time scheduling API not implemented for Windows. */ -int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { return -1; } +int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { + (void)thread; // Suppress unused variable warning. + (void)cpu_number; // Suppress unused variable warning. + 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) { + (void)thread; // Suppress unused variable warning. + (void)priority; // Suppress unused variable warning. + 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) { + (void)thread; // Suppress unused variable warning. + (void)policy; // Suppress unused variable warning. + return -1; +} int lf_mutex_init(_lf_critical_section_t* critical_section) { // Set up a recursive mutex @@ -278,10 +300,21 @@ int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { } // convert ns to ms and round up to closest full integer - DWORD wait_duration_ms = (wait_duration + 999999LL) / 1000000LL; + interval_t wait_duration_ms = (wait_duration + 999999LL) / 1000000LL; + DWORD wait_duration_saturated; + if (wait_duration_ms > 0xFFFFFFFFLL) { + // Saturate at 0xFFFFFFFFLL + wait_duration_saturated = (DWORD)0xFFFFFFFFLL; + } else if (wait_duration_ms <= 0) { + // No need to wait. Return indicating that the wait is complete. + return LF_TIMEOUT; + } else { + wait_duration_saturated = (DWORD)wait_duration_ms; + } int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, wait_duration_ms); + (PCRITICAL_SECTION)cond->critical_section, + wait_duration_saturated); if (return_value == 0) { // Error if (GetLastError() == ERROR_TIMEOUT) { From ebdc1c350bfcf237a1046098b639e6abafe4ecf8 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 11:18:00 -0700 Subject: [PATCH 2/8] Format --- core/threaded/reactor_threaded.c | 4 +--- include/core/lf_token.h | 6 +++--- logging/api/logging_macros.h | 4 ++-- low_level_platform/impl/src/lf_windows_support.c | 12 +++++------- 4 files changed, 11 insertions(+), 15 deletions(-) diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 2e96c4073..658b9078e 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -1033,9 +1033,7 @@ int lf_reactor_c_main(int argc, const char* argv[]) { // Use strftime rather than ctime because as of C23, ctime is deprecated. strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", time_info); - lf_print("---- Start execution on %s ---- plus %ld nanoseconds", - buffer, - physical_time_timespec.tv_nsec); + lf_print("---- Start execution on %s ---- plus %ld nanoseconds", buffer, physical_time_timespec.tv_nsec); #endif // MINIMAL_STDLIB // Create and initialize the environments for each enclave diff --git a/include/core/lf_token.h b/include/core/lf_token.h index a9a883812..38e80310a 100644 --- a/include/core/lf_token.h +++ b/include/core/lf_token.h @@ -108,9 +108,9 @@ typedef struct lf_token_t { * A record of the subset of channels of a multiport that have present inputs. */ typedef struct lf_sparse_io_record_t { - int size; // -1 if overflowed. 0 if empty. - size_t capacity; // Max number of writes to be considered sparse. - size_t* present_channels; // Array of channel indices that are present. + int size; // -1 if overflowed. 0 if empty. + size_t capacity; // Max number of writes to be considered sparse. + size_t* present_channels; // Array of channel indices that are present. } lf_sparse_io_record_t; /** diff --git a/logging/api/logging_macros.h b/logging/api/logging_macros.h index c42173601..21735b73f 100644 --- a/logging/api/logging_macros.h +++ b/logging/api/logging_macros.h @@ -36,7 +36,7 @@ static bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; */ #define LF_PRINT_LOG(format, ...) \ do { \ - if (_lf_log_level_is_log) { \ + if (_lf_log_level_is_log) { \ lf_print_log(format, ##__VA_ARGS__); \ } \ } while (0) @@ -59,7 +59,7 @@ static bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; */ #define LF_PRINT_DEBUG(format, ...) \ do { \ - if (_lf_log_level_is_debug) { \ + if (_lf_log_level_is_debug) { \ lf_print_debug(format, ##__VA_ARGS__); \ } \ } while (0) diff --git a/low_level_platform/impl/src/lf_windows_support.c b/low_level_platform/impl/src/lf_windows_support.c index ec60555c0..c4524eda4 100644 --- a/low_level_platform/impl/src/lf_windows_support.c +++ b/low_level_platform/impl/src/lf_windows_support.c @@ -170,9 +170,8 @@ int lf_thread_create(lf_thread_t* thread, void* (*lf_thread)(void*), void* argum // _beginthreadex requires a function that returns unsigned rather than void*. // So the following double cast suppresses the warning: // '_beginthreadex_proc_type' differs in levels of indirection from 'void *(__cdecl *)(void *)' - uintptr_t handle = _beginthreadex(NULL, 0, - (unsigned (__stdcall *)( void * ))(uintptr_t (__stdcall *)( void * )) lf_thread, - arguments, 0, NULL); + uintptr_t handle = + _beginthreadex(NULL, 0, (unsigned(__stdcall*)(void*))(uintptr_t(__stdcall*)(void*))lf_thread, arguments, 0, NULL); *thread = (HANDLE)handle; if (handle == 0) { return errno; @@ -203,13 +202,13 @@ int lf_thread_join(lf_thread_t thread, void** thread_return) { * Real-time scheduling API not implemented for Windows. */ int lf_thread_set_cpu(lf_thread_t thread, size_t cpu_number) { - (void)thread; // Suppress unused variable warning. + (void)thread; // Suppress unused variable warning. (void)cpu_number; // Suppress unused variable warning. return -1; } int lf_thread_set_priority(lf_thread_t thread, int priority) { - (void)thread; // Suppress unused variable warning. + (void)thread; // Suppress unused variable warning. (void)priority; // Suppress unused variable warning. return -1; } @@ -313,8 +312,7 @@ int _lf_cond_timedwait(lf_cond_t* cond, instant_t wakeup_time) { } int return_value = (int)SleepConditionVariableCS((PCONDITION_VARIABLE)&cond->condition, - (PCRITICAL_SECTION)cond->critical_section, - wait_duration_saturated); + (PCRITICAL_SECTION)cond->critical_section, wait_duration_saturated); if (return_value == 0) { // Error if (GetLastError() == ERROR_TIMEOUT) { From 30d6384e2e5b4a680a568f6f35aedd57fccde5a6 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 11:37:24 -0700 Subject: [PATCH 3/8] Make statics const to suppress warning --- logging/api/logging_macros.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/logging/api/logging_macros.h b/logging/api/logging_macros.h index 21735b73f..3e22950b5 100644 --- a/logging/api/logging_macros.h +++ b/logging/api/logging_macros.h @@ -1,3 +1,5 @@ +#ifndef LOGGING_MACROS_H +#define LOGGING_MACROS_H #include "logging.h" /** @@ -14,8 +16,8 @@ // To prevent warnings "conditional expression is constant", we define static booleans // here instead of directly testing LOG_LEVEL in the if statements in the macros below. -static bool _lf_log_level_is_log = LOG_LEVEL >= LOG_LEVEL_LOG; -static bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; +static const bool _lf_log_level_is_log = LOG_LEVEL >= LOG_LEVEL_LOG; +static const bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; /** * A macro used to print useful logging information. It can be enabled @@ -105,3 +107,4 @@ static bool _lf_log_level_is_debug = LOG_LEVEL >= LOG_LEVEL_DEBUG; } \ } while (0) #endif // NDEBUG +#endif // LOGGING_MACROS_H \ No newline at end of file From d655debd5847df71df2aaace93f9f54924f32dad Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 11:57:27 -0700 Subject: [PATCH 4/8] Fix off-by-one memory error --- core/environment.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/core/environment.c b/core/environment.c index ae2755a9f..d24de4bfc 100644 --- a/core/environment.c +++ b/core/environment.c @@ -211,12 +211,15 @@ int environment_init(environment_t* env, const char* name, int id, int num_worke (void)trace_file_name; // Will be used with future enclave support. // Space for the name string with the null terminator. - size_t name_size = strlen(name) + 1; - env->name = malloc(name_size); // +1 for the null terminator - LF_ASSERT_NON_NULL(env->name); - // Use strncpy rather than strcpy to avoid compiler warnings. - strncpy(env->name, name, name_size + 1); // +1 ensures the null terminator is copied. - + if (name != NULL) { + size_t name_size = strlen(name) + 1; // +1 for the null terminator + env->name = (char*)malloc(name_size); + LF_ASSERT_NON_NULL(env->name); + // Use strncpy rather than strcpy to avoid compiler warnings. + strncpy(env->name, name, name_size); + } else { + env->name = NULL; + } env->id = id; env->stop_tag = FOREVER_TAG; From 10f46a15fc2e3e69c1702e1f229dcaf2bbfb885b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 12:51:44 -0700 Subject: [PATCH 5/8] More warnings --- trace/impl/src/trace_impl.c | 67 +++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index 895247e87..8eb35d881 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -43,46 +43,46 @@ static version_t version = {.build_config = * See trace.h. * @return The number of items written to the object table or -1 for failure. */ -static int write_trace_header(trace_t* trace) { - if (trace->_lf_trace_file != NULL) { - size_t items_written = fwrite(&start_time, sizeof(int64_t), 1, trace->_lf_trace_file); +static size_t write_trace_header(trace_t* t) { + if (t->_lf_trace_file != NULL) { + size_t items_written = fwrite(&start_time, sizeof(int64_t), 1, t->_lf_trace_file); if (items_written != 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); // The next item in the header is the size of the // _lf_trace_object_descriptions table. - items_written = fwrite(&trace->_lf_trace_object_descriptions_size, sizeof(int), 1, trace->_lf_trace_file); + items_written = fwrite(&t->_lf_trace_object_descriptions_size, sizeof(int), 1, t->_lf_trace_file); if (items_written != 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); // Next we write the table. - for (size_t i = 0; i < trace->_lf_trace_object_descriptions_size; i++) { + for (size_t i = 0; i < t->_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); + items_written = fwrite(&t->_lf_trace_object_descriptions[i].pointer, sizeof(void*), 1, t->_lf_trace_file); if (items_written != 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); // Write the pointer to the trigger_t struct. - items_written = fwrite(&trace->_lf_trace_object_descriptions[i].trigger, sizeof(void*), 1, trace->_lf_trace_file); + items_written = fwrite(&t->_lf_trace_object_descriptions[i].trigger, sizeof(void*), 1, t->_lf_trace_file); if (items_written != 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); // Write the object type. - items_written = fwrite(&trace->_lf_trace_object_descriptions[i].type, // Write the pointer value. - sizeof(_lf_trace_object_t), 1, trace->_lf_trace_file); + items_written = fwrite(&t->_lf_trace_object_descriptions[i].type, // Write the pointer value. + sizeof(_lf_trace_object_t), 1, t->_lf_trace_file); if (items_written != 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); // Write the 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), + size_t description_size = strlen(t->_lf_trace_object_descriptions[i].description); + items_written = fwrite(t->_lf_trace_object_descriptions[i].description, sizeof(char), description_size + 1, // Include null terminator. - trace->_lf_trace_file); + t->_lf_trace_file); if (items_written != description_size + 1) - _LF_TRACE_FAILURE(trace); + _LF_TRACE_FAILURE(t); } } - return trace->_lf_trace_object_descriptions_size; + return t->_lf_trace_object_descriptions_size; } /** @@ -125,37 +125,38 @@ static void flush_trace_locked(trace_t* trace, int worker) { /** * @brief Flush the specified buffer to a file. + * @param t The trace struct. * @param worker Index specifying the trace to flush. */ -static void flush_trace(trace_t* trace, int worker) { +static void flush_trace(trace_t* t, int worker) { // To avoid having more than one worker writing to the file at the same time, // enter a critical section. lf_platform_mutex_lock(trace_mutex); - flush_trace_locked(trace, worker); + flush_trace_locked(t, worker); lf_platform_mutex_unlock(trace_mutex); } -static void start_trace(trace_t* trace, int max_num_local_threads) { +static void start_trace(trace_t* t, int max_num_local_threads) { // Do not write the trace header information to the file yet - // so that startup reactions can register user-defined trace objects. + // so that startup reactions can register user-defined t objects. // write_trace_header(); - trace->_lf_trace_header_written = false; + t->_lf_trace_header_written = false; // Allocate an array of arrays of trace records, one per worker thread plus one // for the 0 thread (the main thread, or in an single-threaded program, the only // thread). - trace->_lf_number_of_trace_buffers = 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++) { - trace->_lf_trace_buffer[i] = (trace_record_nodeps_t*)malloc(sizeof(trace_record_nodeps_t) * TRACE_BUFFER_CAPACITY); + t->_lf_number_of_trace_buffers = max_num_local_threads; + t->_lf_trace_buffer = + (trace_record_nodeps_t**)malloc(sizeof(trace_record_nodeps_t*) * (t->_lf_number_of_trace_buffers + 1)); + t->_lf_trace_buffer++; // the buffer at index -1 is a fallback for user threads. + for (int i = -1; i < (int)t->_lf_number_of_trace_buffers; i++) { + t->_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(size_t), trace->_lf_number_of_trace_buffers + 1); - trace->_lf_trace_buffer_size++; + t->_lf_trace_buffer_size = (size_t*)calloc(sizeof(size_t), t->_lf_number_of_trace_buffers + 1); + t->_lf_trace_buffer_size++; - trace->_lf_trace_stop = 0; + t->_lf_trace_stop = 0; LF_PRINT_DEBUG("Started tracing."); } From c809f16c4b3fa903476621fe10a88c162d9d953c Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 12:56:56 -0700 Subject: [PATCH 6/8] Restore use of deprecated strerror because Windows does not define strerror_r --- core/threaded/reactor_threaded.c | 7 +++---- core/utils/util.c | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/core/threaded/reactor_threaded.c b/core/threaded/reactor_threaded.c index 658b9078e..82dd2b648 100644 --- a/core/threaded/reactor_threaded.c +++ b/core/threaded/reactor_threaded.c @@ -1118,10 +1118,9 @@ int lf_reactor_c_main(int argc, const char* argv[]) { } else { int failure = lf_thread_join(env->thread_ids[j], &worker_thread_exit_status); if (failure) { - // On Windows (or C23), strerror is deprecated. Use strerror_r instead. - char buffer[80]; // Truncate error message at 80 chars. - strerror_r(failure, buffer, sizeof(buffer)); - lf_print_error("Failed to join thread listening for incoming messages: %s", buffer); + // Windows warns that strerror is deprecated but doesn't define strerror_r. + // There seems to be no portable replacement. + lf_print_error("Failed to join thread listening for incoming messages: %s", strerror(failure)); } } if (worker_thread_exit_status != NULL) { diff --git a/core/utils/util.c b/core/utils/util.c index e36c69dd5..4fb956b3a 100644 --- a/core/utils/util.c +++ b/core/utils/util.c @@ -206,10 +206,9 @@ void lf_print_error_system_failure(const char* format, ...) { va_start(args, format); lf_vprint_error(format, args); va_end(args); - // On Windows (or C23), strerror is deprecated. Use strerror_r instead. - char buffer[80]; // Truncate error message at 80 chars. - strerror_r(errno, buffer, sizeof(buffer)); - lf_print_error_and_exit("Error %d: %s", errno, buffer); + // Windows warns that strerror is deprecated but doesn't define strerror_r. + // There seems to be no portable replacement. + lf_print_error_and_exit("Error %d: %s", errno, strerror(errno)); exit(EXIT_FAILURE); } From a5771a81431e0747997e05bec8770195368ffe2c Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 29 Sep 2024 13:03:12 -0700 Subject: [PATCH 7/8] Another attempt --- trace/impl/src/trace_impl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trace/impl/src/trace_impl.c b/trace/impl/src/trace_impl.c index 8eb35d881..02ffbb3bd 100644 --- a/trace/impl/src/trace_impl.c +++ b/trace/impl/src/trace_impl.c @@ -43,7 +43,7 @@ static version_t version = {.build_config = * See trace.h. * @return The number of items written to the object table or -1 for failure. */ -static size_t write_trace_header(trace_t* t) { +static int write_trace_header(trace_t* t) { if (t->_lf_trace_file != NULL) { size_t items_written = fwrite(&start_time, sizeof(int64_t), 1, t->_lf_trace_file); if (items_written != 1) @@ -82,7 +82,7 @@ static size_t write_trace_header(trace_t* t) { _LF_TRACE_FAILURE(t); } } - return t->_lf_trace_object_descriptions_size; + return (int)t->_lf_trace_object_descriptions_size; } /** From 3909a83536f001d48254361787857fa645000002 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 30 Sep 2024 08:26:17 -0700 Subject: [PATCH 8/8] Point to master --- 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 5d6695559..1f7391f92 100644 --- a/lingua-franca-ref.txt +++ b/lingua-franca-ref.txt @@ -1 +1 @@ -add-reaction +master