freertos: Add priority scheduling unit tests

This commit adds a priority scheduling unit test to test that the scheduler
always schedules the highest priority ready state task. Single core and SMP
variants of the test are both added.
This commit is contained in:
Darian Leung
2022-09-19 20:20:19 +08:00
parent 188c21319d
commit 882515fcef
2 changed files with 184 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "FreeRTOS.h"
#include "task.h"
#include "unity.h"
#include "portTestMacro.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/*
Test Priority Scheduling (Single Core)
Purpose:
- Test that the single-core scheduler always schedules the highest priority ready task
Procedure:
- Raise the unityTask priority to (configMAX_PRIORITIES - 1)
- unityTask creates the following lower priority tasks
- task_A (configMAX_PRIORITIES - 2)
- task_B (configMAX_PRIORITIES - 3)
- UnityTask blocks for a short period of time to allow task_A to run
- Clean up and restore unityTask's original priority
Expected:
- task_A should run after unityTask blocks
- task_B should never have run
*/
#if ( configNUM_CORES == 1 )
#define UNITY_TASK_DELAY_TICKS 10
static BaseType_t task_A_ran;
static BaseType_t task_B_ran;
static void task_A(void *arg)
{
task_A_ran = pdTRUE;
/* Keeping spinning to prevent the lower priority task_B from running */
while (1) {
;
}
}
static void task_B(void *arg)
{
/* The following should never run due to task_B having a lower priority */
task_B_ran = pdTRUE;
while (1) {
;
}
}
TEST_CASE("Tasks: Test priority scheduling", "[freertos]")
{
TaskHandle_t task_A_handle;
TaskHandle_t task_B_handle;
task_A_ran = pdFALSE;
task_B_ran = pdFALSE;
/* Raise the priority of the unityTask */
vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
/* Create task_A and task_B */
xTaskCreate(task_A, "task_A", configTEST_DEFAULT_STACK_SIZE, (void *)xTaskGetCurrentTaskHandle(), configMAX_PRIORITIES - 2, &task_A_handle);
xTaskCreate(task_B, "task_B", configTEST_DEFAULT_STACK_SIZE, (void *)xTaskGetCurrentTaskHandle(), configMAX_PRIORITIES - 3, &task_B_handle);
/* Block to allow task_A to be scheduled */
vTaskDelay(UNITY_TASK_DELAY_TICKS);
/* Test that only task_A has run */
TEST_ASSERT_EQUAL(pdTRUE, task_A_ran);
TEST_ASSERT_EQUAL(pdFALSE, task_B_ran);
vTaskDelete(task_A_handle);
vTaskDelete(task_B_handle);
/* Restore the priority of the unityTask */
vTaskPrioritySet(NULL, configTEST_UNITY_TASK_PRIORITY);
}
#endif /* configNUM_CORES == 1 */

View File

@@ -0,0 +1,102 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "unity.h"
#include "portTestMacro.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/*
Test Priority Scheduling SMP
Purpose:
- Test that the SMP scheduler always schedules the highest priority ready tasks for each core
Procedure:
- Raise the unityTask priority to (configMAX_PRIORITIES - 1)
- unityTask creates the following lower priority tasks for each core
- task_A (configMAX_PRIORITIES - 2) for each core
- task_B (configMAX_PRIORITIES - 3) for each core
- unityTask blocks for a short period of time to allow all of the task_As to run
- Clean up and restore unityTask's original priority
Expected:
- All of the task_As should be run by the scheduler
- None of the task_Bs should have run
*/
#if ( defined( CONFIG_FREERTOS_SMP ) && ( configNUM_CORES > 1 ) && ( configRUN_MULTIPLE_PRIORITIES == 1 ) ) \
|| ( !defined( CONFIG_FREERTOS_SMP ) && ( configNUM_CORES > 1 ) )
#define UNITY_TASK_DELAY_TICKS 10
static BaseType_t task_A_ran[configNUM_CORES];
static BaseType_t task_B_ran[configNUM_CORES];
static void task_A(void *arg)
{
BaseType_t task_idx = (BaseType_t) arg;
task_A_ran[task_idx] = pdTRUE;
/* Keeping spinning to prevent the lower priority task_B from running */
while (1) {
;
}
}
static void task_B(void *arg)
{
/* The following should never be run due to task_B having a lower priority */
BaseType_t task_idx = (BaseType_t) arg;
task_B_ran[task_idx] = pdTRUE;
while (1) {
;
}
}
TEST_CASE("Tasks: Test priority scheduling (SMP)", "[freertos]")
{
TaskHandle_t task_A_handles[configNUM_CORES];
TaskHandle_t task_B_handles[configNUM_CORES];
memset(task_A_ran, pdFALSE, sizeof(task_A_ran));
memset(task_B_ran, pdFALSE, sizeof(task_B_ran));
/* Raise the priority of the unityTask */
vTaskPrioritySet(NULL, configMAX_PRIORITIES - 1);
/* Create task_A for each core */
for (UBaseType_t x = 0; x < configNUM_CORES; x++) {
xTaskCreate(task_A, "task_A", configTEST_DEFAULT_STACK_SIZE, (void *)x, configMAX_PRIORITIES - 2, &task_A_handles[x]);
}
/* Create task_B for each core */
for (UBaseType_t x = 0; x < configNUM_CORES; x++) {
xTaskCreate(task_B, "task_B", configTEST_DEFAULT_STACK_SIZE, (void *)x, configMAX_PRIORITIES - 3, &task_B_handles[x]);
}
/* Block to ensure all the task_As to be scheduled */
vTaskDelay(UNITY_TASK_DELAY_TICKS);
/* Check that all the task_As have run, and none of the task_Bs have run */
for (UBaseType_t x = 0; x < configNUM_CORES; x++) {
TEST_ASSERT_EQUAL(pdTRUE, task_A_ran[x]);
TEST_ASSERT_EQUAL(pdFALSE, task_B_ran[x]);
}
/* Cleanup */
for (UBaseType_t x = 0; x < configNUM_CORES; x++) {
vTaskDelete(task_A_handles[x]);
vTaskDelete(task_B_handles[x]);
}
/* Restore the priority of the unityTask */
vTaskPrioritySet(NULL, configTEST_UNITY_TASK_PRIORITY);
}
#endif /* ( defined( CONFIG_FREERTOS_SMP ) && ( configNUM_CORES > 1 ) && ( configRUN_MULTIPLE_PRIORITIES == 1 ) )
|| ( !defined( CONFIG_FREERTOS_SMP ) && ( configNUM_CORES > 1 ) ) */