diff --git a/include/FreeRTOS.h b/include/FreeRTOS.h index 712d8cb52fe..f575863758c 100644 --- a/include/FreeRTOS.h +++ b/include/FreeRTOS.h @@ -2872,6 +2872,12 @@ #define configRUN_ADDITIONAL_TESTS 0 #endif +/* The following config allows infinite loop control. For example, control the + * infinite loop in idle task function when performing unit tests. */ +#ifndef configCONTROL_INFINITE_LOOP + #define configCONTROL_INFINITE_LOOP() +#endif + /* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using * dynamically allocated RAM, in which case when any task is deleted it is known * that both the task's stack and TCB need to be freed. Sometimes the diff --git a/tasks.c b/tasks.c index bea306ea512..48c1960aa7d 100644 --- a/tasks.c +++ b/tasks.c @@ -317,12 +317,6 @@ #define portDECREMENT_CRITICAL_NESTING_COUNT() ( pxCurrentTCBs[ portGET_CORE_ID() ]->uxCriticalNesting-- ) #endif /* #if ( ( configNUMBER_OF_CORES > 1 ) && ( portCRITICAL_NESTING_IN_TCB == 1 ) ) */ -/* Code below here allows infinite loop controlling, especially for the infinite loop - * in idle task function (for example when performing unit tests). */ -#ifndef INFINITE_LOOP - #define INFINITE_LOOP() 1 -#endif - #define taskBITS_PER_BYTE ( ( size_t ) 8 ) #if ( configNUMBER_OF_CORES > 1 ) @@ -1134,16 +1128,31 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION; if( ( uxCoreMap & ( ( UBaseType_t ) 1U << ( UBaseType_t ) xCoreID ) ) != 0U ) { - /* The ready task that was removed from this core is not excluded from it. - * Only look at the intersection of the cores the removed task is allowed to run - * on with the cores that the new task is excluded from. It is possible that the - * new task was only placed onto this core because it is excluded from another. - * Check to see if the previous task could run on one of those cores. */ + /* pxPreviousTCB was removed from this core and this core is not excluded + * from it's core affinity mask. + * + * pxPreviousTCB is preempted by the new higher priority task + * pxCurrentTCBs[ xCoreID ]. When searching a new core for pxPreviousTCB, + * we do not need to look at the cores on which pxCurrentTCBs[ xCoreID ] + * is allowed to run. The reason is - when more than one cores are + * eligible for an incoming task, we preempt the core with the minimum + * priority task. Because this core (i.e. xCoreID) was preempted for + * pxCurrentTCBs[ xCoreID ], this means that all the others cores + * where pxCurrentTCBs[ xCoreID ] can run, are running tasks with priority + * no lower than pxPreviousTCB's priority. Therefore, the only cores where + * which can be preempted for pxPreviousTCB are the ones where + * pxCurrentTCBs[ xCoreID ] is not allowed to run (and obviously, + * pxPreviousTCB is allowed to run). + * + * This is an optimization which reduces the number of cores needed to be + * searched for pxPreviousTCB to run. */ uxCoreMap &= ~( pxCurrentTCBs[ xCoreID ]->uxCoreAffinityMask ); } else { - /* The ready task that was removed from this core is excluded from it. */ + /* pxPreviousTCB's core affinity mask is changed and it is no longer + * allowed to run on this core. Searching all the cores in pxPreviousTCB's + * new core affinity mask to find a core on which it can run. */ } uxCoreMap &= ( ( 1U << configNUMBER_OF_CORES ) - 1U ); @@ -5359,7 +5368,7 @@ void vTaskMissedYield( void ) taskYIELD(); - for( ; INFINITE_LOOP(); ) + for( ; configCONTROL_INFINITE_LOOP(); ) { #if ( configUSE_PREEMPTION == 0 ) { @@ -5444,7 +5453,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } #endif /* #if ( configNUMBER_OF_CORES > 1 ) */ - for( ; INFINITE_LOOP(); ) + for( ; configCONTROL_INFINITE_LOOP(); ) { /* See if any tasks have deleted themselves - if so then the idle task * is responsible for freeing the deleted task's TCB and stack. */ diff --git a/timers.c b/timers.c index f27caba3f46..e2f3f98091f 100644 --- a/timers.c +++ b/timers.c @@ -709,7 +709,7 @@ } #endif /* configUSE_DAEMON_TASK_STARTUP_HOOK */ - for( ; ; ) + for( ; configCONTROL_INFINITE_LOOP(); ) { /* Query the timers list to see if it contains any timers, and if so, * obtain the time at which the next timer will expire. */