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