fix(freertos): Fixed assert failure in vTaskDeleteWithCaps

This commit fixes an assert failure in vTaskDeleteWithCaps() when
multiple un-pinned tasks are created with stack in the external memory
and such tasks delete themselves.

Closes https://github.com/espressif/esp-idf/issues/14222
This commit is contained in:
Sudeep Mohanty 2024-09-11 15:14:52 +02:00
parent 02cd0253a1
commit c36674eaa8

View File

@ -81,15 +81,44 @@ err:
#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
static void prvTaskDeleteWithCaps( TaskHandle_t xTaskToDelete )
{
/* Return value unused if asserts are disabled */
BaseType_t __attribute__( ( unused ) ) xResult;
StaticTask_t * pxTaskBuffer;
StackType_t * puxStackBuffer;
/* The task to be deleted must not be running.
* So we suspend the task before deleting it. */
vTaskSuspend( xTaskToDelete );
/* Wait for the task to be suspended */
while( eRunning == eTaskGetState( xTaskToDelete ) )
{
taskYIELD();
}
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
configASSERT( xResult == pdTRUE );
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );
/* We can delete the task and free the memory buffers. */
vTaskDelete( xTaskToDelete );
/* Free the memory buffers */
heap_caps_free( puxStackBuffer );
vPortFree( pxTaskBuffer );
}
static void prvTaskDeleteWithCapsTask( void * pvParameters ) static void prvTaskDeleteWithCapsTask( void * pvParameters )
{ {
TaskHandle_t xTaskToDelete = ( TaskHandle_t ) pvParameters; TaskHandle_t xTaskToDelete = ( TaskHandle_t ) pvParameters;
/* The task to be deleted must not be running */
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
/* Delete the WithCaps task */ /* Delete the WithCaps task */
vTaskDeleteWithCaps( xTaskToDelete ); prvTaskDeleteWithCaps( xTaskToDelete );
/* Delete the temporary clean up task */ /* Delete the temporary clean up task */
vTaskDelete( NULL ); vTaskDelete( NULL );
@ -98,7 +127,7 @@ err:
void vTaskDeleteWithCaps( TaskHandle_t xTaskToDelete ) void vTaskDeleteWithCaps( TaskHandle_t xTaskToDelete )
{ {
/* THIS FUNCTION SHOULD NOT BE CALLED FROM AN INTERRUPT CONTEXT. */ /* THIS FUNCTION SHOULD NOT BE CALLED FROM AN INTERRUPT CONTEXT. */
/*TODO: Update it to use portASSERT_IF_IN_ISR() instead. (IDF-10540) */ /* TODO: Update it to use portASSERT_IF_IN_ISR() instead. (IDF-10540) */
vPortAssertIfInISR(); vPortAssertIfInISR();
TaskHandle_t xCurrentTaskHandle = xTaskGetCurrentTaskHandle(); TaskHandle_t xCurrentTaskHandle = xTaskGetCurrentTaskHandle();
@ -151,60 +180,8 @@ err:
} }
} }
#if ( configNUM_CORES > 1 ) /* Delete the WithCaps task */
else if( eRunning == eTaskGetState( xTaskToDelete ) ) prvTaskDeleteWithCaps( xTaskToDelete );
{
/* The WithCaps task is running on another core.
* We suspend the task first and then delete it. */
vTaskSuspend( xTaskToDelete );
/* Wait for the task to be suspended */
while( eRunning == eTaskGetState( xTaskToDelete ) )
{
portYIELD_WITHIN_API();
}
// Return value unused if asserts are disabled
BaseType_t __attribute__((unused)) xResult;
StaticTask_t * pxTaskBuffer;
StackType_t * puxStackBuffer;
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
configASSERT( xResult == pdTRUE );
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );
/* Delete the task */
vTaskDelete( xTaskToDelete );
/* Free the memory buffers */
heap_caps_free( puxStackBuffer );
vPortFree( pxTaskBuffer );
}
#endif /* if ( configNUM_CORES > 1 ) */
else
{
/* The WithCaps task is not running and is being deleted
* from another task's context. */
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
// Return value unused if asserts are disabled
BaseType_t __attribute__((unused)) xResult;
StaticTask_t * pxTaskBuffer;
StackType_t * puxStackBuffer;
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
configASSERT( xResult == pdTRUE );
configASSERT( puxStackBuffer != NULL );
configASSERT( pxTaskBuffer != NULL );
/* We can delete the task and free the memory buffers. */
vTaskDelete( xTaskToDelete );
/* Free the memory buffers */
heap_caps_free( puxStackBuffer );
vPortFree( pxTaskBuffer );
} /* if( ( xTaskToDelete == NULL ) || ( xTaskToDelete == xCurrentTaskHandle ) ) */
} }
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ #endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
@ -262,8 +239,8 @@ err:
void vQueueDeleteWithCaps( QueueHandle_t xQueue ) void vQueueDeleteWithCaps( QueueHandle_t xQueue )
{ {
// Return value unused if asserts are disabled /* Return value unused if asserts are disabled */
BaseType_t __attribute__((unused)) xResult; BaseType_t __attribute__( ( unused ) ) xResult;
StaticQueue_t * pxQueueBuffer; StaticQueue_t * pxQueueBuffer;
uint8_t * pucQueueStorageBuffer; uint8_t * pucQueueStorageBuffer;
@ -335,8 +312,8 @@ err:
void vSemaphoreDeleteWithCaps( SemaphoreHandle_t xSemaphore ) void vSemaphoreDeleteWithCaps( SemaphoreHandle_t xSemaphore )
{ {
// Return value unused if asserts are disabled /* Return value unused if asserts are disabled */
BaseType_t __attribute__((unused)) xResult; BaseType_t __attribute__( ( unused ) ) xResult;
StaticSemaphore_t * pxSemaphoreBuffer; StaticSemaphore_t * pxSemaphoreBuffer;
/* Retrieve the buffer used to create the semaphore before deleting it /* Retrieve the buffer used to create the semaphore before deleting it
@ -408,8 +385,8 @@ err:
void vStreamBufferGenericDeleteWithCaps( StreamBufferHandle_t xStreamBuffer, void vStreamBufferGenericDeleteWithCaps( StreamBufferHandle_t xStreamBuffer,
BaseType_t xIsMessageBuffer ) BaseType_t xIsMessageBuffer )
{ {
// Return value unused if asserts are disabled /* Return value unused if asserts are disabled */
BaseType_t __attribute__((unused)) xResult; BaseType_t __attribute__( ( unused ) ) xResult;
StaticStreamBuffer_t * pxStaticStreamBuffer; StaticStreamBuffer_t * pxStaticStreamBuffer;
uint8_t * pucStreamBufferStorageArea; uint8_t * pucStreamBufferStorageArea;