I’m now porting FreeRTOS V11.1.0 with SMP to my RISC-V and encountering some problems when using semaphores. Now I’m running with two cores.
The tasks are created and binded to core-0 and core-1 and the semaphore is initialized as a mutex.
void smp_example(void)
{
xMutex = xSemaphoreCreateMutex();
/* create a task and pin them each cpu */
for (UBaseType_t i = 0; i < CONFIG_NR_CPUS; i++)
{
char name[32];
TaskHandle_t xHandle = NULL;
snprintf(name, sizeof(name), "thread_pinned_%u", (unsigned int)i);
UBaseType_t uxCoreAffinityMask = (1 << i); // core id
BaseType_t ret = xTaskCreate(task_entry, name, 8192 / sizeof(StackType_t), NULL, tskIDLE_PRIORITY + 5 + i, &xHandle);
task_created[i] = xHandle;
if (ret != pdPASS)
{
printf("create task failed\r\n");
vTaskResume(xHandle);
}
vTaskCoreAffinitySet(xHandle, uxCoreAffinityMask );
}
}
in task_entry, they take the semaphores and print the line to the COM.
void task_entry(void *parameter)
{
while (1)
{
int id = csi_get_cpu_id();
TaskHandle_t tcb_cur = xTaskGetCurrentTaskHandle();
if( xMutex == NULL )
{
printf("mutex is null\r\n");
}
if (xSemaphoreTake(xMutex, 0) == pdTRUE)
{
printf("[%s] in %lu core, tid = %p, count: %d, MIE = 0x%x, MIP = 0x%x\r\n", pcTaskGetName(NULL), (unsigned long)id, tcb_cur, g_count++, __get_MIE(), __get_MIP());
xSemaphoreGive(xMutex);
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
but it hits the assert in xTaskPriorityDisinherit()
/* A task can only have an inherited priority if it holds the mutex.
* If the mutex is held by a task then it cannot be given from an
* interrupt, and if a mutex is given by the holding task then it must
* be the running state task. */
configASSERT( pxTCB == pxCurrentTCB );
it’s because both of the two tasks acquire the mutex and access the protected resource at the same time. So we can see the mutex is locked by a task and released by the other.
Does the functions xQueueSemaphoreTake()
goes wrong in SMP? taskENTER_CRITICAL()
only disables Interrupt of the current core.
I think these code should be execute within the context of a spinlock, but it doesn’t.
// line 1681 in queue.c, xQueueSemaphoreTake()
taskENTER_CRITICAL();
{
/* Semaphores are queues with an item size of 0, and where the
* number of messages in the queue is the semaphore's count value. */
const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
/* Is there data in the queue now? To be running the calling task
* must be the highest priority task wanting to access the queue. */
if( uxSemaphoreCount > ( UBaseType_t ) 0 )
{
traceQUEUE_RECEIVE( pxQueue );
/* Semaphores are queues with a data size of zero and where the
* messages waiting is the semaphore's count. Reduce the count. */
pxQueue->uxMessagesWaiting = ( UBaseType_t ) ( uxSemaphoreCount - ( UBaseType_t ) 1 );
#if ( configUSE_MUTEXES == 1 )
{
...
Thanks and appreciate for your help!