Delete kernel created task in vTaskEndScheduler (#962)

* Update vTaskDelete() to delete a task directly when scheduler is stopped instead of putting it on the xTasksWaitingTermination list.
* Delete the idle tasks and timer task in vTaskEndScheduler().
* Reclaim resources for all the tasks on the xTasksWaitingTermination list in vTaskEndScheduler().
* Update POSIX to no longer delete FreeRTOS tasks in the port.

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
pull/976/head^2
chinglee-iot 1 year ago committed by GitHub
parent ba1e2dad3c
commit 1de764ba87
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -74,7 +74,6 @@
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "list.h"
#include "timers.h"
#include "utils/wait_for_event.h"
/*-----------------------------------------------------------*/
@ -88,7 +87,6 @@ typedef struct THREAD
void * pvParams;
BaseType_t xDying;
struct event * ev;
ListItem_t xThreadListItem;
} Thread_t;
/*
@ -113,7 +111,6 @@ static BaseType_t xSchedulerEnd = pdFALSE;
static pthread_t hTimerTickThread;
static bool xTimerTickThreadShouldRun;
static uint64_t prvStartTimeNs;
static List_t xThreadList;
/*-----------------------------------------------------------*/
static void prvSetupSignalsAndSchedulerPolicy( void );
@ -197,14 +194,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
thread->ev = event_create();
vListInitialiseItem( &thread->xThreadListItem );
listSET_LIST_ITEM_OWNER( &thread->xThreadListItem, thread );
vPortEnterCritical();
/* Add the new thread in xThreadList. */
vListInsertEnd( &xThreadList, &thread->xThreadListItem );
iRet = pthread_create( &thread->pthread, &xThreadAttributes,
prvWaitForStart, thread );
@ -235,8 +226,6 @@ BaseType_t xPortStartScheduler( void )
{
int iSignal;
sigset_t xSignals;
ListItem_t * pxIterator;
const ListItem_t * pxEndMarker;
hMainThread = pthread_self();
prvPortSetCurrentThreadName("Scheduler");
@ -263,19 +252,6 @@ BaseType_t xPortStartScheduler( void )
sigwait( &xSignals, &iSignal );
}
/* Cancel all the running thread. */
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 );
pthread_join( pxThread->pthread, NULL );
event_delete( pxThread->ev );
}
/*
* clear out the variable that is used to end the scheduler, otherwise
* subsequent scheduler restarts will end immediately.
@ -300,6 +276,8 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
Thread_t * pxCurrentThread;
/* Stop the timer tick thread. */
xTimerTickThreadShouldRun = false;
pthread_join( hTimerTickThread, NULL );
@ -308,7 +286,10 @@ void vPortEndScheduler( void )
xSchedulerEnd = pdTRUE;
( void ) pthread_kill( hMainThread, SIG_RESUME );
pthread_exit( NULL );
/* Waiting to be deleted here. */
pxCurrentThread = prvGetThreadFromTask( xTaskGetCurrentTaskHandle() );
event_wait( pxCurrentThread->ev );
pthread_testcancel();
}
/*-----------------------------------------------------------*/
@ -491,11 +472,6 @@ void vPortCancelThread( void * pxTaskToDelete )
{
Thread_t * pxThreadToCancel = prvGetThreadFromTask( pxTaskToDelete );
/* Remove the thread from xThreadList. */
vPortEnterCritical();
uxListRemove( &pxThreadToCancel->xThreadListItem );
vPortExitCritical();
/*
* The thread has already been suspended so it can be safely cancelled.
*/
@ -600,9 +576,6 @@ 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 );

@ -2229,7 +2229,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
/* If the task is running (or yielding), we must add it to the
* termination list so that an idle task can delete it when it is
* no longer running. */
if( taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) != pdFALSE )
if( ( xSchedulerRunning != pdFALSE ) && ( taskTASK_IS_RUNNING_OR_SCHEDULED_TO_YIELD( pxTCB ) != pdFALSE ) )
{
/* A running task or a task which is scheduled to yield is being
* deleted. This cannot complete when the task is still running
@ -3740,11 +3740,39 @@ void vTaskEndScheduler( void )
{
traceENTER_vTaskEndScheduler();
#if ( INCLUDE_vTaskDelete == 1 )
{
BaseType_t xCoreID;
#if ( configUSE_TIMERS == 1 )
{
/* Delete the timer task created by the kernel. */
vTaskDelete( xTimerGetTimerDaemonTaskHandle() );
}
#endif /* #if ( configUSE_TIMERS == 1 ) */
/* Delete Idle tasks created by the kernel.*/
for( xCoreID = 0; xCoreID < ( BaseType_t ) configNUMBER_OF_CORES; xCoreID++ )
{
vTaskDelete( xIdleTaskHandles[ xCoreID ] );
}
/* Idle task is responsible for reclaiming the resources of the tasks in
* xTasksWaitingTermination list. Since the idle task is now deleted and
* no longer going to run, we need to reclaim resources of all the tasks
* in the xTasksWaitingTermination list. */
prvCheckTasksWaitingTermination();
}
#endif /* #if ( INCLUDE_vTaskDelete == 1 ) */
/* Stop the scheduler interrupts and call the portable scheduler end
* routine so the original ISRs can be restored if necessary. The port
* layer must ensure interrupts enable bit is left in the correct state. */
portDISABLE_INTERRUPTS();
xSchedulerRunning = pdFALSE;
/* This function must be called from a task and the application is
* responsible for deleting that task after the scheduler is stopped. */
vPortEndScheduler();
traceRETURN_vTaskEndScheduler();

Loading…
Cancel
Save