Assertion fail on xQueueSemaphoreTake for task scheduler suspended

I’m trying to debug an assertion fail which happens in my application, running with the Posix port of the kernel (I’m testing it on my PC). I have a simple thread structure, with two main threads:

  • one is running a loop which performs some logic and locks/unlocks a semaphore using the xSemaphoreTake and xSemaphoreGive (with portMAX_DELAY timeout) to control the access on a data buffer
  • the other thread is running an endless loop with a vTaskDelay(50) (it should also be calling another function but for simplicity I’ve replicated the issue with just the delay

If I’m understanding it correctly the vTaskDelay always call the vTaskSuspendAll() to add the task to the delayed list and then the xTaskResumeAll() to restart the scheduler; however it seems that this conflicts with the fact that the semaphore functions check for the following assert

configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );

Should I be doing things differently?

Hi - I would like to double check I understand the issue you are seeing.

When you have task A locking and unlocking a semaphore, and task B calling vTaskDelay(), you find task A triggers the assert you posted because task B temporarily locks the scheduler. Is this correct?

If that is correct then it would seem to be an error because the two tasks are independent of each other, so a switch to Task A should not be possible while the scheduler is locked by task B.

Which version of FreeRTOS are you using (it will say in the comments at the top of the source file)? What is configNUMBER_OF_CORES set to?

It would also help if you can share code snippets of your tasks.

When you have task A locking and unlocking a semaphore, and task B calling vTaskDelay(), you find task A triggers the assert you posted because task B temporarily locks the scheduler. Is this correct?

This is correct.

Which version of FreeRTOS are you using (it will say in the comments at the top of the source file)?

I’m using the V11.0.1 kernel as a git submodule.

What is configNUMBER_OF_CORES set to?

Actually this is a good question, I didn’t set it so I imagine it defaults to 1. I tried setting it to 8 but I get some compile errors for more missing defines, I’ll have to work on that for a bit.

It would also help if you can share code snippets of your tasks.

I tried recreating a small project with the same structure but that doesn’t seem to be triggering the assert; the code is something along the lines of

static void taskSleep(__attribute__((unused)) void const *arg)
{
    while (1)
    {
        vTaskDelay(5);
    }
}

static SemaphoreHandle_t pTestMutex = NULL;

static void taskApplication(__attribute__((unused)) void const *arg)
{
    pTestMutex = xSemaphoreCreateMutex();
    configASSERT(pTestMutex != NULL);

    while (1)
    {
        if (xSemaphoreTake(pTestMutex, portMAX_DELAY) == pdTRUE)
        {
            // Simulate work
            vTaskDelay(5);
            xSemaphoreGive(pTestMutex);
        }

        vTaskDelay(5);
    }
}

static void initTasks()
{
    pxApplicationTask = xTaskCreateStatic((TaskFunction_t)taskApplication, "app", CONFIG_APPLICATION_STK_SZ, NULL,
                                          CONFIG_APPLICATION_PRIO, xApplicationTaskStack, &xApplicationTaskBuffer);
    configASSERT(NULL != pxApplicationTask);

    pxSleepTask = xTaskCreateStatic((TaskFunction_t)taskSleep, "sleep", CONFIG_SLEEP_STK_SZ, NULL, CONFIG_SLEEP_PRIO,
                                    xSleepTaskStack, &xSleepTaskBuffer);
    configASSERT(NULL != pxSleepTask);
}

int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
{
    initTasks();

    vTaskStartScheduler();

    while (1)
    {
    }

    return 0;
}

This is an indicator that the problem is likely elsewhere. Can you try disabling parts of your application to locate the problematic code section?