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 /* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
too often in the idle task. */ 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 ); xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
} }
if( xListIsEmpty == pdFALSE ) if( xListIsEmpty == pdFALSE )
{ {
TCB_t *pxTCB;
{ {
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) ); 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 /* 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; --uxTasksDeleted;
} else { } else {
/* Need to wait until the idle task on the other processor kills that task first. */ /* Need to wait until the idle task on the other processor kills that task first. */
taskEXIT_CRITICAL(&xTaskQueueMutex);
break; 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; if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL)
for( x = 0; x < ( UBaseType_t ) configNUM_THREAD_LOCAL_STORAGE_POINTERS; x++ )
{ {
if (pxTCB->pvThreadLocalStoragePointersDelCallback[ x ] != NULL) pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]);
{
pxTCB->pvThreadLocalStoragePointersDelCallback[ x ](x, pxTCB->pvThreadLocalStoragePointers[ x ]);
}
} }
} }
#endif #endif
prvDeleteTCB( pxTCB ); prvDeleteTCB( pxTCB );
} }
else else
{ {
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
} }
taskEXIT_CRITICAL(&xTaskQueueMutex);
} }
#endif /* vTaskDelete */ #endif /* vTaskDelete */
} }