I have developed a program that periodically reads some input, does some processing, and writes some output. Plain old global variables are used for sharing information among tasks.
Recently I’ve learned about the data race UB in C11, and I realize the program is full of data races.
To solve the data race problem, I can define the global variables as atomic or use mutexes to protect the global variables. But that seems a lot of work.
I am wondering whether the data race can be solved by simply defining configUSE_PREEMPTION
0 instead of the original 1. Is there something I should watch out if configUSE_PREEMPTION is changed to 0? Thanks very much.
The basic idea of the program:
struct Input1 { int someData[50]; /*...*/ } g_input1;
struct Input2 { int someData[50]; /*...*/ } g_input2;
struct Output1 { int someData[50]; /*...*/ } g_output1;
struct Output2 { int someData[50]; /*...*/ } g_output2;
// task bodies, run every step, non-blocking
void GetInput1(struct Input1 *);
void GetInput2(struct Input2 *);
void Process(const struct Input1 *, const struct Input2 *, struct Output1 *, struct Output2 *);
void SetOutput1(const struct Output1 *);
void SetOutput2(const struct Output2 *);
#define PERIOD pdMS_TO_TICKS(10)
void InputTask1(void *arg) {
for (;;) {
GetInput1(&g_input1);
vTaskDelay(PERIOD);
}
}
void InputTask2(void *arg) {
for (;;) {
GetInput2(&g_input2);
vTaskDelay(PERIOD);
}
}
void ProcessTask(void *arg) {
for (;;) {
// consume input and produce output
Process(&g_input1, &g_input2, &g_output1, &g_output2);
vTaskDelay(PERIOD);
}
}
void OutputTask1(void *arg) {
for (;;) {
SetOutput1(&g_output1);
vTaskDelay(PERIOD);
}
}
void OutputTask2(void *arg) {
for (;;) {
SetOutput2(&g_output2);
vTaskDelay(PERIOD);
}
}
int main(void) {
// same priority, task order doesn't really matter
xTaskCreate(InputTask1 /*...*/);
xTaskCreate(InputTask2 /*...*/);
xTaskCreate(ProcessTask /*...*/);
xTaskCreate(OutputTask1 /*...*/);
xTaskCreate(OutputTask2 /*...*/);
vTaskStartScheduler();
}