From 1fe57a5d8e1e2ad37acc26ac6f2b8590188e949a Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Wed, 16 Oct 2024 09:59:45 +0200 Subject: [PATCH] fix(freertos): Fixed SMP race condition in xStreamBufferSend() This commit fixes a race condition in dual-core SMP mode where in the xStreamBufferSend() makes the xTaskWaitingToSend NULL but it may have already been evaluated to not be NULL by xStreamBufferReceive() running on another core and eventually leading to a crash in tasks.c. --- components/freertos/FreeRTOS-Kernel/idf_changes.md | 2 ++ components/freertos/FreeRTOS-Kernel/stream_buffer.c | 13 ++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/components/freertos/FreeRTOS-Kernel/idf_changes.md b/components/freertos/FreeRTOS-Kernel/idf_changes.md index 83bee68433..7bf620e6e4 100644 --- a/components/freertos/FreeRTOS-Kernel/idf_changes.md +++ b/components/freertos/FreeRTOS-Kernel/idf_changes.md @@ -125,6 +125,8 @@ The following functions were modified to accommodate SMP behavior: - Added extra check to see if current blocking task has already been deleted by the other core. - `xStreamBufferReceive()` - Added a critical section for setting `xTaskWaitingToReceive` to `NULL` so that the write is SMP safe. +- `xStreamBufferSend()` + - Added a critical section for setting `xTaskWaitingToSend` to `NULL` so that the write is SMP safe. ### Critical Section Changes diff --git a/components/freertos/FreeRTOS-Kernel/stream_buffer.c b/components/freertos/FreeRTOS-Kernel/stream_buffer.c index 988eb3f5f7..04d67a2005 100644 --- a/components/freertos/FreeRTOS-Kernel/stream_buffer.c +++ b/components/freertos/FreeRTOS-Kernel/stream_buffer.c @@ -774,7 +774,18 @@ size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); - pxStreamBuffer->xTaskWaitingToSend = NULL; + /* In SMP mode, the task may have been woken and scheduled on + * another core. Hence, we must clear the xTaskWaitingToSend + * handle in a critical section. */ + #if ( configNUMBER_OF_CORES > 1 ) + taskENTER_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ + { + pxStreamBuffer->xTaskWaitingToSend = NULL; + } + #if ( configNUMBER_OF_CORES > 1 ) + taskEXIT_CRITICAL( &( pxStreamBuffer->xStreamBufferLock ) ); + #endif /* configNUMBER_OF_CORES > 1 */ } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); } else