mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'fix/freertos_delete_with_caps_smp_race_v5.2' into 'release/v5.2'
fix(freertos): close vTaskDeleteWithCaps cross-core delete race on SMP preview kernel (v5.2) See merge request espressif/esp-idf!48604
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -92,14 +92,43 @@ err:
|
|||||||
* So we suspend the task before deleting it. */
|
* So we suspend the task before deleting it. */
|
||||||
vTaskSuspend( xTaskToDelete );
|
vTaskSuspend( xTaskToDelete );
|
||||||
|
|
||||||
/* Wait for the task to be suspended */
|
/* Wait until the task is no longer the current task on any core.
|
||||||
while( eRunning == eTaskGetState( xTaskToDelete ) )
|
*
|
||||||
|
* Polling on pxCurrentTCBs[] (via xTaskGetCurrentTaskHandleForCore())
|
||||||
|
* matches the predicate vTaskDelete() uses to choose between immediate
|
||||||
|
* and IDLE-deferred TCB cleanup. By waiting on it here, we guarantee
|
||||||
|
* that the vTaskDelete() call below takes the immediate path and that
|
||||||
|
* prvDeleteTCB() runs synchronously before vTaskDelete() returns, so
|
||||||
|
* the heap_caps_free() / vPortFree() that follow cannot race with the
|
||||||
|
* IDLE task. */
|
||||||
|
for( ;; )
|
||||||
{
|
{
|
||||||
|
BaseType_t xStillOnCore = pdFALSE;
|
||||||
|
|
||||||
|
for( BaseType_t xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ )
|
||||||
|
{
|
||||||
|
if( xTaskGetCurrentTaskHandleForCore( xCoreID ) == xTaskToDelete )
|
||||||
|
{
|
||||||
|
xStillOnCore = pdTRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xStillOnCore == pdFALSE )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
taskYIELD();
|
taskYIELD();
|
||||||
}
|
}
|
||||||
|
|
||||||
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
|
/* We can delete the task and free the memory buffers.
|
||||||
|
* First, we must call `vTaskDelete` so that the port task delete callback is called.
|
||||||
|
* On targets that have coprocessors, it may be possible that the stack pointer is modified (restored)
|
||||||
|
* during this phase, hence, it must be done before getting the statuc buffers out of the task. */
|
||||||
|
vTaskDelete( xTaskToDelete );
|
||||||
|
|
||||||
|
/* Free the memory buffers */
|
||||||
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
|
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
|
||||||
configASSERT( xResult == pdTRUE );
|
configASSERT( xResult == pdTRUE );
|
||||||
configASSERT( puxStackBuffer != NULL );
|
configASSERT( puxStackBuffer != NULL );
|
||||||
|
|||||||
Reference in New Issue
Block a user