Skip to content

Commit c01512f

Browse files
Merge branch 'fix/assert_fail_in_xtaskdeletewithcaps' into 'master'
Fixed occational assert failure in vTaskDeleteWithCaps() Closes IDFGH-13294 See merge request espressif/esp-idf!33468
2 parents 19d512e + c36674e commit c01512f

File tree

3 files changed

+71
-65
lines changed

3 files changed

+71
-65
lines changed

components/freertos/esp_additions/idf_additions.c

Lines changed: 42 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,44 @@
8181

8282
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
8383

84-
static void prvTaskDeleteWithCapsTask( void * pvParameters )
84+
static void prvTaskDeleteWithCaps( TaskHandle_t xTaskToDelete )
8585
{
86-
TaskHandle_t xTaskToDelete = ( TaskHandle_t ) pvParameters;
86+
/* Return value unused if asserts are disabled */
87+
BaseType_t __attribute__( ( unused ) ) xResult;
88+
StaticTask_t * pxTaskBuffer;
89+
StackType_t * puxStackBuffer;
90+
91+
/* The task to be deleted must not be running.
92+
* So we suspend the task before deleting it. */
93+
vTaskSuspend( xTaskToDelete );
94+
95+
/* Wait for the task to be suspended */
96+
while( eRunning == eTaskGetState( xTaskToDelete ) )
97+
{
98+
taskYIELD();
99+
}
87100

88-
/* The task to be deleted must not be running */
89101
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
90102

103+
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
104+
configASSERT( xResult == pdTRUE );
105+
configASSERT( puxStackBuffer != NULL );
106+
configASSERT( pxTaskBuffer != NULL );
107+
108+
/* We can delete the task and free the memory buffers. */
109+
vTaskDelete( xTaskToDelete );
110+
111+
/* Free the memory buffers */
112+
heap_caps_free( puxStackBuffer );
113+
vPortFree( pxTaskBuffer );
114+
}
115+
116+
static void prvTaskDeleteWithCapsTask( void * pvParameters )
117+
{
118+
TaskHandle_t xTaskToDelete = ( TaskHandle_t ) pvParameters;
119+
91120
/* Delete the WithCaps task */
92-
vTaskDeleteWithCaps( xTaskToDelete );
121+
prvTaskDeleteWithCaps( xTaskToDelete );
93122

94123
/* Delete the temporary clean up task */
95124
vTaskDelete( NULL );
@@ -98,7 +127,7 @@
98127
void vTaskDeleteWithCaps( TaskHandle_t xTaskToDelete )
99128
{
100129
/* THIS FUNCTION SHOULD NOT BE CALLED FROM AN INTERRUPT CONTEXT. */
101-
/*TODO: Update it to use portASSERT_IF_IN_ISR() instead. (IDF-10540) */
130+
/* TODO: Update it to use portASSERT_IF_IN_ISR() instead. (IDF-10540) */
102131
vPortAssertIfInISR();
103132

104133
TaskHandle_t xCurrentTaskHandle = xTaskGetCurrentTaskHandle();
@@ -151,60 +180,8 @@
151180
}
152181
}
153182

154-
#if ( configNUM_CORES > 1 )
155-
else if( eRunning == eTaskGetState( xTaskToDelete ) )
156-
{
157-
/* The WithCaps task is running on another core.
158-
* We suspend the task first and then delete it. */
159-
vTaskSuspend( xTaskToDelete );
160-
161-
/* Wait for the task to be suspended */
162-
while( eRunning == eTaskGetState( xTaskToDelete ) )
163-
{
164-
portYIELD_WITHIN_API();
165-
}
166-
167-
// Return value unused if asserts are disabled
168-
BaseType_t __attribute__((unused)) xResult;
169-
StaticTask_t * pxTaskBuffer;
170-
StackType_t * puxStackBuffer;
171-
172-
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
173-
configASSERT( xResult == pdTRUE );
174-
configASSERT( puxStackBuffer != NULL );
175-
configASSERT( pxTaskBuffer != NULL );
176-
177-
/* Delete the task */
178-
vTaskDelete( xTaskToDelete );
179-
180-
/* Free the memory buffers */
181-
heap_caps_free( puxStackBuffer );
182-
vPortFree( pxTaskBuffer );
183-
}
184-
#endif /* if ( configNUM_CORES > 1 ) */
185-
else
186-
{
187-
/* The WithCaps task is not running and is being deleted
188-
* from another task's context. */
189-
configASSERT( eRunning != eTaskGetState( xTaskToDelete ) );
190-
191-
// Return value unused if asserts are disabled
192-
BaseType_t __attribute__((unused)) xResult;
193-
StaticTask_t * pxTaskBuffer;
194-
StackType_t * puxStackBuffer;
195-
196-
xResult = xTaskGetStaticBuffers( xTaskToDelete, &puxStackBuffer, &pxTaskBuffer );
197-
configASSERT( xResult == pdTRUE );
198-
configASSERT( puxStackBuffer != NULL );
199-
configASSERT( pxTaskBuffer != NULL );
200-
201-
/* We can delete the task and free the memory buffers. */
202-
vTaskDelete( xTaskToDelete );
203-
204-
/* Free the memory buffers */
205-
heap_caps_free( puxStackBuffer );
206-
vPortFree( pxTaskBuffer );
207-
} /* if( ( xTaskToDelete == NULL ) || ( xTaskToDelete == xCurrentTaskHandle ) ) */
183+
/* Delete the WithCaps task */
184+
prvTaskDeleteWithCaps( xTaskToDelete );
208185
}
209186

