From 6dfa1a0e573692af48f114c844fddb6de8d2cbab Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Sat, 15 Apr 2023 16:17:23 +0900 Subject: [PATCH 01/28] Add CMake definition to find FEDERATED_AUTHENTICATED --- core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 4e5ff3224..b427b06de 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -85,6 +85,7 @@ define(EXECUTABLE_PREAMBLE) define(FEDERATED_CENTRALIZED) define(FEDERATED_DECENTRALIZED) define(FEDERATED) +define(FEDERATED_AUTHENTICATED) define(LF_REACTION_GRAPH_BREADTH) define(LF_THREADED) define(LF_TRACE) From 4920ead7960d1d30d7b4ba6becfb1bd9362b81e5 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Sat, 15 Apr 2023 19:48:23 +0900 Subject: [PATCH 02/28] Change ci.yml point --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0209e033..56603cffd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,14 +50,14 @@ jobs: lf-default: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} lf-gedf-np: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} @@ -65,7 +65,7 @@ jobs: lf-gedf-np-ci: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} @@ -73,7 +73,7 @@ jobs: lf-adaptive: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} From 1d573dac6775c09bdec92b28a0a5fad5c88476f7 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Sun, 16 Apr 2023 19:35:01 +0900 Subject: [PATCH 03/28] Try openssl/hmac.h first --- core/federated/federate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index c0964e2d3..4b01f2eae 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -62,8 +62,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scheduler.h" #include "trace.h" #ifdef FEDERATED_AUTHENTICATED -#include // For secure random number generation. #include // For HMAC-based authentication of federates. +#include // For secure random number generation. #endif // Error messages. From 8525a1fa27fdf3b420871ff0121b0f374fc3f053 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Sun, 16 Apr 2023 20:37:14 +0900 Subject: [PATCH 04/28] Revert "Try openssl/hmac.h first" This reverts commit 1d573dac6775c09bdec92b28a0a5fad5c88476f7. --- core/federated/federate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/federated/federate.c b/core/federated/federate.c index 4b01f2eae..c0964e2d3 100644 --- a/core/federated/federate.c +++ b/core/federated/federate.c @@ -62,8 +62,8 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "scheduler.h" #include "trace.h" #ifdef FEDERATED_AUTHENTICATED -#include // For HMAC-based authentication of federates. #include // For secure random number generation. +#include // For HMAC-based authentication of federates. #endif // Error messages. From 83a9aa318f1d1c9be4989af7255d2c1163b8829b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 20 Apr 2023 16:19:16 +0200 Subject: [PATCH 05/28] Moved \#define from platform.h to tag.h because platform.h is no longer automatically included --- include/core/platform/lf_nrf52_support.h | 17 ----------------- include/core/platform/lf_tag_64_32.h | 16 ---------------- include/core/tag.h | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 33 deletions(-) diff --git a/include/core/platform/lf_nrf52_support.h b/include/core/platform/lf_nrf52_support.h index a0a10d278..89bcf1444 100644 --- a/include/core/platform/lf_nrf52_support.h +++ b/include/core/platform/lf_nrf52_support.h @@ -52,23 +52,6 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. typedef void lf_mutex_t; typedef void _lf_cond_var_t; -/** - * For user-friendly reporting of time values, the buffer length required. - * This is calculated as follows, based on 64-bit time in nanoseconds: - * Maximum number of weeks is 15,250 - * Maximum number of days is 6 - * Maximum number of hours is 23 - * Maximum number of minutes is 59 - * Maximum number of seconds is 59 - * Maximum number of nanoseconds is 999,999,999 - * Maximum number of microsteps is 4,294,967,295 - * Total number of characters for the above is 24. - * Text descriptions and spaces add an additional 55, - * for a total of 79. One more allows for a null terminator. - */ -#define LF_TIME_BUFFER_LENGTH 80 - - // The underlying physical clock for Linux #define _LF_CLOCK CLOCK_MONOTONIC diff --git a/include/core/platform/lf_tag_64_32.h b/include/core/platform/lf_tag_64_32.h index 49f9e38c0..da1d77da5 100644 --- a/include/core/platform/lf_tag_64_32.h +++ b/include/core/platform/lf_tag_64_32.h @@ -47,19 +47,3 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // format for printing both time and microstep as follows: // printf("Tag is " PRINTF_TAG "\n", time_value, microstep); #define PRINTF_TAG "(" PRINTF_TIME ", " PRINTF_MICROSTEP ")" - -/** - * For user-friendly reporting of time values, the buffer length required. - * This is calculated as follows, based on 64-bit time in nanoseconds: - * Maximum number of weeks is 15,250 - * Maximum number of days is 6 - * Maximum number of hours is 23 - * Maximum number of minutes is 59 - * Maximum number of seconds is 59 - * Maximum number of nanoseconds is 999,999,999 - * Maximum number of microsteps is 4,294,967,295 - * Total number of characters for the above is 24. - * Text descriptions and spaces add an additional 55, - * for a total of 79. One more allows for a null terminator. - */ -#define LF_TIME_BUFFER_LENGTH 80 diff --git a/include/core/tag.h b/include/core/tag.h index 75c0a81a9..a8c9cc558 100644 --- a/include/core/tag.h +++ b/include/core/tag.h @@ -157,6 +157,22 @@ instant_t lf_time_start(void); */ void lf_set_physical_clock_offset(interval_t offset); +/** + * For user-friendly reporting of time values, the buffer length required. + * This is calculated as follows, based on 64-bit time in nanoseconds: + * Maximum number of weeks is 15,250 + * Maximum number of days is 6 + * Maximum number of hours is 23 + * Maximum number of minutes is 59 + * Maximum number of seconds is 59 + * Maximum number of nanoseconds is 999,999,999 + * Maximum number of microsteps is 4,294,967,295 + * Total number of characters for the above is 24. + * Text descriptions and spaces add an additional 55, + * for a total of 79. One more allows for a null terminator. + */ +#define LF_TIME_BUFFER_LENGTH 80 + /** * Store into the specified buffer a string giving a human-readable * rendition of the specified time. The buffer must have length at least From aa4b15bab296b2621927c5e45ac3075f065832c5 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Fri, 21 Apr 2023 17:04:48 +0900 Subject: [PATCH 06/28] Fix ci tests --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56603cffd..e0209e033 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,14 +50,14 @@ jobs: lf-default: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} lf-gedf-np: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} @@ -65,7 +65,7 @@ jobs: lf-gedf-np-ci: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} @@ -73,7 +73,7 @@ jobs: lf-adaptive: needs: fetch-lf - uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@auth-fail-test + uses: lf-lang/lingua-franca/.github/workflows/c-tests.yml@master with: runtime-ref: ${{ github.ref }} compiler-ref: ${{ needs.fetch-lf.outputs.ref }} From 6d0854a9ebb0ff06a774e28a12dcef0118037f06 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Fri, 21 Apr 2023 17:10:23 +0900 Subject: [PATCH 07/28] Add openssl library links to reactor-c/core --- core/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index b427b06de..dde09fe7a 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -51,6 +51,12 @@ target_include_directories(core PUBLIC ../include/core/modal_models) target_include_directories(core PUBLIC ../include/core/threaded) target_include_directories(core PUBLIC ../include/core/utils) +# Link with OpenSSL library +if(DEFINED FEDERATED_AUTHENTICATED) + find_package(OpenSSL REQUIRED) + target_link_libraries(core PUBLIC OpenSSL::SSL) +endif() + # Link with thread library if(DEFINED LF_THREADED OR DEFINED LF_TRACE) find_package(Threads REQUIRED) From 1bdca24e0ab3530b24319c6c967f4b8d1323d039 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Fri, 21 Apr 2023 18:01:05 +0200 Subject: [PATCH 08/28] Added LF_SOURCE_DIRECTORY and LF_FILE_SEPARATOR --- core/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 4e5ff3224..e182902b9 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -94,5 +94,6 @@ define(MODAL_REACTORS) define(NUMBER_OF_FEDERATES) define(NUMBER_OF_WORKERS) define(SCHEDULER) -define(TARGET_FILES_DIRECTORY) +define(LF_SOURCE_DIRECTORY) +define(LF_FILE_SEPARATOR) define(WORKERS_NEEDED_FOR_FEDERATE) From 9d465ec9edb203e75e28c9096430b2a7a6b60a1a Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Fri, 21 Apr 2023 18:04:12 +0200 Subject: [PATCH 09/28] Cleaned up docs for doxygen --- util/audio_loop.h | 64 +++++++++++------------------------------ util/audio_loop_linux.c | 56 ++---------------------------------- util/audio_loop_mac.c | 29 ++----------------- util/wave_file_reader.c | 47 +++--------------------------- util/wave_file_reader.h | 49 +++++++++++-------------------- 5 files changed, 42 insertions(+), 203 deletions(-) diff --git a/util/audio_loop.h b/util/audio_loop.h index 9df35bcc8..011b31eb5 100644 --- a/util/audio_loop.h +++ b/util/audio_loop.h @@ -2,66 +2,34 @@ * @file * @author Edward A. Lee * @author Soroush Bateni + * @copyright (c) 2020-2023, The University of California at Berkeley and UT Dallas. + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) + * + * @brief Utility function for playing audio on Linux or MacOS. * - * @section LICENSE -Copyright (c) 2020, The University of California at Berkeley and UT Dallas - -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. - - * @section DESCRIPTION - * - * Audio functions for Linux. To start an audio loop, call - * `lf_start_audio_loop`, passing it the logical time at which + * Audio functions for Linux or MacOS. To start an audio loop, call + * `lf_start_audio_loop()`, passing it the logical time at which * you would like the loop to start. To play a waveform, * call `lf_play_audio_waveform()`. A waveform may be * synthesized or read from a .wav file using * `read_wave_file()` (see wave_file_reader.h). * - * To use this, include the following flags in your target properties: - * If you are running on Linux: + * To use this, include the following in your target properties: *
- * target C {
- *     flags: "-lasound -lm",
- *     files: ["/lib/C/util/audio_loop_linux.c", "/lib/C/util/audio_loop.h"]
- * };
- * 
- * If you are running on Mac: - *
- * target C {
- *     flags: "-framework AudioToolbox -framework CoreFoundation -lm",
- *     files: ["/lib/C/util/audio_loop_mac.c", "/lib/C/util/audio_loop.h"]
- * };
+    files: [
+        "/lib/c/reactor-c/util/audio_loop_mac.c",
+        "/lib/c/reactor-c/util/audio_loop.h",
+        "/lib/c/reactor-c/util/audio_loop_linux.c",
+    ],
+    cmake-include: [
+        "/lib/c/reactor-c/util/audio_loop.cmake"
+    ]
  * 
