From aa8fcad60b4f56aef849eae603eb6b1a2d62060c Mon Sep 17 00:00:00 2001 From: John Boiles Date: Fri, 17 Jan 2025 13:54:32 -0800 Subject: [PATCH 1/3] Avoid using pthread_sigmask on pthreads not created by FreeRTOS --- portable/ThirdParty/GCC/Posix/port.c | 72 ++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index 1bec7afd88..946f73f2ce 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -109,6 +109,8 @@ static BaseType_t xSchedulerEnd = pdFALSE; static pthread_t hTimerTickThread; static bool xTimerTickThreadShouldRun; static uint64_t prvStartTimeNs; +static pthread_mutex_t xThreadMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t xThreadKey = 0; /*-----------------------------------------------------------*/ static void prvSetupSignalsAndSchedulerPolicy( void ); @@ -123,6 +125,44 @@ static void vPortStartFirstTask( void ); static void prvPortYieldFromISR( void ); /*-----------------------------------------------------------*/ +void prvThreadKeyDestructor( void * data ) +{ + free( data ); +} + +static void prvInitThreadKey() +{ + pthread_mutex_lock( &xThreadMutex ); + + if( xThreadKey == 0 ) + { + pthread_key_create( &xThreadKey, prvThreadKeyDestructor ); + } + + pthread_mutex_unlock( &xThreadMutex ); +} + +static void prvMarkAsFreeRTOSThread( pthread_t thread ) +{ + prvInitThreadKey(); + uint8_t * thread_data = malloc( 1 ); + *thread_data = 1; + pthread_setspecific( xThreadKey, thread_data ); +} + +static BaseType_t prvIsFreeRTOSThread( pthread_t thread ) +{ + uint8_t * thread_data = ( uint8_t * ) pthread_getspecific( xThreadKey ); + + return thread_data != NULL && *thread_data == 1; +} + +static void prvDestroyThreadKey() +{ + pthread_key_delete( xThreadKey ); +} +/*-----------------------------------------------------------*/ + static void prvFatalError( const char * pcCall, int iErrno ) __attribute__( ( __noreturn__ ) ); @@ -253,6 +293,8 @@ BaseType_t xPortStartScheduler( void ) /* Restore original signal mask. */ ( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); + prvDestroyThreadKey(); + return 0; } /*-----------------------------------------------------------*/ @@ -270,8 +312,12 @@ void vPortEndScheduler( void ) ( void ) pthread_kill( hMainThread, SIG_RESUME ); /* Waiting to be deleted here. */ - pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - event_wait( pxCurrentThread->ev ); + if( prvIsFreeRTOSThread( pthread_self() ) == pdTRUE ) + { + pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + event_wait( pxCurrentThread->ev ); + } + pthread_testcancel(); } /*-----------------------------------------------------------*/ @@ -326,13 +372,21 @@ void vPortYield( void ) void vPortDisableInterrupts( void ) { - pthread_sigmask( SIG_BLOCK, &xAllSignals, NULL ); + if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + { + return; + } + pthread_sigmask(SIG_BLOCK, &xAllSignals, NULL); } /*-----------------------------------------------------------*/ void vPortEnableInterrupts( void ) { - pthread_sigmask( SIG_UNBLOCK, &xAllSignals, NULL ); + if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + { + return; + } + pthread_sigmask(SIG_UNBLOCK, &xAllSignals, NULL); } /*-----------------------------------------------------------*/ @@ -368,6 +422,8 @@ static void * prvTimerTickHandler( void * arg ) { ( void ) arg; + prvMarkAsFreeRTOSThread( pthread_self() ); + prvPortSetCurrentThreadName("Scheduler timer"); while( xTimerTickThreadShouldRun ) @@ -400,6 +456,12 @@ void prvSetupTimerInterrupt( void ) static void vPortSystemTickHandler( int sig ) { + if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + { + fprintf( stderr, "vPortSystemTickHandler called from non-FreeRTOS thread\n" ); + return; + } + Thread_t * pxThreadToSuspend; Thread_t * pxThreadToResume; @@ -452,6 +514,8 @@ static void * prvWaitForStart( void * pvParams ) { Thread_t * pxThread = pvParams; + prvMarkAsFreeRTOSThread( pthread_self() ); + prvSuspendSelf( pxThread ); /* Resumed for the first time, unblocks all signals. */ From 8110c056298f7d38dbf7e65aac5fb7e498a1ffc4 Mon Sep 17 00:00:00 2001 From: John Boiles Date: Fri, 24 Jan 2025 16:32:57 -0800 Subject: [PATCH 2/3] PR feedback to eliminate early returns --- portable/ThirdParty/GCC/Posix/port.c | 43 +++++++++++++--------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index 0ebf86fb1c..a81227069f 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -368,21 +368,19 @@ void vPortYield( void ) void vPortDisableInterrupts( void ) { - if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + if( prvIsFreeRTOSThread( pthread_self() ) == pdTRUE ) { - return; + pthread_sigmask(SIG_BLOCK, &xAllSignals, NULL); } - pthread_sigmask(SIG_BLOCK, &xAllSignals, NULL); } /*-----------------------------------------------------------*/ void vPortEnableInterrupts( void ) { - if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + if( prvIsFreeRTOSThread( pthread_self() ) == pdTRUE ) { - return; + pthread_sigmask(SIG_UNBLOCK, &xAllSignals, NULL); } - pthread_sigmask(SIG_UNBLOCK, &xAllSignals, NULL); } /*-----------------------------------------------------------*/ @@ -452,32 +450,31 @@ void prvSetupTimerInterrupt( void ) static void vPortSystemTickHandler( int sig ) { - if( prvIsFreeRTOSThread( pthread_self() ) == pdFALSE ) + if( prvIsFreeRTOSThread( pthread_self() ) == pdTRUE ) { - fprintf( stderr, "vPortSystemTickHandler called from non-FreeRTOS thread\n" ); - return; - } + Thread_t * pxThreadToSuspend; + Thread_t * pxThreadToResume; - Thread_t * pxThreadToSuspend; - Thread_t * pxThreadToResume; + ( void ) sig; - ( void ) sig; + uxCriticalNesting++; /* Signals are blocked in this signal handler. */ - uxCriticalNesting++; /* Signals are blocked in this signal handler. */ + pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - pxThreadToSuspend = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + if( xTaskIncrementTick() != pdFALSE ) + { + /* Select Next Task. */ + vTaskSwitchContext(); - if( xTaskIncrementTick() != pdFALSE ) - { - /* Select Next Task. */ - vTaskSwitchContext(); + pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); - pxThreadToResume = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() ); + prvSwitchThread( pxThreadToResume, pxThreadToSuspend ); + } - prvSwitchThread( pxThreadToResume, pxThreadToSuspend ); + uxCriticalNesting--; + } else { + fprintf( stderr, "vPortSystemTickHandler called from non-FreeRTOS thread\n" ); } - - uxCriticalNesting--; } /*-----------------------------------------------------------*/ From 9b7810acc299645874387d3bad1a988519bcb520 Mon Sep 17 00:00:00 2001 From: John Boiles Date: Fri, 24 Jan 2025 16:43:08 -0800 Subject: [PATCH 3/3] Assert that thread_data != NULL --- portable/ThirdParty/GCC/Posix/port.c | 1 + 1 file changed, 1 insertion(+) diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index a81227069f..c4eacb2ba6 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -142,6 +142,7 @@ static void prvMarkAsFreeRTOSThread( pthread_t thread ) { prvInitThreadKey(); uint8_t * thread_data = malloc( 1 ); + configASSERT( thread_data != NULL ); *thread_data = 1; pthread_setspecific( xThreadKey, thread_data ); }