diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index d312aa48d..c5864f823 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -69,6 +69,7 @@ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" +#include "list.h" #include "timers.h" #include "utils/wait_for_event.h" /*-----------------------------------------------------------*/ @@ -82,6 +83,7 @@ typedef struct THREAD void * pvParams; BaseType_t xDying; struct event * ev; + ListItem_t xThreadListItem; } Thread_t; /* @@ -102,6 +104,7 @@ static sigset_t xAllSignals; static sigset_t xSchedulerOriginalSignalMask; static pthread_t hMainThread = ( pthread_t ) NULL; static volatile BaseType_t uxCriticalNesting; +static List_t xThreadList; /*-----------------------------------------------------------*/ static pthread_t hTimerTickThread; @@ -178,6 +181,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, thread->ev = event_create(); + /* Add the new thread in xThreadList. */ + vListInitialiseItem( &thread->xThreadListItem ); + listSET_LIST_ITEM_OWNER( &thread->xThreadListItem, thread ); + vListInsertEnd( &xThreadList, &thread->xThreadListItem ); + vPortEnterCritical(); iRet = pthread_create( &thread->pthread, &xThreadAttributes, @@ -210,6 +218,8 @@ BaseType_t xPortStartScheduler( void ) { int iSignal; sigset_t xSignals; + ListItem_t * pxIterator; + const ListItem_t * pxEndMarker; hMainThread = pthread_self(); @@ -239,15 +249,23 @@ BaseType_t xPortStartScheduler( void ) xTimerTickThreadShouldRun = false; pthread_join( hTimerTickThread, NULL ); - /* Cancel the Idle task and free its resources */ - #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) - vPortCancelThread( xTaskGetIdleTaskHandle() ); - #endif + /* + * cancel and join any remaining pthreads + * to ensure their resources are freed + * + * https://stackoverflow.com/a/5612424 + */ + pxEndMarker = listGET_END_MARKER( &xThreadList ); + for( pxIterator = listGET_HEAD_ENTRY( &xThreadList ); pxIterator != pxEndMarker; pxIterator = listGET_NEXT( pxIterator ) ) + { + Thread_t *pxThread = ( Thread_t * ) listGET_LIST_ITEM_OWNER( pxIterator ); + + pthread_cancel( pxThread->pthread ); + event_signal( pxThread->ev ); - #if ( configUSE_TIMERS == 1 ) - /* Cancel the Timer task and free its resources */ - vPortCancelThread( xTimerGetTimerDaemonTaskHandle() ); - #endif /* configUSE_TIMERS */ + pthread_join( pxThread->pthread, NULL ); + event_delete( pxThread->ev ); + } /* Restore original signal mask. */ ( void ) pthread_sigmask( SIG_SETMASK, &xSchedulerOriginalSignalMask, NULL ); @@ -444,10 +462,14 @@ void vPortCancelThread( void * pxTaskToDelete ) { Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete ); + /* Remove the thread from xThreadList. */ + uxListRemove( &pxThreadToCancel->xThreadListItem ); + /* * The thread has already been suspended so it can be safely cancelled. */ pthread_cancel( pxThreadToCancel->pthread ); + event_signal( pxThreadToCancel->ev ); pthread_join( pxThreadToCancel->pthread, NULL ); event_delete( pxThreadToCancel->ev ); } @@ -543,6 +565,9 @@ static void prvSetupSignalsAndSchedulerPolicy( void ) hMainThread = pthread_self(); + /* Setup thread list to record all the task which are not deleted. */ + vListInitialise( &xThreadList ); + /* Initialise common signal masks. */ sigfillset( &xAllSignals );