I’m using the RP2040 Port.
From Mastering the FreeRTOS™ Real Time Kernel, “The xEventGroupWaitBits() API Function”,
The calling task specifies bits to test using the uxBitsToWaitFor parameter, and it is likely the
calling task will need to clear these bits back to zero after its unblock condition has been met.
Event bits can be cleared using the xEventGroupClearBits() API function, but using that
function to manually clear event bits will lead to race conditions in the application code if:
There is more than one task using the same event group.
Bits are set in the event group by a different task, or by an interrupt service routine.
The xClearOnExit parameter is provided to avoid these potential race conditions. If
xClearOnExit is set to pdTRUE, then the testing and clearing of event bits appears to the
calling task to be an atomic operation (uninterruptable by other tasks or interrupts).
However, if I’m very much mistaken, this test case shows that testing and clearing of event bits is not atomic:
static EventGroupHandle_t xEventGroupHandle;
#define mask 0x01
static TaskHandle_t owner;
#define N 3
static void Task(void *arg) {
// const EventBits_t mask = 1 << arg;
unsigned task_no = (unsigned)arg;
unsigned rand_st = task_no;
for (;;) {
EventBits_t xBits =
xEventGroupWaitBits(xEventGroupHandle, mask, /* uxBitsToWaitFor */
pdTRUE, /* xClearOnExit */
pdFALSE, /* xWaitForAllBits n.a. */
portMAX_DELAY);
configASSERT(mask & xBits);
configASSERT(0 == owner);
owner = xTaskGetCurrentTaskHandle();
if (rand_r(&rand_st) % 2) {
vTaskDelay(1);
}
owner = 0;
xEventGroupSetBits(xEventGroupHandle, mask);
}
}
int main(void) {
stdio_init_all();
printf("\nHello, world!\n");
xEventGroupHandle = xEventGroupCreate();
configASSERT(xEventGroupHandle);
xEventGroupSetBits(xEventGroupHandle, mask);
for (size_t i = 0; i < N; ++i) {
char cTaskName[configMAX_TASK_NAME_LEN];
snprintf(cTaskName, sizeof(cTaskName), "Task%zu", i);
BaseType_t xReturned =
xTaskCreate(Task, cTaskName, 512, (void *)i,
configMAX_PRIORITIES -
3, /* Priority at which the task is created. */
NULL);
configASSERT(xReturned == pdPASS);
}
vTaskStartScheduler();
/* should never reach here */
panic_unsupported();
}
gives:
Task2: assertion "0 == owner" failed: file "/home/carlk/pi/pico/FreeRTOS/FreeRTOS/Demo/ThirdParty/Community-Supported/CORTEX_M0+_RP2040/OnEitherCore/main.c", line 27, function: Task
It does not fail if I #define N 2
.
Is this a problem in FreeRTOS, or FreeRTOS SMP, or the RP2040 Port? Or am I not very much mistaken?