In the FreeRTOS Windows (Win32) simulator port, critical sections and scheduler protection are implemented using Windows Mutex (a Windows synchronization primitive), instead of disabling and enabling hardware interrupts (as is done on real embedded platforms).
Each call to xTaskCreate()
uses this Windows Mutex
/ReleaseMutex
pair to protect the scheduler’s ready‐list. But, if you create a higher‑priority task while still holding that mutex, the scheduler immediately switches to the new task. This leaves the mutex locked in xTaskCreate()
. When the new task invokes any kernel call (even vTaskSuspend(NULL)
), it deadlocks trying to reacquire the same mutex.
This is why creating many tasks, with the last one at highest priority, can cause deadlock about half the times, as the preemption happens before the mutex is released.
To avoid this, you can either bulk‑create tasks at the same priority and then elevate one with vTaskPrioritySet()
, or (as shown below) simply bracket your creation loop within a critical section using vTaskSuspendAll()
/vTaskResumeAll()
so no context switch (and thus no premature mutex contention) can occur until all tasks are safely created.
void task0( void * pvParameters )
{
vTaskSuspendAll();
for(int i = 0; i < NUMBER_OF_TASKS; i++)
{
int priority = (i == NUMBER_OF_TASKS-1) ? HIGHER_PRIORITY : LOWER_PRIORITY;
xTaskCreate(task1, "T1", configMINIMAL_STACK_SIZE, NULL, priority, NULL);
}
xTaskResumeAll();
/* Now the highest‑priority task can run */
vTaskSuspend(NULL);
}