diff --git a/FreeRTOS/Source b/FreeRTOS/Source index 53c7e7c46f..e43553af1e 160000 --- a/FreeRTOS/Source +++ b/FreeRTOS/Source @@ -1 +1 @@ -Subproject commit 53c7e7c46f20dbd941d3f17116725d8fda9e6b90 +Subproject commit e43553af1e3d19a1eec27593c332f97e986cbd1c diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c index 3757ba8803..6d53b05993 100644 --- a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/multiple_priorities_no_timeslice_utest.c @@ -3499,3 +3499,85 @@ void test_task_priority_inherit_disinherit_timeout( void ) /* Verify that the low priority task is ready. */ verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); } + + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-110 + * Yield for the task when setting the core affinity of a task of ready state. This + * situation happens when the core can't select the task to run before the task + * core affinity is changed. The vTaskCoreAffinitySet should request a core on which + * the task is able to run with new core affinity setting. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configUSE_CORE_AFFINITY 1 + * #define configNUMBER_OF_CORES (N > 2) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 2. + * + * Tasks are created prior to starting the scheduler + * + * Main task (T1) + * Priority – 3 + * State – Ready + * + * After calling vTaskStartScheduler() + * + * Main task (T1) + * Priority – 3 + * State – Running( 0 ) + * + * After creating the core task with xTaskCreate(). Core 2 was requested to yield + * but not yet able to select core task. + * + * Main task (T1) Core Task (T2) + * Priority – 3 Priority – 3 + * State – Running( 0 ) State – Ready + * + * After setting the core affinity of the core task to core 1 only with vTaskCoreAffinitySet(). + * + * Main task (T1) Core Task (T2) + * Priority – 3 Priority – 3 + * State – Running( 0 ) Affinity – ( 1 ) + * State – Ready + * + * After async core yield for core task. + * + * Main Task (T1) Core Task (T2) + * Priority – 3 Priority – 3 + * State – Running( 0 ) Affinity – ( 1 ) + * State – Running( 1 ) + * + */ +void test_task_create_task_set_affinity_async_yield( void ) +{ + TaskHandle_t xMainTaskHandle; + TaskHandle_t xCoreTaskHandle; + BaseType_t xCoreID; + + /* The core yield should be manually triggered in the test cases when using + * async core yield setup. */ + commonAsyncCoreYieldSetup(); + + /* Create high priority main task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xMainTaskHandle ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Create high priority core task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xCoreTaskHandle ); + + /* Set the core affinity of the core task to core 1. */ + vTaskCoreAffinitySet( xCoreTaskHandle, ( 1 << 1 ) ); + + /* Core yield is called here to simulate SMP asynchronous behavior. */ + for( xCoreID = 0; xCoreID < configNUMBER_OF_CORES; xCoreID++ ) + { + vCheckAndExecuteAsyncCoreYield( xCoreID ); + } + + /* Verify that the task core task can run on core 1. */ + verifySmpTask( &xCoreTaskHandle, eRunning, 1 ); +} diff --git a/FreeRTOS/Test/CMock/smp/smp_utest_common.c b/FreeRTOS/Test/CMock/smp/smp_utest_common.c index ebc4ec87eb..33b1433e51 100644 --- a/FreeRTOS/Test/CMock/smp/smp_utest_common.c +++ b/FreeRTOS/Test/CMock/smp/smp_utest_common.c @@ -154,6 +154,14 @@ void vFakePortYieldCoreStubCallback( int xCoreID, } } +void vFakePortYieldCoreAsyncStubCallback( int xCoreID, + int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + xCoreYields[ xCoreID ] = pdTRUE; +} + void vFakePortYieldStubCallback( int cmock_num_calls ) { vTaskSwitchContext( xCurrentCoreId ); @@ -182,6 +190,34 @@ void vSetCurrentCore( BaseType_t xCoreID ) xCurrentCoreId = xCoreID; } +void vCheckAndExecuteAsyncCoreYield( BaseType_t xCoreID ) +{ + BaseType_t xCoreInCritical = pdFALSE; + BaseType_t xPreviousCoreId = xCurrentCoreId; + int i; + + if( xCoreYields[ xCoreID ] != pdFALSE ) + { + /* Check if the lock is acquired by any core. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + if( ( xIsrLockCount[ i ] > 0 ) || ( xTaskLockCount[ i ] > 0 ) ) + { + xCoreInCritical = pdTRUE; + break; + } + } + + if( xCoreInCritical != pdTRUE ) + { + /* No task is in the critical section. We can yield this core. */ + xCurrentCoreId = xCoreID; + vTaskSwitchContext( xCurrentCoreId ); + xCurrentCoreId = xPreviousCoreId; + } + } +} + static void vYieldCores( void ) { BaseType_t i; @@ -265,6 +301,14 @@ void vFakePortReleaseTaskLockCallback( int cmock_num_calls ) } } +void vFakePortReleaseTaskLockAsyncCallback( int cmock_num_calls ) +{ + ( void ) cmock_num_calls; + + TEST_ASSERT_MESSAGE( xTaskLockCount[ xCurrentCoreId ] > 0, "xTaskLockCount[ xCurrentCoreId ] <= 0" ); + xTaskLockCount[ xCurrentCoreId ]--; +} + portBASE_TYPE vFakePortEnterCriticalFromISRCallback( int cmock_num_calls ) { portBASE_TYPE xSavedInterruptState; @@ -281,6 +325,12 @@ void vFakePortExitCriticalFromISRCallback( portBASE_TYPE xSavedInterruptState, vYieldCores(); } +void vFakePortExitCriticalFromISRAsyncCallback( portBASE_TYPE xSavedInterruptState, + int cmock_num_calls ) +{ + vTaskExitCriticalFromISR( xSavedInterruptState ); +} + /* ============================= Unity Fixtures ============================= */ void commonSetUp( void ) @@ -342,6 +392,13 @@ void commonSetUp( void ) memset( xIsrLockCount, 0x00, sizeof( xIsrLockCount ) ); } +void commonAsyncCoreYieldSetup( void ) +{ + vFakePortYieldCore_StubWithCallback( vFakePortYieldCoreAsyncStubCallback ); + vFakePortExitCriticalFromISR_StubWithCallback( vFakePortExitCriticalFromISRAsyncCallback ); + vFakePortReleaseTaskLock_StubWithCallback( vFakePortReleaseTaskLockAsyncCallback ); +} + void commonTearDown( void ) { } diff --git a/FreeRTOS/Test/CMock/smp/smp_utest_common.h b/FreeRTOS/Test/CMock/smp/smp_utest_common.h index 8a05c1268b..a1ed4fccf4 100644 --- a/FreeRTOS/Test/CMock/smp/smp_utest_common.h +++ b/FreeRTOS/Test/CMock/smp/smp_utest_common.h @@ -65,6 +65,12 @@ void vPortFree( void * pv ); */ void commonSetUp( void ); +/** + * @brief Common test case asyncrhonous core yield setup function for SMP tests. + * This API should be called after commonSetUp(). + */ +void commonAsyncCoreYieldSetup( void ); + /** * @brief Common test case teardown function for SMP tests. */ @@ -98,6 +104,11 @@ void xTaskIncrementTick_helper( void ); */ void vSetCurrentCore( BaseType_t xCoreID ); +/** + * @brief Check and execut asynchronous core yield request. + */ +void vCheckAndExecuteAsyncCoreYield( BaseType_t xCoreID ); + /** * @brief Helper function to create static test task. */ diff --git a/manifest.yml b/manifest.yml index 85c31dfddc..eff9194b6a 100644 --- a/manifest.yml +++ b/manifest.yml @@ -5,7 +5,7 @@ license: "MIT" dependencies: - name: "FreeRTOS-Kernel" - version: "53c7e7c46" + version: "e43553af1" repository: type: "git" url: "https://github.com/FreeRTOS/FreeRTOS-Kernel.git"