mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-20 10:46:02 -04:00
Merge branch 'bugfix/tw9313_dual_core_issue' into 'master'
freertos: fix dual core issue This commit try to fix dual issue tw9313 raised by QA 1. Put per-core data into critical session or interrupt disabled/enabled session 2. Idle task may have problem when it terminate the task in both core See merge request !333
This commit is contained in:
commit
6d0fd80af4
@ -3,7 +3,7 @@ menu "FreeRTOS"
|
||||
# This is actually also handled in the ESP32 startup code, not only in FreeRTOS.
|
||||
config FREERTOS_UNICORE
|
||||
bool "Run FreeRTOS only on first core"
|
||||
default y
|
||||
default n
|
||||
help
|
||||
This version of FreeRTOS normally takes control of all cores of
|
||||
the CPU. Select this if you only want to start it on the first core.
|
||||
@ -195,8 +195,6 @@ config FREERTOS_PORTMUX_DEBUG_RECURSIVE
|
||||
If enabled, additional debug information will be printed for recursive
|
||||
portMUX usage.
|
||||
|
||||
|
||||
|
||||
endif # FREERTOS_DEBUG_INTERNALS
|
||||
|
||||
endmenu
|
||||
|
@ -213,7 +213,6 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux);
|
||||
#define portEXIT_CRITICAL_ISR(mux) vPortCPUReleaseMutex(mux)
|
||||
#endif
|
||||
|
||||
|
||||
// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack.
|
||||
// They can be called from interrupts too.
|
||||
//NOT SMP-COMPATIBLE! Use only if all you want is to disable the interrupts locally!
|
||||
|
@ -369,7 +369,7 @@ PRIVILEGED_DATA static portMUX_TYPE xTickCountMutex = portMUX_INITIALIZER_UNLOCK
|
||||
\
|
||||
/* listGET_OWNER_OF_NEXT_ENTRY indexes through the list, so the tasks of \
|
||||
the same priority get an equal share of the processor time. */ \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ xPortGetCoreID() ], &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( xTaskGetCurrentTaskHandle(), &( pxReadyTasksLists[ uxTopReadyPriority ] ) ); \
|
||||
} /* taskSELECT_HIGHEST_PRIORITY_TASK */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
@ -398,7 +398,7 @@ PRIVILEGED_DATA static portMUX_TYPE xTickCountMutex = portMUX_INITIALIZER_UNLOCK
|
||||
/* Find the highest priority queue that contains ready tasks. */ \
|
||||
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \
|
||||
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[ xPortGetCoreID() ], &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||
listGET_OWNER_OF_NEXT_ENTRY( xTaskGetCurrentTaskHandle(), &( pxReadyTasksLists[ uxTopPriority ] ) ); \
|
||||
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
@ -456,7 +456,7 @@ count overflows. */
|
||||
* see if the parameter is NULL and returns a pointer to the appropriate TCB.
|
||||
*/
|
||||
/* ToDo: See if this still works for multicore. */
|
||||
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ] : ( TCB_t * ) ( pxHandle ) )
|
||||
#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( TCB_t * ) xTaskGetCurrentTaskHandle() : ( TCB_t * ) ( pxHandle ) )
|
||||
|
||||
/* The item value of the event list item is normally used to hold the priority
|
||||
of the task to which it belongs (coded to allow it to be held in reverse
|
||||
@ -631,9 +631,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
*/
|
||||
void taskYIELD_OTHER_CORE( BaseType_t xCoreID, UBaseType_t uxPriority )
|
||||
{
|
||||
TCB_t *curTCB = xTaskGetCurrentTaskHandle();
|
||||
BaseType_t i;
|
||||
|
||||
if (xCoreID != tskNO_AFFINITY) {
|
||||
if ( pxCurrentTCB[ xCoreID ]->uxPriority < uxPriority ) {
|
||||
if ( curTCB->uxPriority < uxPriority ) {
|
||||
vPortYieldOtherCore( xCoreID );
|
||||
}
|
||||
}
|
||||
@ -1039,6 +1041,7 @@ UBaseType_t x;
|
||||
|
||||
static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode, const BaseType_t xCoreID )
|
||||
{
|
||||
TCB_t *curTCB;
|
||||
BaseType_t i;
|
||||
|
||||
/* Ensure interrupts don't access the task lists while the lists are being
|
||||
@ -1111,23 +1114,25 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
|
||||
portSETUP_TCB( pxNewTCB );
|
||||
}
|
||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
/* Scheduler is running. If the created task is of a higher priority than an executing task
|
||||
then it should run now.
|
||||
ToDo: This only works for the current core. If a task is scheduled on an other processor,
|
||||
the other processor will keep running the task it's working on, and only switch to the newer
|
||||
task on a timer interrupt. */
|
||||
//No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
|
||||
if( pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority )
|
||||
if( curTCB->uxPriority < pxNewTCB->uxPriority )
|
||||
{
|
||||
/* Scheduler is running. If the created task is of a higher priority than an executing task
|
||||
then it should run now.
|
||||
No mux here, uxPriority is mostly atomic and there's not really any harm if this check misfires.
|
||||
*/
|
||||
if( tskCAN_RUN_HERE( xCoreID ) && pxCurrentTCB[ xPortGetCoreID() ]->uxPriority < pxNewTCB->uxPriority )
|
||||
if( tskCAN_RUN_HERE( xCoreID ) && curTCB->uxPriority < pxNewTCB->uxPriority )
|
||||
{
|
||||
taskYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
@ -1143,6 +1148,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1409,11 +1415,12 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
eTaskState eReturn;
|
||||
List_t *pxStateList;
|
||||
const TCB_t * const pxTCB = ( TCB_t * ) xTask;
|
||||
TCB_t * curTCB = xTaskGetCurrentTaskHandle();
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
configASSERT( pxTCB );
|
||||
|
||||
if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] )
|
||||
if( pxTCB == curTCB )
|
||||
{
|
||||
/* The task calling this function is querying its own state. */
|
||||
eReturn = eRunning;
|
||||
@ -1691,6 +1698,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
void vTaskSuspend( TaskHandle_t xTaskToSuspend )
|
||||
{
|
||||
TCB_t *pxTCB;
|
||||
TCB_t *curTCB;
|
||||
|
||||
UNTESTED_FUNCTION();
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
@ -1723,10 +1731,11 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode
|
||||
}
|
||||
|
||||
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xGenericListItem ) );
|
||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
}
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
if( pxTCB == pxCurrentTCB[ xPortGetCoreID() ] )
|
||||
if( pxTCB == curTCB )
|
||||
{
|
||||
if( xSchedulerRunning != pdFALSE )
|
||||
{
|
||||
@ -2034,7 +2043,7 @@ void vTaskEndScheduler( void )
|
||||
//Return global reent struct if FreeRTOS isn't running,
|
||||
struct _reent* __getreent() {
|
||||
//No lock needed because if this changes, we won't be running anymore.
|
||||
TCB_t *currTask=pxCurrentTCB[ xPortGetCoreID() ];
|
||||
TCB_t *currTask=xTaskGetCurrentTaskHandle();
|
||||
if (currTask==NULL) {
|
||||
//No task running. Return global struct.
|
||||
return _GLOBAL_REENT;
|
||||
@ -2052,7 +2061,11 @@ void vTaskSuspendAll( void )
|
||||
BaseType_t. Please read Richard Barry's reply in the following link to a
|
||||
post in the FreeRTOS support forum before reporting this as a bug! -
|
||||
http://goo.gl/wu4acr */
|
||||
unsigned state;
|
||||
|
||||
state = portENTER_CRITICAL_NESTED();
|
||||
++uxSchedulerSuspended[ xPortGetCoreID() ];
|
||||
portEXIT_CRITICAL_NESTED(state);
|
||||
}
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
@ -2595,7 +2608,7 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
/* If xTask is NULL then we are setting our own task hook. */
|
||||
if( xTask == NULL )
|
||||
{
|
||||
xTCB = ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ];
|
||||
xTCB = ( TCB_t * ) xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2626,7 +2639,7 @@ BaseType_t xSwitchRequired = pdFALSE;
|
||||
/* If xTask is NULL then we are calling our own task hook. */
|
||||
if( xTask == NULL )
|
||||
{
|
||||
xTCB = ( TCB_t * ) pxCurrentTCB[ xPortGetCoreID() ];
|
||||
xTCB = ( TCB_t * ) xTaskGetCurrentTaskHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3387,8 +3400,8 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
||||
|
||||
if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
|
||||
{
|
||||
pxTCB = prvGetTCBFromHandle( xTaskToSet );
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
pxTCB = prvGetTCBFromHandle( xTaskToSet );
|
||||
pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
|
||||
pxTCB->pvThreadLocalStoragePointersDelCallback[ xIndex ] = xDelCallback;
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
@ -3408,8 +3421,10 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
|
||||
|
||||
if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
|
||||
{
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
pxTCB = prvGetTCBFromHandle( xTaskToSet );
|
||||
pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
}
|
||||
}
|
||||
#endif /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS */
|
||||
@ -3496,26 +3511,23 @@ static void prvCheckTasksWaitingTermination( void )
|
||||
|
||||
/* ucTasksDeleted is used to prevent vTaskSuspendAll() being called
|
||||
too often in the idle task. */
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
while( uxTasksDeleted > ( UBaseType_t ) 0U )
|
||||
{
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
{
|
||||
xListIsEmpty = listLIST_IS_EMPTY( &xTasksWaitingTermination );
|
||||
}
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
if( xListIsEmpty == pdFALSE )
|
||||
{
|
||||
TCB_t *pxTCB;
|
||||
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
{
|
||||
pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xTasksWaitingTermination ) );
|
||||
( void ) uxListRemove( &( pxTCB->xGenericListItem ) );
|
||||
--uxCurrentNumberOfTasks;
|
||||
--uxTasksDeleted;
|
||||
}
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) && ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS )
|
||||
{
|
||||
@ -3536,6 +3548,7 @@ static void prvCheckTasksWaitingTermination( void )
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
}
|
||||
#endif /* vTaskDelete */
|
||||
}
|
||||
@ -3805,11 +3818,11 @@ TCB_t *pxTCB;
|
||||
TaskHandle_t xTaskGetCurrentTaskHandle( void )
|
||||
{
|
||||
TaskHandle_t xReturn;
|
||||
unsigned state;
|
||||
|
||||
/* A critical section is not required as this is not called from
|
||||
an interrupt and the current TCB will always be the same for any
|
||||
individual execution thread. */
|
||||
state = portENTER_CRITICAL_NESTED();
|
||||
xReturn = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
portEXIT_CRITICAL_NESTED(state);
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
@ -3835,7 +3848,9 @@ TCB_t *pxTCB;
|
||||
BaseType_t xTaskGetSchedulerState( void )
|
||||
{
|
||||
BaseType_t xReturn;
|
||||
unsigned state;
|
||||
|
||||
state = portENTER_CRITICAL_NESTED();
|
||||
if( xSchedulerRunning == pdFALSE )
|
||||
{
|
||||
xReturn = taskSCHEDULER_NOT_STARTED;
|
||||
@ -3851,6 +3866,7 @@ TCB_t *pxTCB;
|
||||
xReturn = taskSCHEDULER_SUSPENDED;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL_NESTED(state);
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
@ -4386,6 +4402,8 @@ TickType_t uxReturn;
|
||||
|
||||
void *pvTaskIncrementMutexHeldCount( void )
|
||||
{
|
||||
TCB_t *curTCB;
|
||||
|
||||
/* If xSemaphoreCreateMutex() is called before any tasks have been created
|
||||
then pxCurrentTCB will be NULL. */
|
||||
taskENTER_CRITICAL(&xTaskQueueMutex);
|
||||
@ -4393,9 +4411,10 @@ TickType_t uxReturn;
|
||||
{
|
||||
( pxCurrentTCB[ xPortGetCoreID() ]->uxMutexesHeld )++;
|
||||
}
|
||||
curTCB = pxCurrentTCB[ xPortGetCoreID() ];
|
||||
taskEXIT_CRITICAL(&xTaskQueueMutex);
|
||||
|
||||
return pxCurrentTCB[ xPortGetCoreID() ];
|
||||
return curTCB;
|
||||
}
|
||||
|
||||
#endif /* configUSE_MUTEXES */
|
||||
|
Loading…
Reference in New Issue
Block a user