once without global mutex

This commit is contained in:
2025-08-12 15:10:56 +02:00
parent 243fd19827
commit bb5fbf19cf
+24 -37
View File
@@ -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);
}
}