210187
#endif /* if ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
@@ -262,8 +239,8 @@
262239

263240
void vQueueDeleteWithCaps( QueueHandle_t xQueue )
264241
{
265-
// Return value unused if asserts are disabled
266-
BaseType_t __attribute__((unused)) xResult;
242+
/* Return value unused if asserts are disabled */
243+
BaseType_t __attribute__( ( unused ) ) xResult;
267244
StaticQueue_t * pxQueueBuffer;
268245
uint8_t * pucQueueStorageBuffer;
269246

@@ -335,8 +312,8 @@
335312

336313
void vSemaphoreDeleteWithCaps( SemaphoreHandle_t xSemaphore )
337314
{
338-
// Return value unused if asserts are disabled
339-
BaseType_t __attribute__((unused)) xResult;
315+
/* Return value unused if asserts are disabled */
316+
BaseType_t __attribute__( ( unused ) ) xResult;
340317
StaticSemaphore_t * pxSemaphoreBuffer;
341318

342319
/* Retrieve the buffer used to create the semaphore before deleting it
@@ -408,8 +385,8 @@
408385
void vStreamBufferGenericDeleteWithCaps( StreamBufferHandle_t xStreamBuffer,
409386
BaseType_t xIsMessageBuffer )
410387
{
411-
// Return value unused if asserts are disabled
412-
BaseType_t __attribute__((unused)) xResult;
388+
/* Return value unused if asserts are disabled */
389+
BaseType_t __attribute__( ( unused ) ) xResult;
413390
StaticStreamBuffer_t * pxStaticStreamBuffer;
414391
uint8_t * pucStreamBufferStorageArea;
415392

components/freertos/test_apps/freertos/misc/test_idf_additions.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,34 @@ TEST_CASE("IDF additions: Task creation with memory caps and self deletion", "[f
8989
xTaskNotifyGive(task_handle);
9090
}
9191

92+
#if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
93+
94+
TEST_CASE("IDF additions: Task creation with SPIRAM memory caps and self deletion stress test", "[freertos]")
95+
{
96+
#define TEST_NUM_TASKS 5
97+
#define TEST_NUM_ITERATIONS 1000
98+
TaskHandle_t task_handle[TEST_NUM_TASKS];
99+
StackType_t *puxStackBuffer;
100+
StaticTask_t *pxTaskBuffer;
101+
102+
for (int j = 0; j < TEST_NUM_ITERATIONS; j++) {
103+
for (int i = 0; i < TEST_NUM_TASKS; i++) {
104+
// Create a task with caps
105+
TEST_ASSERT_EQUAL(pdPASS, xTaskCreateWithCaps(task_with_caps_self_delete, "task", 4096, NULL, UNITY_FREERTOS_PRIORITY, &task_handle[i], MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
106+
TEST_ASSERT_NOT_EQUAL(NULL, task_handle);
107+
// Get the task's memory
108+
TEST_ASSERT_EQUAL(pdTRUE, xTaskGetStaticBuffers(task_handle[i], &puxStackBuffer, &pxTaskBuffer));
109+
}
110+
111+
for (int i = 0; i < TEST_NUM_TASKS; i++) {
112+
// Notify the task to delete itself
113+
xTaskNotifyGive(task_handle[i]);
114+
}
115+
}
116+
}
117+
118+
#endif /* CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY */
119+
92120
#if ( CONFIG_FREERTOS_NUMBER_OF_CORES > 1 )
93121

94122
static void task_with_caps_running_on_other_core(void *arg)

components/freertos/test_apps/freertos/sdkconfig.ci.psram

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CONFIG_IDF_TARGET="esp32"
55
# Enable SPIRAM
66
CONFIG_SPIRAM=y
77
CONFIG_SPIRAM_OCCUPY_NO_HOST=y
8+
CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY=y
89

910
# Disable encrypted flash reads/writes to save IRAM in this build configuration
1011
CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=n

0 commit comments

Comments
 (0)