mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
freertos: When scheduler is disabled, tasks on other core should immediately resume
... if triggered by a SemaphoreGive/etc. Previously they would resume after scheduler was resumed, on next RTOS tick of other CPU.
This commit is contained in:
parent
f2f9170abc
commit
3e62c2e052
@ -3038,6 +3038,8 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
|
||||
{
|
||||
TCB_t *pxUnblockedTCB;
|
||||
BaseType_t xReturn;
|
||||
BaseType_t xTaskCanBeReady;
|
||||
UBaseType_t i;
|
||||
|
||||
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
|
||||
called from a critical section within an ISR. */
|
||||
@ -3061,7 +3063,21 @@ BaseType_t xReturn;
|
||||
return pdFALSE;
|
||||
}
|
||||
|
||||
if( uxSchedulerSuspended[ xPortGetCoreID() ] == ( UBaseType_t ) pdFALSE )
|
||||
/* Determine if the task can possibly be run on either CPU now, either because the scheduler
|
||||
the task is pinned to is running or because a scheduler is running on any CPU. */
|
||||
xTaskCanBeReady = pdFALSE;
|
||||
if ( pxUnblockedTCB->xCoreID == tskNO_AFFINITY ) {
|
||||
for (i = 0; i < portNUM_PROCESSORS; i++) {
|
||||
if ( uxSchedulerSuspended[ i ] == ( UBaseType_t ) pdFALSE ) {
|
||||
xTaskCanBeReady = pdTRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
xTaskCanBeReady = uxSchedulerSuspended[ pxUnblockedTCB->xCoreID ] == ( UBaseType_t ) pdFALSE;
|
||||
}
|
||||
|
||||
if( xTaskCanBeReady )
|
||||
{
|
||||
( void ) uxListRemove( &( pxUnblockedTCB->xGenericListItem ) );
|
||||
prvAddTaskToReadyList( pxUnblockedTCB );
|
||||
@ -3069,7 +3085,7 @@ BaseType_t xReturn;
|
||||
else
|
||||
{
|
||||
/* The delayed and ready lists cannot be accessed, so hold this task
|
||||
pending until the scheduler is resumed. */
|
||||
pending until the scheduler is resumed on this CPU. */
|
||||
vListInsertEnd( &( xPendingReadyList[ xPortGetCoreID() ] ), &( pxUnblockedTCB->xEventListItem ) );
|
||||
}
|
||||
|
||||
|
@ -154,9 +154,8 @@ TEST_CASE("Handle waking multiple tasks while scheduler suspended", "[freertos]"
|
||||
/* Suspend scheduler on this CPU */
|
||||
vTaskSuspendAll();
|
||||
|
||||
/* Give all the semaphores once. You might expect this will wake up tasks on the other
|
||||
CPU (where the scheduler is not suspended) but it doesn't do this in the current implementation
|
||||
- all tasks are added to xPendingReadyList and woken up later. See note in the freertos-smp docs.
|
||||
/* Give all the semaphores once. This will wake tasks immediately on the other
|
||||
CPU, but they are deferred here until the scheduler resumes.
|
||||
*/
|
||||
for (int p = 0; p < portNUM_PROCESSORS; p++) {
|
||||
for (int t = 0; t < TASKS_PER_PROC; t++) {
|
||||
@ -164,21 +163,19 @@ TEST_CASE("Handle waking multiple tasks while scheduler suspended", "[freertos]"
|
||||
}
|
||||
}
|
||||
|
||||
ets_delay_us(2 * 1000); /* Can't vTaskDelay() while scheduler is suspended, but let other CPU do some things */
|
||||
ets_delay_us(1000); /* Let the other CPU do some things */
|
||||
|
||||
for (int p = 0; p < portNUM_PROCESSORS; p++) {
|
||||
for (int t = 0; t < TASKS_PER_PROC; t++) {
|
||||
/* You might expect that this is '1' for the other CPU, but it's not (see comment above) */
|
||||
ets_printf("Checking CPU %d task %d (expected 0 actual %d)\n", p, t, counters[p][t].counter);
|
||||
TEST_ASSERT_EQUAL(0, counters[p][t].counter);
|
||||
int expected = (p == UNITY_FREERTOS_CPU) ? 0 : 1; // Has run if it was on the other CPU
|
||||
ets_printf("Checking CPU %d task %d (expected %d actual %d)\n", p, t, expected, counters[p][t].counter);
|
||||
TEST_ASSERT_EQUAL(expected, counters[p][t].counter);
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume scheduler */
|
||||
xTaskResumeAll();
|
||||
|
||||
vTaskDelay(TASKS_PER_PROC * 2);
|
||||
|
||||
/* Now the tasks on both CPUs should have been woken once and counted once. */
|
||||
for (int p = 0; p < portNUM_PROCESSORS; p++) {
|
||||
for (int t = 0; t < TASKS_PER_PROC; t++) {
|
||||
|
@ -227,11 +227,6 @@ protection against simultaneous access. Consider using critical sections
|
||||
(disables interrupts) or semaphores (does not disable interrupts) instead when
|
||||
protecting shared resources in ESP-IDF FreeRTOS.
|
||||
|
||||
If the task running on the CPU with scheduler suspended calls a function (like
|
||||
``xSemaphoreGive``, ``xQueueSend``) that wakes another task, this task will not run
|
||||
until after ``vTaskResumeAll()`` is called. This is true even if the woken task is
|
||||
on the other CPU (where the scheduler is still running).
|
||||
|
||||
In general, it's better to use other RTOS primitives like mutex semaphores to protect
|
||||
against data shared between tasks, rather than ``vTaskSuspendAll()``.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user