freertos: Idle task shouldn't hold xTaskQueueMutex while calling TLS destructors

If the callbacks use any blocking call (ie printf), this can otherwise trigger a deadlock.
This commit is contained in:
Angus Gratton 2017-10-05 12:12:19 +11:00 committed by Angus Gratton
parent 2ccc2ec5ee
commit 3234064b6a

View file

@ -3577,17 +3577,16 @@ static void prvCheckTasksWaitingTermination( void )
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
too often in the idle task. */
taskENTER_CRITICAL(&xTaskQueueMutex);
while( uxTasksDeleted > ( UBaseType_t ) 0U )
while(uxTasksDeleted > ( UBaseType_t ) 0U )
{
TCB_t *pxTCB = NULL;
taskENTER_CRITICAL(&xTaskQueueMutex);
{
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
}
if( xListIsEmpty == pdFALSE )
{
TCB_t *pxTCB;
{
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
/* We only want to kill tasks that ran on this core because e.g. _xt_coproc_release needs to
@ -3598,30 +3597,31 @@ static void prvCheckTasksWaitingTermination( void )
--uxTasksDeleted;
} else {
/* Need to wait until the idle task on the other processor kills that task first. */
taskEXIT_CRITICAL(&xTaskQueueMutex);
break;
}
}
}
taskEXIT_CRITICAL(&xTaskQueueMutex);
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
if (pxTCB != NULL) {
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
int x;
for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
{
int x;
for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL)
{
if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL)
{
pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]);
}
pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]);
}
}
#endif
prvDeleteTCB( pxTCB );
#endif
prvDeleteTCB( pxTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
#endif /* vTaskDelete */
}