forked from epagris/FreeRTOS-Kernel
		
	POSIX port - Cancel and join all FreeRTOS managed pthreads upon shutdown
For a clean shutdown where memory is freed, it is necessary for all pthreads to be joined at shutdown. Previously there was explicit cancellation of the idle task and timer daemon task, however there may be a number of other tasks in the system, both system created and user created, and those tasks/threads were being left at shutdown. This change calls pthread_cancel()/pthread_join() on all FreeRTOS managed pthreads upon shutdown.
This commit is contained in:
		
							parent
							
								
									ddc89fa985
								
							
						
					
					
						commit
						88d3540b54
					
				
							
								
								
									
										41
									
								
								portable/ThirdParty/GCC/Posix/port.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								portable/ThirdParty/GCC/Posix/port.c
									
									
									
									
										vendored
									
									
								
							@ -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 );
 | 
			
		||||
 | 
			
		||||
    #if ( configUSE_TIMERS == 1 )
 | 
			
		||||
        /* Cancel the Timer task and free its resources */
 | 
			
		||||
        vPortCancelThread( xTimerGetTimerDaemonTaskHandle() );
 | 
			
		||||
    #endif /* configUSE_TIMERS */
 | 
			
		||||
        pthread_cancel( pxThread->pthread );
 | 
			
		||||
        event_signal( pxThread->ev );
 | 
			
		||||
 | 
			
		||||
        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 );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user