forked from ROMEO/fsw-ws
once without global mutex
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user