From bb5fbf19cf98e44d2c7d43a42ab9025d996e0ac9 Mon Sep 17 00:00:00 2001 From: Ulrich Mohr Date: Tue, 12 Aug 2025 15:10:56 +0200 Subject: [PATCH] once without global mutex --- mission/freeRTOS_rust_helper.c | 61 +++++++++++++--------------------- 1 file changed, 24 insertions(+), 37 deletions(-) diff --git a/mission/freeRTOS_rust_helper.c b/mission/freeRTOS_rust_helper.c index 08bd8d3..96db555 100644 --- a/mission/freeRTOS_rust_helper.c +++ b/mission/freeRTOS_rust_helper.c @@ -9,23 +9,11 @@ // TODO panic if able, but not in runtime calls -StaticSemaphore_t global_once_mutex_data; -SemaphoreHandle_t global_once_mutex = NULL; - -void freertos_init_once() { - global_once_mutex = - xSemaphoreCreateRecursiveMutexStatic(&global_once_mutex_data); - if (global_once_mutex == NULL) { - // TODO panic - } -} - - // Wraps xTaskGetCurrentTaskHandle and returns NULL if no Task is running // // xTaskGetCurrentTaskHandle() will return a handle even if no task is // running as long as one has been created already. -void *freertos_task_current() { +void *freertos_task_current(void) { // If scheduler is not running, xTaskGetCurrentTaskHandle() might return a // valid handle of a already created task, so we check for Scheduler state // before calling it @@ -42,7 +30,6 @@ StaticTask_t init_task_data; StackType_t init_task_stack[configMINIMAL_STACK_SIZE * 10]; void freertos_init_and_start_scheduling(TaskFunction_t init_task) { - freertos_init_once(); // TaskHandle_t handle = xTaskCreateStatic(init_task, "c_init", configMINIMAL_STACK_SIZE * 10, NULL, configMAX_PRIORITIES - 1, init_task_stack, &init_task_data); @@ -166,8 +153,8 @@ typedef struct { /** * mimics pthread_once() * - * uses a global mutex to threadsafely check if the passed local mutex - * was created already, creating it if not. + * uses a mutex to guard the state, to allow threads to block waiting + * until function has been called. * * After that, the local mutex guards once_data, which is used to only * call the function once. All calls sharing the local_mutex and @@ -181,6 +168,9 @@ typedef struct { */ uint8_t freertos_once(char *once_data_in, uint32_t once_data_len, void *function(void)) { + if (once_data_in == NULL) { + return 0; + } if (once_data_len < sizeof(StaticOnceData_t)) { // TODO panic // printf("freertos_once: data needs to be %zu long\n", @@ -192,21 +182,22 @@ uint8_t freertos_once(char *once_data_in, uint32_t once_data_len, // TODO assert global_once_mutex != NULL // first, we need to check if the local mutex was already created - // this needs to be protected by a mutex to be threadsafe - if (xSemaphoreTakeRecursive(global_once_mutex, portMAX_DELAY) != pdTRUE) { - // TODO panic - } + // this needs to be protected to be threadsafe + // Documentation says that we must not call APIs from within a critical + // Section but I think we are safe in the case of creating a mutex + // which basically only intializes the fields + // TODO verify? + taskENTER_CRITICAL(); if (once_data->once_state == UNINIT) { once_data->local_mutex = xSemaphoreCreateRecursiveMutexStatic(&once_data->local_mutex_data); - if (once_data->local_mutex == NULL) { - // TODO panic - } + // if (once_data->local_mutex == NULL) { + // // will not happen, xSemaphoreCreateRecursiveMutexStatic returns its parameter + // // which we checked above to be != NULL + // } once_data->once_state = INIT; } - if (xSemaphoreGiveRecursive(global_once_mutex) != pdTRUE) { - // TODO panic - } + taskEXIT_CRITICAL(); // Now, we know local mutex is valid, so we use it to guard access to // the once_state @@ -241,24 +232,20 @@ uint8_t freertos_simple_once(uint8_t *once_data) { // TODO assert global_once_mutex != NULL uint8_t result = 0; - // Todo: Replace Mutex with critical section - // This function is basically a flag stored in once_data, protected by the - // global_once_mutex - if (xSemaphoreTakeRecursive(global_once_mutex, portMAX_DELAY) != pdTRUE) { - // TODO panic - } + // This function is basically a flag stored in once_data, protected by + // a critical section + // Critical section is ok, because simple arithmetic is bounded in execution time + taskENTER_CRITICAL(); if (*once_data == 0) { *once_data = 1; result = 1; } - if (xSemaphoreGiveRecursive(global_once_mutex) != pdTRUE) { - // TODO panic - } + taskEXIT_CRITICAL(); return result; } -uint32_t freertos_task_priority_max() { +uint32_t freertos_task_priority_max(void) { // -1 is the max to be used per documentation return configMAX_PRIORITIES - 1; } @@ -301,4 +288,4 @@ void *freertos_mutex_create_static(char *mutex_data, uint32_t mutex_data_len) { return NULL; } return xSemaphoreCreateRecursiveMutexStatic((StaticSemaphore_t *)mutex_data); -} \ No newline at end of file +}