* * In addition, you need this in your Lingua Franca file: - * If you are running on Linux: - *
- * preamble {=
- *     #include "audio_loop_linux.c"
- * =}
- * 
- * If you are running on Mac: *
  * preamble {=
- *     #include "audio_loop_mac.c"
+ *     #include "audio_loop.h"
  * =}
  * 
*/ diff --git a/util/audio_loop_linux.c b/util/audio_loop_linux.c index 52ea6a9a2..ecc9e4395 100644 --- a/util/audio_loop_linux.c +++ b/util/audio_loop_linux.c @@ -2,33 +2,10 @@ * @file * @author Edward A. Lee * @author Soroush Bateni - * - * @section LICENSE -Copyright (c) 2020, The University of California at Berkeley and TU Dresden - -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. - - * @section DESCRIPTION + * @copyright (c) 2020-2023, The University of California at Berkeley and UT Dallas. + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) * - * Audio functions for Linux. + * @brief Utility function for playing audio on Linux. * * See audio_loop.h for instructions. * @@ -313,13 +290,6 @@ void* run_audio_loop(void* ignored) { pthread_t loop_thread_id; bool loop_thread_started = false; -/** - * Start an audio loop thread that becomes ready to receive - * audio amplitude samples via add_to_sound(). If there is - * already an audio loop running, then do nothing. - * @param start_time The logical time that aligns with the - * first audio buffer. - */ void lf_start_audio_loop(instant_t start_time) { if (loop_thread_started) return; @@ -341,30 +311,10 @@ void lf_start_audio_loop(instant_t start_time) { pthread_create(&loop_thread_id, NULL, &run_audio_loop, NULL); } -/** - * Stop the audio loop thread. - */ void lf_stop_audio_loop() { stop_audio = true; } -/** - * Play the specified waveform with the specified emphasis at - * the specified time. If the waveform is null, play a simple tick - * (an impulse). If the waveform has length zero or volume 0, - * play nothing. - * - * If the time is too far in the future - * (beyond the window of the current audio write buffer), then - * block until the audio output catches up. If the audio playback - * has already passed the specified point, then play the waveform - * as soon as possible and return 1. - * Otherwise, return 0. - * - * @param waveform The waveform to play or NULL to just play a tick. - * @param emphasis The emphasis (0.0 for silence, 1.0 for waveform volume). - * @param start_time The time to start playing the waveform. - */ int lf_play_audio_waveform(lf_waveform_t* waveform, float emphasis, instant_t start_time) { int result = 0; pthread_mutex_lock(&lf_audio_mutex); diff --git a/util/audio_loop_mac.c b/util/audio_loop_mac.c index 0a2ada606..c592d2d4d 100644 --- a/util/audio_loop_mac.c +++ b/util/audio_loop_mac.c @@ -1,33 +1,10 @@ /** * @file * @author Edward A. Lee - * - * @section LICENSE -Copyright (c) 2020, The University of California at Berkeley and TU Dresden - -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. - - * @section DESCRIPTION + * @copyright (c) 2020-2023, The University of California at Berkeley and UT Dallas. + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) * - * Audio functions for MacOS. + * @brief Utility function for playing audio on MacOS. * * See audio_loop.h for instructions. * diff --git a/util/wave_file_reader.c b/util/wave_file_reader.c index 1bf4e9fe7..bb84bd120 100644 --- a/util/wave_file_reader.c +++ b/util/wave_file_reader.c @@ -1,35 +1,9 @@ /** * @file * @author Edward A. Lee - * - * @section LICENSE -Copyright (c) 2020, The University of California at Berkeley and TU Dresden - -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. - - * @section DESCRIPTION - * - * Utility functions for importing audio files with the - * wave audio format. This code has few dependencies, so - * it should run on just about any platform. + * @copyright (c) 2020-2023, The University of California at Berkeley + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) + * @brief Utility function for reading WAV audio files. * * See wave_file_reader.h for instructions. */ @@ -37,6 +11,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include "wave_file_reader.h" #if _WIN32 || WIN32 @@ -91,20 +66,6 @@ typedef struct { lf_wav_data_t data; } lf_wav_t; -/** - * Open a wave file, check that the format is supported, - * allocate memory for the sample data, and fill the memory - * with the sample data. It is up to the caller to free the - * memory when done with it. That code should first free the - * waveform element of the returned struct, then the struct itself. - * This implementation supports only 16-bit linear PCM files. - * On a Mac, you can convert audio files into this format - * using the afconvert utility. - * - * @param path The path to the file. - * @return An array of sample data or NULL if the file can't be opened - * or has an usupported format. - */ lf_waveform_t* read_wave_file(const char* path) { FILE *fp = NULL; diff --git a/util/wave_file_reader.h b/util/wave_file_reader.h index ef62bc53e..917d6b4e6 100644 --- a/util/wave_file_reader.h +++ b/util/wave_file_reader.h @@ -1,52 +1,35 @@ /** * @file * @author Edward A. Lee - * - * @section LICENSE -Copyright (c) 2020, The University of California at Berkeley and TU Dresden - -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. - - * @section DESCRIPTION + * @copyright (c) 2020-2023, The University of California at Berkeley + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) + * @brief Utility function for reading WAV audio files. * - * Utility functions and data types for importing audio files with the + * This defines functions and data types for importing audio files with the * wave audio format. The main function is read_wave_file(), which, given * a path to a .wav file, reads the file and, if the format of the file is * supported, returns an lf_waveform_t struct, which contains the raw * audio data in 16-bit linear PCM form. * - * This code has few dependencies, so - * it should run on just about any platform. + * This code has few dependencies, so it should run on just about any platform. * * To use this, include the following flags in your target properties: *
- * target C {
- *     files: ["/lib/C/util/wave_file_reader.c", "/lib/C/util/wave_file_reader.h"]
- * };
+target C {
+    files: [
+        "/lib/c/reactor-c/util/wave_file_reader.c",
+        "/lib/c/reactor-c/util/wave_file_reader.h"
+    ],
+    cmake-include: [
+        "/lib/c/reactor-c/util/wave_file_reader.cmake"
+    ]
+}
  * 
* - * In addition, you need this in your Lingua Franca file: + * In addition, you need this in your Lingua Franca file or reactor: *
  * preamble {=
- *     #include "wave_file_reader.c"
+ *     #include "wave_file_reader.h"
  * =}
  * 
*/ From 3ac86974f05b14481da83f21e039704f35130a5b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 22 Apr 2023 00:55:21 +0200 Subject: [PATCH 10/28] Cleaned up docs and const args --- util/sensor_simulator.c | 96 ++++++------------------------- util/sensor_simulator.h | 122 +++++++++++++++++----------------------- 2 files changed, 69 insertions(+), 149 deletions(-) diff --git a/util/sensor_simulator.c b/util/sensor_simulator.c index 38cfea964..6f404b95e 100644 --- a/util/sensor_simulator.c +++ b/util/sensor_simulator.c @@ -1,34 +1,12 @@ /** -@file -@author Edward A. Lee (eal@berkeley.edu) - -@section LICENSE -Copyright (c) 2020, 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. - -@section DESCRIPTION - -See sensor_simulator.h. -*/ + * @file + * @author Edward A. Lee + * @copyright (c) 2020-2023, The University of California at Berkeley and UT Dallas. + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) + * + * @brief Simple terminal-based user interface based on ncurses. + * See sensor_simulator.h. + */ #include #include @@ -64,7 +42,7 @@ enum _lf_sensor_message_type { typedef struct _lf_sensor_message_t { enum _lf_sensor_message_type type; - char* message; + char* message; struct _lf_sensor_message_t* next; } _lf_sensor_message_t; @@ -101,7 +79,7 @@ struct { FILE* log_file; /** The welcome message. */ - char** welcome_message; + const char** welcome_message; /** The length of the welcome message. */ int welcome_message_length; @@ -122,7 +100,7 @@ struct { * @param message_lines The message lines. * @param number_of_lines The number of lines. */ -void _lf_show_message(char* message_lines[], int number_of_lines) { +void _lf_show_message(const char* message_lines[], int number_of_lines) { int term_height, term_width; int message_width = 0; // Find the widest message in the list. @@ -367,9 +345,6 @@ void* _lf_sensor_simulator_thread(void* ignored) { return NULL; } -/** - * End ncurses control of the terminal. - */ void end_sensor_simulator() { lf_register_print_function(NULL, -1); _lf_sensor_post_message(_lf_sensor_close_windows, NULL); @@ -386,27 +361,8 @@ void end_sensor_simulator() { } } -/** - * Start the sensor simulator if it has not been already - * started. This must be called at least once before any - * call to register_sensor_key. The specified message - * is an initial message to display at the upper left, - * typically a set of instructions, that remains displayed - * throughout the lifetime of the window. Please ensure that - * the message_lines array and its contained strings are not - * on the stack because they will be used later in a separate - * thread. - * @param message_lines The message lines. - * @param number_of_lines The number of lines. - * @param tick_window_width The width of the tick window or 0 for none. - * @param log_file If non-NULL, the name of a file to which to write logging messages. - * @param log_level The level of log messages to redirect to the file. - * The level should be one of LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, - * LOG_LEVEL_INFO, LOG_LEVEL_LOG, LOG_LEVEL_DEBUG, or LOG_LEVEL_ALL. - * @return 0 for success, error code for failure. - */ int start_sensor_simulator( - char* message_lines[], + const char* message_lines[], int number_of_lines, int tick_window_width, char* log_file, @@ -454,34 +410,14 @@ int start_sensor_simulator( return result; } -/** - * Place a tick (usually a single character) in the tick window. - * @param character The tick character. - */ -void show_tick(char* character) { +void show_tick(const char* character) { if (character != NULL) { - _lf_sensor_post_message(_lf_sensor_tick, character); + char* copy; + asprintf(©, "%s", character); + _lf_sensor_post_message(_lf_sensor_tick, copy); } } -/** - * Register a keyboard key to trigger the specified action. - * Printable ASCII characters (codes 32 to 127) are supported - * plus '\n' and '\0', where the latter registers a trigger - * to invoked when any key is pressed. If a specific key is - * registered and any key ('\0') is also registered, the - * any key trigger will be scheduled after the specific key - * is scheduled. If these triggers belong to different reactors, - * they could be invoked in parallel. - * This will fail if the specified key has already been - * registered (error code 1), or the key is not a supported key - * (error code 2) or if the trigger is NULL - * (error code 3). - * @param key The key to register. - * @param action The action to trigger when the key is pressed - * (a pointer to a trigger_t struct). - * @return 0 for success, error code for failure. - */ int register_sensor_key(char key, void* action) { if (action == NULL) { return 3; diff --git a/util/sensor_simulator.h b/util/sensor_simulator.h index 650445878..4b18a828e 100644 --- a/util/sensor_simulator.h +++ b/util/sensor_simulator.h @@ -1,83 +1,67 @@ -/** -@file -@author Edward A. Lee (eal@berkeley.edu) - -@section LICENSE -Copyright (c) 2020, 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. - -@section DESCRIPTION - -When prototyping Lingua Franca programs on a laptop, it is convenient to use -the laptop keyboard to simulate asynchronous sensor input. This small library -provides a convenient way to do that. - -To use this, include the following flags in your target properties: -
-target C {
-    cmake-include: "include/ncurses-cmake-extension.txt", // Adds support for ncurses
-    files: ["/lib/C/util/sensor_simulator.c", "/lib/C/util/sensor_simulator.h"]
-};
-
-This requires `ncurses`, a library providing somewhat portable keyboard access. - -In addition, you need this in your Lingua Franca file: -
-preamble {=
-    #include "sensor_simulator.c"
-=}
-
-To start the sensor simulator, call `start_sensor_simulator` passing it -an array of strings to print and the width of the window to use to display -characters using the `show_tick` function. - -To print messages to the screen, rather than using printf(), you should use -the messaging functions in util.h, such as lf_print(). Otherwise, your messages -will be printed over other information. -*/ - #ifndef SENSOR_SIMULATOR_H #define SENSOR_SIMULATOR_H +/** + * @file + * @author Edward A. Lee + * @copyright (c) 2020-2023, The University of California at Berkeley and UT Dallas. + * License in [BSD 2-clause](https://github.com/lf-lang/reactor-c/blob/main/LICENSE.md) + * + * @brief Simple terminal-based user interface based on ncurses. + * + * When prototyping Lingua Franca programs on a laptop, it is convenient to use + * the laptop keyboard to simulate asynchronous sensor input. This small library + * provides a convenient way to do that. + * + * To use this, include the following flags in your target properties: + *
+ * target C {
+    files: [
+        "/lib/c/reactor-c/util/sensor_simulator.c", 
+        "/lib/c/reactor-c/util/sensor_simulator.h",
+    ],
+    cmake-include: [
+        "/lib/c/reactor-c/util/sensor_simulator.cmake",
+    ] 
+ * };
+ * 
+ * This requires `ncurses`, a library providing somewhat portable keyboard access. + * + * In addition, you need this in your Lingua Franca file: + *
+ * preamble {=
+ *     #include "sensor_simulator.c"
+ * =}
+ * 
+ * To start the sensor simulator, call `start_sensor_simulator` passing it + * an array of strings to print and the width of the window to use to display + * characters using the `show_tick` function. + * + * To print messages to the screen, rather than using printf(), you should use + * the messaging functions in util.h, such as lf_print(). Otherwise, your messages + * will be printed over other information. + */ /** * Start the sensor simulator if it has not been already * started. This must be called at least once before any - * call to register_sensor_key. If given, this will - * put a message in the center of the terminal window. - * The message will be left justified, with each string - * in the specified array on a new line. - * If a tick_window_width is given, then a second window - * will be created that is intended to show activity, - * typically using a single character per event. - * @param message_lines The message lines or NULL for none. - * @param number_of_lines The number of message lines or 0 for none. + * call to register_sensor_key. The specified message + * is an initial message to display at the upper left, + * typically a set of instructions, that remains displayed + * throughout the lifetime of the window. Please ensure that + * the message_lines array and its contained strings are not + * on the stack because they will be used later in a separate + * thread. + * @param message_lines The message lines. + * @param number_of_lines The number of lines. * @param tick_window_width The width of the tick window or 0 for none. * @param log_file If non-NULL, the name of a file to which to write logging messages. * @param log_level The level of log messages to redirect to the file. * The level should be one of LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, - * LOG_LEVEL_INFO, LOG_LEVEL_LOG, or LOG_LEVEL_DEBUG. + * LOG_LEVEL_INFO, LOG_LEVEL_LOG, LOG_LEVEL_DEBUG, or LOG_LEVEL_ALL. + * @return 0 for success, error code for failure. */ int start_sensor_simulator( - char* message_lines[], + const char* message_lines[], int number_of_lines, int tick_window_width, char* log_file, @@ -93,7 +77,7 @@ void end_sensor_simulator(); * Place a tick (usually a single character) in the tick window. * @param character The tick character. */ -void show_tick(char* character); +void show_tick(const char* character); /** * Register a keyboard key to trigger the specified action. From c75d29ec9e600b428db78dc5ead63b49722cd7b9 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 22 Apr 2023 00:55:42 +0200 Subject: [PATCH 11/28] Added cmake file for wave reader --- util/wave_file_reader.cmake | 1 + 1 file changed, 1 insertion(+) create mode 100644 util/wave_file_reader.cmake diff --git a/util/wave_file_reader.cmake b/util/wave_file_reader.cmake new file mode 100644 index 000000000..6cab61ae2 --- /dev/null +++ b/util/wave_file_reader.cmake @@ -0,0 +1 @@ +target_sources(${LF_MAIN_TARGET} PRIVATE wave_file_reader.c) From f344f55e678d2eb4d7a40eb4725ea2dcc3baf897 Mon Sep 17 00:00:00 2001 From: Jakio815 Date: Sat, 22 Apr 2023 14:47:31 +0900 Subject: [PATCH 12/28] Add mac options --- core/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index dde09fe7a..705c42ef8 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -53,6 +53,9 @@ target_include_directories(core PUBLIC ../include/core/utils) # Link with OpenSSL library if(DEFINED FEDERATED_AUTHENTICATED) + if (APPLE) + set(OPENSSL_ROOT_DIR /usr/local/opt/openssl) + endif() find_package(OpenSSL REQUIRED) target_link_libraries(core PUBLIC OpenSSL::SSL) endif() From 2c4ee46d63da73afb1516233120651560d5458d1 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sun, 23 Apr 2023 08:46:27 +0200 Subject: [PATCH 13/28] const modifier to suppress warnings --- core/trace.c | 2 +- include/core/trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/trace.c b/core/trace.c index 9b2878485..648c26812 100644 --- a/core/trace.c +++ b/core/trace.c @@ -237,7 +237,7 @@ void flush_trace(int worker) { lf_critical_section_exit(); } -void start_trace(char* filename) { +void start_trace(const char* filename) { // FIXME: location of trace file should be customizable. _lf_trace_file = fopen(filename, "w"); if (_lf_trace_file == NULL) { diff --git a/include/core/trace.h b/include/core/trace.h index 5b2cf2589..2aa66f38b 100644 --- a/include/core/trace.h +++ b/include/core/trace.h @@ -248,7 +248,7 @@ int register_user_trace_event(char* description); * Open a trace file and start tracing. * @param filename The filename for the trace file. */ -void start_trace(char* filename); +void start_trace(const char* filename); /** * Trace an event identified by a type and a pointer to the self struct of the reactor instance. From cc661615c84afab03d0fefa5fb98e74916392881 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Tue, 25 Apr 2023 16:13:09 +0200 Subject: [PATCH 14/28] Uncommented code tof fix memory leak --- core/threaded/scheduler_NP.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/threaded/scheduler_NP.c b/core/threaded/scheduler_NP.c index 2877b2aff..b3076eeef 100644 --- a/core/threaded/scheduler_NP.c +++ b/core/threaded/scheduler_NP.c @@ -331,9 +331,9 @@ void lf_sched_init( * This must be called when the scheduler is no longer needed. */ void lf_sched_free() { - // for (size_t j = 0; j <= _lf_sched_instance->max_reaction_level; j++) { - // free(((reaction_t***)_lf_sched_instance->_lf_sched_triggered_reactions)[j]); - // } + for (size_t j = 0; j <= _lf_sched_instance->max_reaction_level; j++) { + free(((reaction_t***)_lf_sched_instance->_lf_sched_triggered_reactions)[j]); + } free(_lf_sched_instance->_lf_sched_triggered_reactions); free(_lf_sched_instance->_lf_sched_executing_reactions); lf_semaphore_destroy(_lf_sched_instance->_lf_sched_semaphore); From 93cb07d47f40373fb4aaac05645e439d4709d67e Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Tue, 25 Apr 2023 16:30:03 +0200 Subject: [PATCH 15/28] Removed incorrect free --- core/threaded/scheduler_NP.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/threaded/scheduler_NP.c b/core/threaded/scheduler_NP.c index b3076eeef..57d754e71 100644 --- a/core/threaded/scheduler_NP.c +++ b/core/threaded/scheduler_NP.c @@ -335,7 +335,6 @@ void lf_sched_free() { free(((reaction_t***)_lf_sched_instance->_lf_sched_triggered_reactions)[j]); } free(_lf_sched_instance->_lf_sched_triggered_reactions); - free(_lf_sched_instance->_lf_sched_executing_reactions); lf_semaphore_destroy(_lf_sched_instance->_lf_sched_semaphore); } From 59ad0882453e2edb489f2359e05822d1f8ebfd13 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Wed, 26 Apr 2023 10:28:38 +0200 Subject: [PATCH 16/28] Moved memory leak check to account for persistent tokens --- core/reactor_common.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index 92f73fffb..a0636273d 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1718,15 +1718,6 @@ void termination(void) { interval_t event_time = event->time - start_time; lf_print_warning("---- The first future event has timestamp " PRINTF_TIME " after start time.", event_time); } - // Issue a warning if a memory leak has been detected. - if (_lf_count_payload_allocations > 0) { - lf_print_warning("Memory allocated for messages has not been freed."); - lf_print_warning("Number of unfreed messages: %d.", _lf_count_payload_allocations); - } - if (_lf_count_token_allocations > 0) { - lf_print_warning("Memory allocated for tokens has not been freed!"); - lf_print_warning("Number of unfreed tokens: %d.", _lf_count_token_allocations); - } // Print elapsed times. // If these are negative, then the program failed to start up. interval_t elapsed_time = lf_time_logical_elapsed(); @@ -1743,6 +1734,15 @@ void termination(void) { } } _lf_free_all_tokens(); // Must be done before freeing reactors. + // Issue a warning if a memory leak has been detected. + if (_lf_count_payload_allocations > 0) { + lf_print_warning("Memory allocated for messages has not been freed."); + lf_print_warning("Number of unfreed messages: %d.", _lf_count_payload_allocations); + } + if (_lf_count_token_allocations > 0) { + lf_print_warning("Memory allocated for tokens has not been freed!"); + lf_print_warning("Number of unfreed tokens: %d.", _lf_count_token_allocations); + } _lf_free_all_reactors(); free(_lf_is_present_fields); free(_lf_is_present_fields_abbreviated); From 2f0fdad7535a7f639f421ac8bc5eec2a159df34c Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Wed, 26 Apr 2023 11:02:12 +0200 Subject: [PATCH 17/28] Resurrected lf_set_array --- include/api/set.h | 4 ++-- include/core/reactor.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/api/set.h b/include/api/set.h index 44c29aa1b..3e61f3d37 100644 --- a/include/api/set.h +++ b/include/api/set.h @@ -80,7 +80,7 @@ do { \ } while (0) /** - * Version of lf_set for output types given as 'type[]' where you + * Version of lf_set for output types given as `type[]` or `type*` where you * want to send a previously dynamically allocated array. * * The deallocation is delegated to downstream reactors, which @@ -95,7 +95,7 @@ do { \ #define SET_ARRAY(out, val, elem_size, length) \ do { \ _Pragma ("Warning \"'SET_ARRAY' is deprecated.\""); \ - _LF_SET_ARRAY(out, val, length); \ + lf_set_array(out, val, length); \ } while (0) /** diff --git a/include/core/reactor.h b/include/core/reactor.h index 6ff487082..936b54a8b 100644 --- a/include/core/reactor.h +++ b/include/core/reactor.h @@ -131,14 +131,14 @@ do { \ * @see lf_token_t */ #ifndef __cplusplus -#define _LF_SET_ARRAY(out, val, length) \ +#define lf_set_array(out, val, length) \ do { \ _lf_set_present((lf_port_base_t*)out); \ lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, length); \ out->value = token->value; \ } while(0) #else -#define _LF_SET_ARRAY(out, val, length) \ +#define lf_set_array(out, val, length) \ do { \ _lf_set_present((lf_port_base_t*)out); \ lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, length); \ From 5c0ba3b43545758a8f96dc168e6947afc767626b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 27 Apr 2023 13:29:16 +0200 Subject: [PATCH 18/28] First pass a refactoring --- core/reactor_common.c | 52 ++--------------------- core/threaded/CMakeLists.txt | 1 + core/threaded/watchdog.c | 71 ++++++++++++++++++++++++++++++++ include/api/api.h | 13 ------ include/core/lf_types.h | 28 +------------ include/core/reactor.h | 14 ------- include/core/reactor_common.h | 5 --- include/core/threaded/watchdog.h | 35 ++++++++++++++++ lib/schedule.c | 7 ---- 9 files changed, 112 insertions(+), 114 deletions(-) create mode 100644 core/threaded/watchdog.c create mode 100644 include/core/threaded/watchdog.h diff --git a/core/reactor_common.c b/core/reactor_common.c index 6caafe63a..a3c2912b8 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1291,50 +1291,6 @@ trigger_handle_t _lf_schedule_int(lf_action_base_t* action, interval_t extra_del return _lf_schedule_value(action, extra_delay, container, 1); } -#ifdef LF_THREADED - -void* run_watchdog(void* arg) { - watchdog_t* watchdog = (watchdog_t*)arg; - - self_base_t* base = watchdog->base; - lf_mutex_lock(&(base->watchdog_mutex)); - - while (lf_time_physical() < watchdog->expiration) { - interval_t T = watchdog->expiration - lf_time_physical(); - lf_mutex_unlock(&(base->watchdog_mutex)); - lf_sleep(T); - lf_mutex_lock(&(base->watchdog_mutex)); - } - - if (watchdog->expiration != NEVER) { - watchdog_function_t watchdog_func = watchdog->watchdog_function; - (*watchdog_func)(base); - } - watchdog->thread_active = false; - - lf_mutex_unlock(&(base->watchdog_mutex)); - watchdog->thread_active = false; - return NULL; -} - -void _lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout) { - // Assumes reaction mutex is already held. - - self_base_t* base = watchdog->base; - - watchdog->expiration = lf_time_logical() + watchdog->min_expiration + additional_timeout; - - if (!watchdog->thread_active) { - lf_thread_create(&(watchdog->thread_id), run_watchdog, watchdog); - watchdog->thread_active = true; - } -} - -void _lf_watchdog_stop(watchdog_t* watchdog) { - watchdog->expiration = NEVER; -} -#endif - /** * Invoke the given reaction @@ -1345,8 +1301,8 @@ void _lf_watchdog_stop(watchdog_t* watchdog) { void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED - if (((self_base_t*) reaction->self)->has_watchdog == true) { - lf_mutex_lock(&(((self_base_t*) reaction->self)->watchdog_mutex)); + if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { + lf_mutex_lock((lf_mutex*)((self_base_t*)reaction->self)->reaction_mutex); } #endif @@ -1358,8 +1314,8 @@ void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED - if (((self_base_t*) reaction->self)->has_watchdog == true) { - lf_mutex_unlock(&(((self_base_t*) reaction->self)->watchdog_mutex)); + if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { + lf_mutex_unlock((lf_mutex*)((self_base_t*)reaction->self)->reaction_mutex); } #endif } diff --git a/core/threaded/CMakeLists.txt b/core/threaded/CMakeLists.txt index 95989b8ad..334c8bfa2 100644 --- a/core/threaded/CMakeLists.txt +++ b/core/threaded/CMakeLists.txt @@ -7,6 +7,7 @@ set( scheduler_NP.c scheduler_PEDF_NP.c scheduler_sync_tag_advance.c + watchdog.c ) list(APPEND INFO_SOURCES ${THREADED_SOURCES}) diff --git a/core/threaded/watchdog.c b/core/threaded/watchdog.c new file mode 100644 index 000000000..2f41d99d9 --- /dev/null +++ b/core/threaded/watchdog.c @@ -0,0 +1,71 @@ +/** + * @file + * @author Benjamin Asch + * @author Edward A. Lee + * @copyright (c) 2023, The University of California at Berkeley. + * License: BSD 2-clause + * @brief Definitions for watchdogs. + */ + +#include "watchdog.h" + +extern int _lf_watchdog_number; + +/** + * Watchdog function type. The argument passed to one of + * these watchdog functions is a pointer to the self struct + * for the reactor. + */ +typedef void(*watchdog_function_t)(void*); + +void _lf_initialize_watchdog_mutexes() { + for (int i = 0; i < _lf_watchdog_number; i++) { + self_base_t* current_base = _lf_watchdogs[i]->base; + if (&(current_base->watchdog_mutex) == NULL) { + lf_mutex_init(&(current_base->watchdog_mutex)); + current_base->has_watchdog = true; + } + } +} + +void* _lf_run_watchdog(void* arg) { + watchdog_t* watchdog = (watchdog_t*)arg; + + self_base_t* base = watchdog->base; + assert(base->reaction_mutex != NULL); + lf_mutex_lock((lf_mutex*)base->reaction_mutex); + + while (lf_time_physical() < watchdog->expiration) { + interval_t T = watchdog->expiration - lf_time_physical(); + lf_mutex_unlock((lf_mutex*)base->reaction_mutex); + lf_sleep(T); + lf_mutex_lock((lf_mutex*)base->reaction_mutex); + } + + if (watchdog->expiration != NEVER) { + watchdog_function_t watchdog_func = watchdog->watchdog_function; + (*watchdog_func)(base); + } + watchdog->thread_active = false; + + lf_mutex_unlock((lf_mutex*)base->reaction_mutex); + watchdog->thread_active = false; + return NULL; +} + +void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout) { + // Assumes reaction mutex is already held. + + self_base_t* base = watchdog->base; + + watchdog->expiration = lf_time_logical() + watchdog->min_expiration + additional_timeout; + + if (!watchdog->thread_active) { + lf_thread_create(&(watchdog->thread_id), _lf_run_watchdog, watchdog); + watchdog->thread_active = true; + } +} + +void lf_watchdog_stop(watchdog_t* watchdog) { + watchdog->expiration = NEVER; +} diff --git a/include/api/api.h b/include/api/api.h index a17000050..505e6aed9 100644 --- a/include/api/api.h +++ b/include/api/api.h @@ -170,19 +170,6 @@ trigger_handle_t lf_schedule_value(void* action, interval_t extra_delay, void* v */ bool lf_check_deadline(void* self, bool invoke_deadline_handler); -#ifdef LF_THREADED -/** - * Begin the watchdog. - * - * @param watchdog The watchdog to be started. - * @param additional_timeout The timeout to be added to the minimum - * experiation of the watchdog. - **/ -void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); - -void lf_watchdog_stop(watchdog_t* watchdog); -#endif - /** * Compare two tags. Return -1 if the first is less than * the second, 0 if they are equal, and +1 if the first is diff --git a/include/core/lf_types.h b/include/core/lf_types.h index d66039e53..559c44e3d 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -140,13 +140,6 @@ typedef pqueue_pri_t index_t; */ typedef void(*reaction_function_t)(void*); -/** - * Watchdog function type. The argument passed to one of - * these watchdog functions is a pointer to the self struct - * for the reactor. - */ -typedef void(*watchdog_function_t)(void*); - /** Trigger struct representing an output, timer, action, or input. See below. */ typedef struct trigger_t trigger_t; @@ -216,23 +209,6 @@ struct event_t { event_t* next; // Pointer to the next event lined up in superdense time. }; -/** Typdef for watchdog_t struct, used to call watchdog handler. */ -typedef struct watchdog_t watchdog_t; - -#ifdef LF_THREADED -/** Watchdog struct for handler. */ -struct watchdog_t { - struct self_base_t* base; // The reactor that contains the watchdog. - trigger_t* trigger; // The trigger associated with this watchdog. - instant_t expiration; // The expiration instant for the watchdog. (Initialized to NEVER) - interval_t min_expiration; // The minimum expiration interval for the watchdog. - lf_thread_t thread_id; // The thread that the watchdog is meant to run on. - bool thread_active; // Boolean indicating whether or not thread is active. - watchdog_function_t watchdog_function; // The function/handler for the watchdog. -}; -#endif - - /** * Trigger struct representing an output, timer, action, or input. */ @@ -303,9 +279,7 @@ typedef struct self_base_t { struct allocation_record_t *allocations; struct reaction_t *executing_reaction; // The currently executing reaction of the reactor. #ifdef LF_THREADED - lf_mutex_t watchdog_mutex; // The mutex for this reactor to be acquired before reaction - // invocation. - bool has_watchdog; // Boolean signifying initialization of watchdog_mutex + void* reaction_mutex; // If not null, this is expected to point to an lf_mutex. #endif #ifdef MODAL_REACTORS reactor_mode_state_t _lf__mode_state; // The current mode (for modal models). diff --git a/include/core/reactor.h b/include/core/reactor.h index d09a60ec0..a2d527688 100644 --- a/include/core/reactor.h +++ b/include/core/reactor.h @@ -535,20 +535,6 @@ trigger_handle_t _lf_schedule_copy(lf_action_base_t* action, interval_t offset, */ void _lf_fd_send_stop_request_to_rti(void); - -#ifdef LF_THREADED -/** - * Function to start the watchdog. - * - * @param watchdog The watchdog to be started - * @param additional_timeout Additional timeout to be added to the watchdog's - * minimum expiration. - **/ -void _lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); - -void _lf_watchdog_stop(watchdog_t* watchdog); -#endif - /** * These functions must be implemented by both threaded and unthreaded * runtime. Should be routed to appropriate API calls in platform.h diff --git a/include/core/reactor_common.h b/include/core/reactor_common.h index 0efe4b110..7e0620346 100644 --- a/include/core/reactor_common.h +++ b/include/core/reactor_common.h @@ -82,11 +82,6 @@ trigger_handle_t _lf_insert_reactions_for_trigger(trigger_t* trigger, lf_token_t void _lf_advance_logical_time(instant_t next_time); trigger_handle_t _lf_schedule_int(lf_action_base_t* action, interval_t extra_delay, int value); -#ifdef LF_THREADED -void* run_watchdog(void* arg); -void _lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); -void _lf_watchdog_stop(watchdog_t* watchdog); -#endif void _lf_invoke_reaction(reaction_t* reaction, int worker); void schedule_output_reactions(reaction_t* reaction, int worker); int process_args(int argc, const char* argv[]); diff --git a/include/core/threaded/watchdog.h b/include/core/threaded/watchdog.h new file mode 100644 index 000000000..07c3965a1 --- /dev/null +++ b/include/core/threaded/watchdog.h @@ -0,0 +1,35 @@ +/** + * @file + * @author Benjamin Asch + * @author Edward A. Lee + * @copyright (c) 2023, The University of California at Berkeley. + * License: BSD 2-clause + * @brief Declarations for watchdogs. + */ + +#include "platform.h" + +/** Typdef for watchdog_t struct, used to call watchdog handler. */ +typedef struct watchdog_t watchdog_t; + +/** Watchdog struct for handler. */ +struct watchdog_t { + struct self_base_t* base; // The reactor that contains the watchdog. + trigger_t* trigger; // The trigger associated with this watchdog. + instant_t expiration; // The expiration instant for the watchdog. (Initialized to NEVER) + interval_t min_expiration; // The minimum expiration interval for the watchdog. + lf_thread_t thread_id; // The thread that the watchdog is meant to run on. + bool thread_active; // Boolean indicating whether or not thread is active. + watchdog_function_t watchdog_function; // The function/handler for the watchdog. +}; + +/** + * Start or restart the watchdog. + * + * @param watchdog The watchdog to be started + * @param additional_timeout Additional timeout to be added to the watchdog's + * minimum expiration. + */ +void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); + +void lf_watchdog_stop(watchdog_t* watchdog); diff --git a/lib/schedule.c b/lib/schedule.c index 11e955dc4..67c182447 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -200,11 +200,4 @@ bool lf_check_deadline(void* self, bool invoke_deadline_handler) { return false; } -#ifdef LF_THREADED -void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout) { - return _lf_watchdog_start(watchdog, additional_timeout); -} -void lf_watchdog_stop(watchdog_t* watchdog) { - return _lf_watchdog_stop(watchdog); -} #endif \ No newline at end of file From 4aef0ef54ca233b3cd9ff43863d0ffa715b91e8b Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Thu, 27 Apr 2023 17:57:29 +0200 Subject: [PATCH 19/28] Fixed compile errors --- core/reactor_common.c | 4 ++-- core/threaded/watchdog.c | 23 ++++++++--------------- include/core/lf_types.h | 1 + include/core/threaded/watchdog.h | 7 +++++++ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index a3c2912b8..4bf469c35 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -1302,7 +1302,7 @@ void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { - lf_mutex_lock((lf_mutex*)((self_base_t*)reaction->self)->reaction_mutex); + lf_mutex_lock((lf_mutex_t*)((self_base_t*)reaction->self)->reaction_mutex); } #endif @@ -1315,7 +1315,7 @@ void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { - lf_mutex_unlock((lf_mutex*)((self_base_t*)reaction->self)->reaction_mutex); + lf_mutex_unlock((lf_mutex_t*)((self_base_t*)reaction->self)->reaction_mutex); } #endif } diff --git a/core/threaded/watchdog.c b/core/threaded/watchdog.c index 2f41d99d9..ae79e3199 100644 --- a/core/threaded/watchdog.c +++ b/core/threaded/watchdog.c @@ -10,20 +10,13 @@ #include "watchdog.h" extern int _lf_watchdog_number; - -/** - * Watchdog function type. The argument passed to one of - * these watchdog functions is a pointer to the self struct - * for the reactor. - */ -typedef void(*watchdog_function_t)(void*); +extern watchdog_t* _lf_watchdogs; void _lf_initialize_watchdog_mutexes() { for (int i = 0; i < _lf_watchdog_number; i++) { - self_base_t* current_base = _lf_watchdogs[i]->base; - if (&(current_base->watchdog_mutex) == NULL) { - lf_mutex_init(&(current_base->watchdog_mutex)); - current_base->has_watchdog = true; + self_base_t* current_base = _lf_watchdogs[i].base; + if (current_base->reaction_mutex != NULL) { + lf_mutex_init((lf_mutex_t*)(current_base->reaction_mutex)); } } } @@ -33,13 +26,13 @@ void* _lf_run_watchdog(void* arg) { self_base_t* base = watchdog->base; assert(base->reaction_mutex != NULL); - lf_mutex_lock((lf_mutex*)base->reaction_mutex); + lf_mutex_lock((lf_mutex_t*)(base->reaction_mutex)); while (lf_time_physical() < watchdog->expiration) { interval_t T = watchdog->expiration - lf_time_physical(); - lf_mutex_unlock((lf_mutex*)base->reaction_mutex); + lf_mutex_unlock((lf_mutex_t*)base->reaction_mutex); lf_sleep(T); - lf_mutex_lock((lf_mutex*)base->reaction_mutex); + lf_mutex_lock((lf_mutex_t*)(base->reaction_mutex)); } if (watchdog->expiration != NEVER) { @@ -48,7 +41,7 @@ void* _lf_run_watchdog(void* arg) { } watchdog->thread_active = false; - lf_mutex_unlock((lf_mutex*)base->reaction_mutex); + lf_mutex_unlock((lf_mutex_t*)(base->reaction_mutex)); watchdog->thread_active = false; return NULL; } diff --git a/include/core/lf_types.h b/include/core/lf_types.h index 559c44e3d..78e517c6e 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -280,6 +280,7 @@ typedef struct self_base_t { struct reaction_t *executing_reaction; // The currently executing reaction of the reactor. #ifdef LF_THREADED void* reaction_mutex; // If not null, this is expected to point to an lf_mutex. + // It is not declared as such to avoid a dependence on platform.h. #endif #ifdef MODAL_REACTORS reactor_mode_state_t _lf__mode_state; // The current mode (for modal models). diff --git a/include/core/threaded/watchdog.h b/include/core/threaded/watchdog.h index 07c3965a1..1b26ba340 100644 --- a/include/core/threaded/watchdog.h +++ b/include/core/threaded/watchdog.h @@ -9,6 +9,13 @@ #include "platform.h" +/** + * Watchdog function type. The argument passed to one of + * these watchdog functions is a pointer to the self struct + * for the reactor. + */ +typedef void(*watchdog_function_t)(void*); + /** Typdef for watchdog_t struct, used to call watchdog handler. */ typedef struct watchdog_t watchdog_t; From c6c549d43aa5144e5c1d4eea4feb16a410c40fd3 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Fri, 28 Apr 2023 09:35:16 +0200 Subject: [PATCH 20/28] Added LF_PROJECT_DIRECTORY --- core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 2f3fd275f..98f3e6a64 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -105,5 +105,6 @@ define(NUMBER_OF_FEDERATES) define(NUMBER_OF_WORKERS) define(SCHEDULER) define(LF_SOURCE_DIRECTORY) +define(LF_PROJECT_DIRECTORY) define(LF_FILE_SEPARATOR) define(WORKERS_NEEDED_FOR_FEDERATE) From 5d58c62cb141e13c423cdadd11dbf97c8edd2d75 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Fri, 28 Apr 2023 11:51:47 +0200 Subject: [PATCH 21/28] Continued refactoring --- core/threaded/watchdog.c | 1 + include/core/threaded/watchdog.h | 4 ++-- lib/schedule.c | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/threaded/watchdog.c b/core/threaded/watchdog.c index ae79e3199..24d758a56 100644 --- a/core/threaded/watchdog.c +++ b/core/threaded/watchdog.c @@ -7,6 +7,7 @@ * @brief Definitions for watchdogs. */ +#include #include "watchdog.h" extern int _lf_watchdog_number; diff --git a/include/core/threaded/watchdog.h b/include/core/threaded/watchdog.h index 1b26ba340..a8853d7e4 100644 --- a/include/core/threaded/watchdog.h +++ b/include/core/threaded/watchdog.h @@ -21,8 +21,8 @@ typedef struct watchdog_t watchdog_t; /** Watchdog struct for handler. */ struct watchdog_t { - struct self_base_t* base; // The reactor that contains the watchdog. - trigger_t* trigger; // The trigger associated with this watchdog. + struct self_base_t* base; // The reactor that contains the watchdog. + trigger_t* trigger; // The trigger associated with this watchdog. instant_t expiration; // The expiration instant for the watchdog. (Initialized to NEVER) interval_t min_expiration; // The minimum expiration interval for the watchdog. lf_thread_t thread_id; // The thread that the watchdog is meant to run on. diff --git a/lib/schedule.c b/lib/schedule.c index 67c182447..30367cb7f 100644 --- a/lib/schedule.c +++ b/lib/schedule.c @@ -199,5 +199,3 @@ bool lf_check_deadline(void* self, bool invoke_deadline_handler) { } return false; } - -#endif \ No newline at end of file From 8eaf16fdc46df596cf85f7be7e901988cabcd873 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 29 Apr 2023 06:51:11 +0200 Subject: [PATCH 22/28] LF_PROJECT_DIRECTORY to LF_PACKAGE_DIRECTORY --- core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 98f3e6a64..31409c377 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -105,6 +105,6 @@ define(NUMBER_OF_FEDERATES) define(NUMBER_OF_WORKERS) define(SCHEDULER) define(LF_SOURCE_DIRECTORY) -define(LF_PROJECT_DIRECTORY) +define(LF_PACKAGE_DIRECTORY) define(LF_FILE_SEPARATOR) define(WORKERS_NEEDED_FOR_FEDERATE) From 68e2c14fabf124f280e656e23f1954df1fd80657 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 29 Apr 2023 11:29:27 +0200 Subject: [PATCH 23/28] Continued refactoring and docs --- core/reactor_common.c | 18 ++++++++++---- core/threaded/watchdog.c | 40 +++++++++++++++++++++++--------- include/core/lf_types.h | 2 +- include/core/threaded/watchdog.h | 14 ++++++++++- 4 files changed, 57 insertions(+), 17 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index 4bf469c35..0994e74af 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -55,6 +55,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vector.h" #include "hashset/hashset.h" #include "hashset/hashset_itr.h" +#include "watchdog.h" // Global variable defined in tag.c: extern tag_t current_tag; @@ -63,6 +64,10 @@ extern instant_t start_time; // Global variable defined in lf_token.c: extern int _lf_count_payload_allocations; +// Code generated global variables. +extern int _lf_watchdog_number; +extern watchdog_t* _lf_watchdogs; + /** * Indicator of whether to wait for physical time to match logical time. * By default, execution will wait. The command-line argument -fast will @@ -1301,8 +1306,8 @@ trigger_handle_t _lf_schedule_int(lf_action_base_t* action, interval_t extra_del void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED - if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { - lf_mutex_lock((lf_mutex_t*)((self_base_t*)reaction->self)->reaction_mutex); + if (((self_base_t*) reaction->self)->reactor_mutex != NULL) { + lf_mutex_lock((lf_mutex_t*)((self_base_t*)reaction->self)->reactor_mutex); } #endif @@ -1314,8 +1319,8 @@ void _lf_invoke_reaction(reaction_t* reaction, int worker) { #ifdef LF_THREADED - if (((self_base_t*) reaction->self)->reaction_mutex != NULL) { - lf_mutex_unlock((lf_mutex_t*)((self_base_t*)reaction->self)->reaction_mutex); + if (((self_base_t*) reaction->self)->reactor_mutex != NULL) { + lf_mutex_unlock((lf_mutex_t*)((self_base_t*)reaction->self)->reactor_mutex); } #endif } @@ -1758,6 +1763,11 @@ void termination(void) { lf_print_warning("Memory allocated for tokens has not been freed!"); lf_print_warning("Number of unfreed tokens: %d.", _lf_count_token_allocations); } + for (int i = 0; i < _lf_watchdog_number; i++) { + if (_lf_watchdogs[i].base->reactor_mutex != NULL) { + free(_lf_watchdogs[i].base->reactor_mutex); + } + } _lf_free_all_reactors(); free(_lf_is_present_fields); free(_lf_is_present_fields_abbreviated); diff --git a/core/threaded/watchdog.c b/core/threaded/watchdog.c index 24d758a56..f93245fdc 100644 --- a/core/threaded/watchdog.c +++ b/core/threaded/watchdog.c @@ -13,27 +13,46 @@ extern int _lf_watchdog_number; extern watchdog_t* _lf_watchdogs; +/** + * @brief Initialize watchdog mutexes. + * For any reactor with one or more watchdogs, the self struct should have a non-NULL + * `reactor_mutex` field which points to an instance of `lf_mutex_t`. + * This function initializes those mutexes. + */ void _lf_initialize_watchdog_mutexes() { for (int i = 0; i < _lf_watchdog_number; i++) { self_base_t* current_base = _lf_watchdogs[i].base; - if (current_base->reaction_mutex != NULL) { - lf_mutex_init((lf_mutex_t*)(current_base->reaction_mutex)); + if (current_base->reactor_mutex != NULL) { + lf_mutex_init((lf_mutex_t*)(current_base->reactor_mutex)); } } } +/** + * @brief Thread function for watchdog. + * This function sleeps until physical time exceeds the expiration time of + * the watchdog and then invokes the watchdog expiration handler function. + * In normal usage, the expiration time is incremented while the thread is + * sleeping, so the watchdog never expires and the handler function is never + * invoked. + * This function acquires the reaction mutex and releases it while sleeping. + * + * @param arg A pointer to the watchdog struct + * @return NULL + */ void* _lf_run_watchdog(void* arg) { watchdog_t* watchdog = (watchdog_t*)arg; self_base_t* base = watchdog->base; - assert(base->reaction_mutex != NULL); - lf_mutex_lock((lf_mutex_t*)(base->reaction_mutex)); - - while (lf_time_physical() < watchdog->expiration) { - interval_t T = watchdog->expiration - lf_time_physical(); - lf_mutex_unlock((lf_mutex_t*)base->reaction_mutex); + assert(base->reactor_mutex != NULL); + lf_mutex_lock((lf_mutex_t*)(base->reactor_mutex)); + instant_t physical_time = lf_time_physical(); + while (physical_time < watchdog->expiration) { + interval_t T = watchdog->expiration - physical_time; + lf_mutex_unlock((lf_mutex_t*)base->reactor_mutex); lf_sleep(T); - lf_mutex_lock((lf_mutex_t*)(base->reaction_mutex)); + lf_mutex_lock((lf_mutex_t*)(base->reactor_mutex)); + physical_time = lf_time_physical(); } if (watchdog->expiration != NEVER) { @@ -42,8 +61,7 @@ void* _lf_run_watchdog(void* arg) { } watchdog->thread_active = false; - lf_mutex_unlock((lf_mutex_t*)(base->reaction_mutex)); - watchdog->thread_active = false; + lf_mutex_unlock((lf_mutex_t*)(base->reactor_mutex)); return NULL; } diff --git a/include/core/lf_types.h b/include/core/lf_types.h index 78e517c6e..d71dbaf7a 100644 --- a/include/core/lf_types.h +++ b/include/core/lf_types.h @@ -279,7 +279,7 @@ typedef struct self_base_t { struct allocation_record_t *allocations; struct reaction_t *executing_reaction; // The currently executing reaction of the reactor. #ifdef LF_THREADED - void* reaction_mutex; // If not null, this is expected to point to an lf_mutex. + void* reactor_mutex; // If not null, this is expected to point to an lf_mutex_t. // It is not declared as such to avoid a dependence on platform.h. #endif #ifdef MODAL_REACTORS diff --git a/include/core/threaded/watchdog.h b/include/core/threaded/watchdog.h index a8853d7e4..6d5bf72a6 100644 --- a/include/core/threaded/watchdog.h +++ b/include/core/threaded/watchdog.h @@ -31,7 +31,13 @@ struct watchdog_t { }; /** - * Start or restart the watchdog. + * @brief Start or restart the watchdog timer. + * This function sets the expiration time of the watchdog to the current logical time + * plus the minimum timeout of the watchdog plus the specified `additional_timeout`. + * If a watchdog timer thread is not already running, then this function will start one. + * This function assumes the reactor mutex is held when it is called; this assumption + * is satisfied whenever this function is called from within a reaction that declares + * the watchdog as an effect. * * @param watchdog The watchdog to be started * @param additional_timeout Additional timeout to be added to the watchdog's @@ -39,4 +45,10 @@ struct watchdog_t { */ void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); +/** + * @brief Stop the specified watchdog without invoking the expiration handler. + * This function sets the expiration time of the watchdog to `NEVER`. + * + * @param watchdog The watchdog. + */ void lf_watchdog_stop(watchdog_t* watchdog); From f762f01902745dff40b9170dce273d29b6df5212 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sat, 29 Apr 2023 23:00:11 -0700 Subject: [PATCH 24/28] Update README.md --- util/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/README.md b/util/README.md index c05656fe3..8f1bf9226 100644 --- a/util/README.md +++ b/util/README.md @@ -4,7 +4,7 @@ This directory contains source files for use by Lingua Franca programs using the C target. To use a file in this directory, specify a target property as follows: ``` target C { - files: ["/lib/C/util/filename", ...], + files: ["/lib/c/reactor-c/util/filename", ...], ... }; ``` @@ -14,4 +14,4 @@ directory. Hence, you can include the file in your C code as follows: preamble {= #include "filename" =} -``` \ No newline at end of file +``` From 32559bfb0dc2f47f0267580aaf8a840a123f4d2a Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 1 May 2023 11:02:27 +0200 Subject: [PATCH 25/28] Removed watchdog initialization for unthreaded runtime --- core/reactor.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/reactor.c b/core/reactor.c index 1172d2c60..62824e480 100644 --- a/core/reactor.c +++ b/core/reactor.c @@ -368,8 +368,6 @@ int lf_reactor_c_main(int argc, const char* argv[]) { _lf_trigger_startup_reactions(); _lf_initialize_timers(); - _lf_initialize_watchdog_mutexes(); - // If the stop_tag is (0,0), also insert the shutdown // reactions. This can only happen if the timeout time // was set to 0. From ffe9a6a2e2bf79f45c1019d48f17b1b92eaf01a5 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 1 May 2023 11:02:52 +0200 Subject: [PATCH 26/28] Guard code to include only for threaded runtime --- core/reactor_common.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/reactor_common.c b/core/reactor_common.c index 0994e74af..7b52548c2 100644 --- a/core/reactor_common.c +++ b/core/reactor_common.c @@ -55,8 +55,15 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "vector.h" #include "hashset/hashset.h" #include "hashset/hashset_itr.h" + +#ifdef LF_THREADED #include "watchdog.h" +// Code generated global variables. +extern int _lf_watchdog_number; +extern watchdog_t* _lf_watchdogs; +#endif + // Global variable defined in tag.c: extern tag_t current_tag; extern instant_t start_time; @@ -64,10 +71,6 @@ extern instant_t start_time; // Global variable defined in lf_token.c: extern int _lf_count_payload_allocations; -// Code generated global variables. -extern int _lf_watchdog_number; -extern watchdog_t* _lf_watchdogs; - /** * Indicator of whether to wait for physical time to match logical time. * By default, execution will wait. The command-line argument -fast will @@ -1763,11 +1766,13 @@ void termination(void) { lf_print_warning("Memory allocated for tokens has not been freed!"); lf_print_warning("Number of unfreed tokens: %d.", _lf_count_token_allocations); } +#ifdef LF_THREADED for (int i = 0; i < _lf_watchdog_number; i++) { if (_lf_watchdogs[i].base->reactor_mutex != NULL) { free(_lf_watchdogs[i].base->reactor_mutex); } } +#endif _lf_free_all_reactors(); free(_lf_is_present_fields); free(_lf_is_present_fields_abbreviated); From 618fa07480964d82ebd88e28378bbfd335adb27c Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Sat, 6 May 2023 06:09:01 -0700 Subject: [PATCH 27/28] Added extern C qualifier --- include/core/platform.h | 8 ++++++++ include/core/threaded/watchdog.h | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/include/core/platform.h b/include/core/platform.h index 30fa251ce..2a632d5fc 100644 --- a/include/core/platform.h +++ b/include/core/platform.h @@ -36,6 +36,10 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef PLATFORM_H #define PLATFORM_H +#ifdef __cplusplus +extern "C" { +#endif + #include "lf_types.h" #if defined(LF_THREADED) && defined(LF_UNTHREADED) @@ -313,4 +317,8 @@ extern int lf_sleep_until_locked(instant_t wakeup_time); */ DEPRECATED(extern int lf_nanosleep(interval_t sleep_duration)); +#ifdef __cplusplus +} +#endif + #endif // PLATFORM_H diff --git a/include/core/threaded/watchdog.h b/include/core/threaded/watchdog.h index 6d5bf72a6..d14c7adad 100644 --- a/include/core/threaded/watchdog.h +++ b/include/core/threaded/watchdog.h @@ -7,8 +7,15 @@ * @brief Declarations for watchdogs. */ +#ifndef WATCHDOG_H +#define WATCHDOG_H 1 + #include "platform.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Watchdog function type. The argument passed to one of * these watchdog functions is a pointer to the self struct @@ -52,3 +59,9 @@ void lf_watchdog_start(watchdog_t* watchdog, interval_t additional_timeout); * @param watchdog The watchdog. */ void lf_watchdog_stop(watchdog_t* watchdog); + +#ifdef __cplusplus +} +#endif + +#endif From 5ed95a7edf8aaf61db22fa946c2a9e8dd7de0572 Mon Sep 17 00:00:00 2001 From: "Edward A. Lee" Date: Mon, 15 May 2023 07:36:45 -0700 Subject: [PATCH 28/28] Update lingua-franca-ref.txt --- 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 021098cc4..5d1996fa8 100644 --- a/lingua-franca-ref.txt +++ b/lingua-franca-ref.txt @@ -1 +1 @@ -watchdogs \ No newline at end of file +watchdogs-eal2