Skip to content

Commit a72ce35

Browse files
committed
Merge branch 'fix/priority_inv_when_remove_from_unordered_event_list_v5.3' into 'release/v5.3'
fix(freertos): Fixed priority inversion when setting event group bits (v5.3) See merge request espressif/esp-idf!34123
2 parents 5eb7462 + 17921b7 commit a72ce35

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

components/freertos/FreeRTOS-Kernel/tasks.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -4123,10 +4123,19 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
41234123
if( taskIS_YIELD_REQUIRED( pxUnblockedTCB, pdFALSE ) == pdTRUE )
41244124
{
41254125
/* The unblocked task has a priority above that of the calling task, so
4126-
* a context switch is required. This function is called with the
4127-
* scheduler suspended so xYieldPending is set so the context switch
4128-
* occurs immediately that the scheduler is resumed (unsuspended). */
4129-
xYieldPending[ xCurCoreID ] = pdTRUE;
4126+
* a context switch is required. */
4127+
#if ( configNUM_CORES > 1 )
4128+
4129+
/* In SMP mode, this function is called from a critical section, so we
4130+
* yield the current core to schedule the unblocked task. */
4131+
portYIELD_WITHIN_API();
4132+
#else /* configNUM_CORES > 1 */
4133+
4134+
/* In single-core mode, this function is called with the scheduler suspended
4135+
* so xYieldPending is set so the context switch occurs immediately once the
4136+
* scheduler is resumed (unsuspended). */
4137+
xYieldPending[ xCurCoreID ] = pdTRUE;
4138+
#endif /* configNUM_CORES > 1 */
41304139
}
41314140
}
41324141
}

components/freertos/test_apps/freertos/kernel/event_groups/test_freertos_eventgroups.c

+51
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,57 @@ TEST_CASE("FreeRTOS Event Group Sync", "[freertos]")
132132
vEventGroupDelete(eg);
133133
}
134134

135+
static TaskHandle_t run_order[2];
136+
static uint32_t run_order_index = 0;
137+
138+
void task_test_eg_prio(void *arg)
139+
{
140+
TaskHandle_t main_task_hdl = (TaskHandle_t)arg;
141+
142+
/* Notify the main task that this task has been created */
143+
xTaskNotifyGive(main_task_hdl);
144+
145+
/* Wait for the event group bits to be set */
146+
TEST_ASSERT_EQUAL(1, xEventGroupWaitBits(eg, 1, pdTRUE, pdTRUE, portMAX_DELAY));
147+
148+
/* Record the task handle in the run order array */
149+
run_order[run_order_index++] = xTaskGetCurrentTaskHandle();
150+
151+
/* Suspend the task */
152+
vTaskSuspend(NULL);
153+
}
154+
155+
TEST_CASE("FreeRTOS Event Groups do not cause priority inversion when higher priority task is unblocked", "[freertos]")
156+
{
157+
run_order[0] = NULL;
158+
run_order[1] = NULL;
159+
run_order_index = 0;
160+
161+
/* Initialize the event group */
162+
eg = xEventGroupCreate();
163+
164+
/* Create a task with higher priority than the task that will set the event group bits */
165+
TaskHandle_t higher_prio_hdl;
166+
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(task_test_eg_prio, "task_test_eg_prio", 2048, (void *)xTaskGetCurrentTaskHandle(), CONFIG_UNITY_FREERTOS_PRIORITY + 1, &higher_prio_hdl, CONFIG_UNITY_FREERTOS_CPU));
167+
168+
/* Wait for the task to be created */
169+
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
170+
171+
/* Set the event group bits */
172+
xEventGroupSetBits(eg, 1);
173+
174+
/* Record the task handle in the run order array */
175+
run_order[run_order_index++] = xTaskGetCurrentTaskHandle();
176+
177+
/* Verify that the higher priority task was unblocked and immediately scheduled and the lower priority task was preempted */
178+
TEST_ASSERT_EQUAL(higher_prio_hdl, run_order[0]);
179+
TEST_ASSERT_EQUAL(xTaskGetCurrentTaskHandle(), run_order[1]);
180+
181+
/* Clean up */
182+
vEventGroupDelete(eg);
183+
vTaskDelete(higher_prio_hdl);
184+
}
185+
135186
/*-----------------Test case for event group trace facilities-----------------*/
136187
#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
137188
/*

0 commit comments

Comments
 (0)