From 3878dd96579fa3431caf0db512f9334daa350610 Mon Sep 17 00:00:00 2001 From: chinglee-iot <61685396+chinglee-iot@users.noreply.github.com> Date: Thu, 8 Feb 2024 00:59:39 +0800 Subject: [PATCH] Add SMP one task enter suspendall on target test (#1183) * Add SMP one task enter suspendall on target test * Fix format and spelling * Code review suggestions Signed-off-by: Gaurav Aggarwal --------- Signed-off-by: Gaurav Aggarwal Co-authored-by: Gaurav Aggarwal Co-authored-by: Rahul Kar <118818625+kar-rahul-aws@users.noreply.github.com> --- .../CMakeLists.txt | 33 +++ ...ly_one_task_enter_suspendall_test_runner.c | 73 +++++ .../only_one_task_enter_suspendall.c | 250 ++++++++++++++++++ .../test_config.h | 59 +++++ 4 files changed, 415 insertions(+) create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/CMakeLists.txt create mode 100644 FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall_test_runner.c create mode 100644 FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall.c create mode 100644 FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/test_config.h diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/CMakeLists.txt b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/CMakeLists.txt new file mode 100644 index 0000000000..e7f45851b4 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.13) + +project(example C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +set(TEST_INCLUDE_PATHS ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/only_one_task_enter_suspendall) +set(TEST_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../../../tests/smp/only_one_task_enter_suspendall) + +add_library(only_one_task_enter_suspendall INTERFACE) +target_sources(only_one_task_enter_suspendall INTERFACE + ${BOARD_LIBRARY_DIR}/main.c + ${CMAKE_CURRENT_LIST_DIR}/only_one_task_enter_suspendall_test_runner.c + ${TEST_SOURCE_DIR}/only_one_task_enter_suspendall.c) + +target_include_directories(only_one_task_enter_suspendall INTERFACE + ${CMAKE_CURRENT_LIST_DIR}/../../.. + ${TEST_INCLUDE_PATHS} + ) + +target_link_libraries(only_one_task_enter_suspendall INTERFACE + FreeRTOS-Kernel + FreeRTOS-Kernel-Heap4 + ${BOARD_LINK_LIBRARIES}) + +add_executable(test_only_one_task_enter_suspendall) +enable_board_functions(test_only_one_task_enter_suspendall) +target_link_libraries(test_only_one_task_enter_suspendall only_one_task_enter_suspendall) +target_include_directories(test_only_one_task_enter_suspendall PUBLIC + ${BOARD_INCLUDE_PATHS}) +target_compile_definitions(test_only_one_task_enter_suspendall PRIVATE + ${BOARD_DEFINES} +) diff --git a/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall_test_runner.c b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall_test_runner.c new file mode 100644 index 0000000000..277f6284a7 --- /dev/null +++ b/FreeRTOS/Test/Target/boards/pico/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall_test_runner.c @@ -0,0 +1,73 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file only_one_task_enter_suspendall_test_runner.c + * @brief The implementation of main function to start test runner task. + * + * Procedure: + * - Initialize environment. + * - Run the test case. + */ + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" + +/* Pico includes. */ +#include "pico/multicore.h" +#include "pico/stdlib.h" + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ); + +/*-----------------------------------------------------------*/ + +static void prvTestRunnerTask( void * pvParameters ) +{ + ( void ) pvParameters; + + /* Run test case. */ + vRunOnlyOneTaskEnterSuspendAll(); + + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vRunTest( void ) +{ + xTaskCreate( prvTestRunnerTask, + "testRunner", + configMINIMAL_STACK_SIZE, + NULL, + configMAX_PRIORITIES - 1, + NULL ); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall.c b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall.c new file mode 100644 index 0000000000..2ecd971332 --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/only_one_task_enter_suspendall.c @@ -0,0 +1,250 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/** + * @file only_one_task_enter_suspendall.c + * @brief Only one task shall be able to enter the section protected by + * vTaskSuspendAll/xTaskResumeAll + * + * Procedure: + * - Create ( num of cores ) tasks. + * - All tasks increment a shared counter for TASK_INCREASE_COUNTER_TIMES + * times in the section protected by vTaskSuspendAll/xTaskResumeAll. + * Expected: + * - All tasks have correct value of counter after incrementing. + */ + +/* Standard includes. */ +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" + +/* Unit testing support functions. */ +#include "unity.h" +/*-----------------------------------------------------------*/ + +/** + * @brief Number of times each task increments the shared counter. + */ +#define TASK_INCREASE_COUNTER_TIMES ( 10000 ) + +/** + * @brief Timeout value to stop test. + */ +#define TEST_TIMEOUT_MS ( 1000 ) +/*-----------------------------------------------------------*/ + +/** + * @brief Test case "Only one task enters the section protected by + * vTaskSuspendAll/xTaskResumeAll". + */ +void Test_OnlyOneTaskEnterSuspendAll( void ); + +/** + * @brief Task function to increment the shared counter and then block. + */ +static void prvTaskIncCounter( void * pvParameters ); +/*-----------------------------------------------------------*/ + +#if ( configNUMBER_OF_CORES < 2 ) + #error This test is for FreeRTOS SMP and therefore, requires at least 2 cores. +#endif /* if ( configNUMBER_OF_CORES < 2 ) */ + +#if ( configMAX_PRIORITIES <= 2 ) + #error configMAX_PRIORITIES must be larger than 2 to avoid scheduling idle tasks unexpectedly. +#endif /* if ( configMAX_PRIORITIES <= 2 ) */ +/*-----------------------------------------------------------*/ + +/** + * @brief Handles of the tasks created in this test. + */ +static TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES ]; + +/** + * @brief Indexes of the tasks created in this test. + */ +static uint32_t xTaskIndexes[ configNUMBER_OF_CORES ]; + +/** + * @brief Flags to indicate if tasks T0~Tn-1 detect an error or not. + */ +static BaseType_t xTestResults[ configNUMBER_OF_CORES ] = { pdFAIL }; + +/** + * @brief Flags to indicate tasks T0~Tn-1 started running. + */ +static volatile BaseType_t xTaskRunning[ configNUMBER_OF_CORES ] = { pdFALSE }; + +/** + * @brief Shared counter for all tasks to increment. + */ +static volatile uint32_t xSharedCounter = 0; +/*-----------------------------------------------------------*/ + +static void prvTaskIncCounter( void * pvParameters ) +{ + uint32_t currentTaskIdx = *( ( uint32_t * ) pvParameters ); + BaseType_t xAllTaskReady = pdFALSE; + BaseType_t xTestResult = pdPASS; + uint32_t xLocalCounter = 0; + uint32_t i; + + /* Wait for all tasks to start running. */ + xTaskRunning[ currentTaskIdx ] = pdTRUE; + + while( xAllTaskReady == pdFALSE ) + { + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xTaskRunning[ i ] != pdTRUE ) + { + break; + } + } + + if( i == configNUMBER_OF_CORES ) + { + xAllTaskReady = pdTRUE; + } + } + + /* Increment the shared counter in a loop. The expectation is that only one + * task increments the counter at a time as it is incremented in the section + * protected by vTaskSuspendAll/xTaskResumeAll. */ + vTaskSuspendAll(); + { + xLocalCounter = xSharedCounter; + + for( i = 0; i < TASK_INCREASE_COUNTER_TIMES; i++ ) + { + /* Increment the local variable xLocalCounter and shared variable + * xSharedCounter. */ + xSharedCounter++; + xLocalCounter++; + + /* If the implementation of vTaskSuspendAll is not correct and + * multiple tasks are able to enter the section protected by + * vTaskSuspendAll/xTaskResumeAll, shared counter will be + * incremented by multiple tasks and as a result, local counter + * xLocalCounterwon't be equal to the shared counter + * xSharedCounter. */ + if( xSharedCounter != xLocalCounter ) + { + xTestResult = pdFAIL; + break; + } + } + } + ( void ) xTaskResumeAll(); + + xTestResults[ currentTaskIdx ] = xTestResult; + + /* Blocking the test task. */ + vTaskDelay( portMAX_DELAY ); +} +/*-----------------------------------------------------------*/ + +void Test_OnlyOneTaskEnterSuspendAll( void ) +{ + uint32_t i; + + BaseType_t xTaskCreationResult; + + /* Create configNUMBER_OF_CORES test tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIndexes[ i ] = i; + xTaskCreationResult = xTaskCreate( prvTaskIncCounter, + "IncCounter", + configMINIMAL_STACK_SIZE, + &( xTaskIndexes[ i ] ), + configMAX_PRIORITIES - 2, + &( xTaskHandles[ i ] ) ); + + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTaskCreationResult, "Task creation failed." ); + } + + /* Delay for other cores to run tasks. */ + vTaskDelay( pdMS_TO_TICKS( TEST_TIMEOUT_MS ) ); + + /* Validate that none of the test tasks detected error. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + TEST_ASSERT_EQUAL_MESSAGE( pdPASS, xTestResults[ i ], "Critical section test task failed." ); + } + + /* Verify the shared counter value. */ + TEST_ASSERT_EQUAL_UINT32( configNUMBER_OF_CORES * TASK_INCREASE_COUNTER_TIMES, xSharedCounter ); +} +/*-----------------------------------------------------------*/ + +/* Runs before every test, put init calls here. */ +void setUp( void ) +{ + uint32_t i; + + xSharedCounter = 0; + + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + xTaskIndexes[ i ] = i; + xTaskHandles[ i ] = NULL; + } +} +/*-----------------------------------------------------------*/ + +/* Runs after every test, put clean-up calls here. */ +void tearDown( void ) +{ + uint32_t i; + + /* Delete all the tasks. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( xTaskHandles[ i ] != NULL ) + { + vTaskDelete( xTaskHandles[ i ] ); + xTaskHandles[ i ] = NULL; + } + } +} +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run "only one task enter suspend all" + * test. + */ +void vRunOnlyOneTaskEnterSuspendAll( void ) +{ + UNITY_BEGIN(); + + RUN_TEST( Test_OnlyOneTaskEnterSuspendAll ); + + UNITY_END(); +} +/*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/test_config.h b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/test_config.h new file mode 100644 index 0000000000..41056d03ea --- /dev/null +++ b/FreeRTOS/Test/Target/tests/smp/only_one_task_enter_suspendall/test_config.h @@ -0,0 +1,59 @@ +/* + * FreeRTOS V202212.00 + * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef TEST_CONFIG_H +#define TEST_CONFIG_H + +/* This file must be included at the end of the FreeRTOSConfig.h. It contains + * any FreeRTOS specific configurations that the test requires. */ + +#ifdef configRUN_MULTIPLE_PRIORITIES + #undef configRUN_MULTIPLE_PRIORITIES +#endif /* ifdef configRUN_MULTIPLE_PRIORITIES */ + +#ifdef configUSE_TIME_SLICING + #undef configUSE_TIME_SLICING +#endif /* ifdef configUSE_TIME_SLICING */ + +#ifdef configUSE_PREEMPTION + #undef configUSE_PREEMPTION +#endif /* ifdef configUSE_PREEMPTION */ + +#define configRUN_MULTIPLE_PRIORITIES 1 +#define configUSE_TIME_SLICING 1 +#define configUSE_PREEMPTION 1 + +/*-----------------------------------------------------------*/ + +/** + * @brief Entry point for test runner to run "only one task enter suspend all" + * test. + */ +void vRunOnlyOneTaskEnterSuspendAll( void ); + +/*-----------------------------------------------------------*/ + +#endif /* ifndef TEST_CONFIG_H */