diff --git a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c index 7e2334421cd..87e19135936 100644 --- a/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c +++ b/FreeRTOS/Test/CMock/smp/multiple_priorities_no_timeslice/covg_multiple_priorities_no_timeslice_utest.c @@ -3901,6 +3901,103 @@ void test_coverage_xTaskPriorityInherit_task_uxpriority_greater( void ) TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); } +/** + * @brief xTaskPriorityInherit - task is already running. + * A running task inherit a high priority task. Verify that the priority is raised. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) + * { + * prvYieldForTask( pxMutexHolderTCB ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) is false. + */ +void test_coverage_xTaskPriorityInherit_task_is_running( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < ( configNUMBER_OF_CORES - 1 ); i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + + /* API call. */ + xTaskPriorityInherit( &xTaskTCBs[ ( configNUMBER_OF_CORES - 1 ) ] ); + + /* Validation. */ + /* Verify the priority of the task is raised. */ + TEST_ASSERT_EQUAL( 2, xTaskTCBs[ ( configNUMBER_OF_CORES - 1 ) ].uxPriority ); +} + +/** + * @brief xTaskPriorityInherit - task is of invalid running state. + * A running task inherit a high priority task. Verify that the priority is raised. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) + * { + * prvYieldForTask( pxMutexHolderTCB ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxMutexHolderTCB ) != pdTRUE ) is true. + */ +void test_coverage_xTaskPriorityInherit_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + pxCurrentTCBs[ i ] = &xTaskTCBs[ i ]; + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + + /* API call. */ + xTaskPriorityInherit( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* The task in pending ready list should not in any event list now. */ + TEST_ASSERT_EQUAL( 2, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + /** * @brief xTaskPriorityDisinherit - restore priority after inheriting the priority of the mutex holder * @@ -4041,6 +4138,56 @@ void test_coverage_xTaskPriorityDisinherit_task_uxpriority_greater( void ) TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); } +/** + * @brief xTaskPriorityDisinherit - task is of invalid running state. + * The task disinherits a high priority task. Verify that the priority of the disinherited + * task is dropped to base priority. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * prvYieldCore( pxTCB->xTaskRunState ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_xTaskPriorityDisinherit_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 2, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 2 ]; + listINSERT_END( &pxReadyTasksLists[ 2 ], &xTaskTCBs[ i ].xStateListItem ); + xTaskTCBs[ i ].uxMutexesHeld = 1; + xTaskTCBs[ i ].uxBasePriority = 1; + + /* API call. */ + xTaskPriorityDisinherit( &xTaskTCBs[ configNUMBER_OF_CORES ] ); + + /* Validation. */ + /* The priority of the task is dropped to base priority. */ + TEST_ASSERT_EQUAL( xTaskTCBs[ i ].uxBasePriority, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + /** * @brief xTaskPriorityDisinheritAfterTimeout - restore priority after inheriting the priority of the mutex holder * @@ -4175,6 +4322,57 @@ void test_coverage_xTaskPriorityDisinheritAfterTimeout_task_uxpriority_greater( TEST_ASSERT_EQUAL( xTaskTCBs[ 1 ].xStateListItem.pvContainer, &pxReadyTasksLists[ xTaskTCBs[ 1 ].uxPriority ] ); } +/** + * @brief vTaskPriorityDisinheritAfterTimeout - task is of invalid running state. + * The task disinherit a high priority task due to high priority task timeout. Verify + * that the priority of the disinherited task is dropped to uxHighestPriorityWaitingTask. + * + * Coverage + * @code{c} + * ... + * if( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) + * { + * prvYieldCore( pxTCB->xTaskRunState ); + * } + * @endcode + * ( taskTASK_IS_RUNNING( pxTCB ) == pdTRUE ) is false. + */ +void test_coverage_vTaskPriorityDisinheritAfterTimeout_task_invalid_state( void ) +{ + TCB_t xTaskTCBs[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + UBaseType_t uxHighestPriorityWaitingTask = 2; + + /* Setup the variables and structure. */ + /* Create high priority task on core 1 ~ N-1. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + vCreateStaticTestTask( &xTaskTCBs[ i ], + 3, + i, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 3 ]; + listINSERT_END( &pxReadyTasksLists[ 3 ], &xTaskTCBs[ i ].xStateListItem ); + } + + /* Create a low priority task on last core. */ + vCreateStaticTestTask( &xTaskTCBs[ i ], + 1, + configNUMBER_OF_CORES, + pdFALSE ); + xTaskTCBs[ i ].xStateListItem.pxContainer = &pxReadyTasksLists[ 1 ]; + listINSERT_END( &pxReadyTasksLists[ 1 ], &xTaskTCBs[ i ].xStateListItem ); + xTaskTCBs[ i ].uxMutexesHeld = 1; + xTaskTCBs[ i ].uxBasePriority = 1; + + /* API call. */ + vTaskPriorityDisinheritAfterTimeout( &xTaskTCBs[ configNUMBER_OF_CORES ], uxHighestPriorityWaitingTask ); + + /* Validation. */ + /* The priority of the task is dropped to uxHighestPriorityWaitingTask. */ + TEST_ASSERT_EQUAL( uxHighestPriorityWaitingTask, xTaskTCBs[ configNUMBER_OF_CORES ].uxPriority ); +} + /** * @brief uxTaskGetSystemState - array size is less than current task number. * 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 139f7253296..700b83e0691 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 @@ -3184,3 +3184,219 @@ void test_task_yield_run_equal_priority_new_task( void ) /* The new task TN+1 should runs on core 0. */ verifySmpTask( &xTaskHandles[ i ], eRunning, 0 ); } + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-106 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priorirty task. + * The lower priority will be switched out when it disinherits higher priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Running State – Ready State – Running + * uxMutexesHeld - 1 + * + * Task TN+1 disinherits task T1's priority. + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * uxMutexesHeld - 0 + */ +void test_task_priority_inherit_disinherit( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + xTaskPriorityDisinherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the mutex held count is decreased. */ + TEST_ASSERT_EQUAL( 0U, xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld ); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify that the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-107 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priorirty task. + * The lower priority will be switched out when it is disinherited by higher priority + * task due to timeout. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Running State – Ready State – Running + * + * Task TN+1 is disinherited by task T1 due to timeout + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Running State – Running State – Ready + */ +void test_task_priority_inherit_disinherit_timeout( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + vTaskPriorityDisinheritAfterTimeout( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the high and medium priority tasks running. */ + for( i = 0; i < configNUMBER_OF_CORES; i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eRunning, i ); + } + + /* Verify that the low priority task is ready. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eReady, -1 ); +} diff --git a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c index a5ae7fd1b89..ceca6c00776 100644 --- a/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c +++ b/FreeRTOS/Test/CMock/smp/single_priority_no_timeslice/single_priority_no_timeslice_utest.c @@ -2326,3 +2326,219 @@ void test_task_block_all_cores_equal_priority_block_running( void ) /* Verify task T0 is now in the ready state */ verifySmpTask( &xTaskHandles[ 0 ], eReady, -1 ); } + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-108 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priorirty task. + * The lower priority will be switched out when it disinherits higher priority task. + * + * #define configRUN_MULTIPLE_PRIORITIES 1 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Ready State – Ready State – Running + * uxMutexesHeld - 1 + * + * Task TN+1 disinherits task T1's priority. + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * uxMutexesHeld - 0 + */ +void test_task_priority_inherit_disinherit( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + xTaskPriorityDisinherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the mutex held count is decreased. */ + TEST_ASSERT_EQUAL( 0U, xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld ); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +} + +/** + * @brief AWS_IoT-FreeRTOS_SMP_TC-109 + * Task can inherit or disinherit other higher priority task. This test verify that + * lower priority task will be selected to run when it inherit a higher priorirty task. + * The lower priority will be switched out when it is disinherited by higher priority + * task due to timeout. + * + * #define configRUN_MULTIPLE_PRIORITIES 0 + * #define configUSE_TIME_SLICING 0 + * #define configNUMBER_OF_CORES (N > 1) + * + * This test can be run with FreeRTOS configured for any number of cores greater + * than 1. + * + * Tasks are created prior to starting the scheduler + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Ready State – Ready State – Ready State – Ready + * + * After calling vTaskStartScheduler() + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + * + * Assuming task TN+1 is holding a mutex. Task TN+1 inherits task T1's priority + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 3 + * State – Running State – Ready State – Ready State – Running + * + * Task TN+1 is disinherited by task T1 due to timeout + * + * Task (T1) Task (T2) Task (TN) Task (TN + 1) + * Priority – 3 Priority – 2 Priority – 2 Priority – 1 + * State – Running State – Ready State – Ready State – Ready + */ +void test_task_priority_inherit_disinherit_timeout( void ) +{ + TaskHandle_t xTaskHandles[ configNUMBER_OF_CORES + 1 ] = { NULL }; + uint32_t i; + TaskStatus_t xTaskDetails; + + /* Create 1 high priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 3, &xTaskHandles[ 0 ] ); + + /* Create N - 1 Medium priority task. */ + for( i = 1; i < configNUMBER_OF_CORES; i++ ) + { + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 2, &xTaskHandles[ i ] ); + } + + /* Create 1 low priority task. */ + xTaskCreate( vSmpTestTask, "SMP Task", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandles[ i ] ); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } + + /* Assuming the low priority task is holding a mutex. */ + xTaskHandles[ configNUMBER_OF_CORES ]->uxMutexesHeld = 1; + + /* Low priority task inherit current core task priority, which is the high priority task. */ + taskENTER_CRITICAL(); + { + xTaskPriorityInherit( xTaskHandles[ configNUMBER_OF_CORES ] ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 3, xTaskDetails.xHandle->uxPriority ); + + /* Verify that the low priority task is running on last core. */ + verifySmpTask( &xTaskHandles[ configNUMBER_OF_CORES ], eRunning, ( configNUMBER_OF_CORES - 1 ) ); + + /* Disinherit low priority task after timeout to it's original priority. */ + taskENTER_CRITICAL(); + { + vTaskPriorityDisinheritAfterTimeout( xTaskHandles[ configNUMBER_OF_CORES ], 1 ); + } + taskEXIT_CRITICAL(); + + /* Verify the priority has been changed */ + vTaskGetInfo( xTaskHandles[ configNUMBER_OF_CORES ], &xTaskDetails, pdTRUE, eInvalid ); + TEST_ASSERT_EQUAL( 1, xTaskDetails.xHandle->uxPriority ); + + /* Verify the high priority task is running. */ + verifySmpTask( &xTaskHandles[ 0 ], eRunning, 0 ); + + /* Verify the medium and low priority tasks are ready. */ + for( i = 1; i < ( configNUMBER_OF_CORES + 1 ); i++ ) + { + verifySmpTask( &xTaskHandles[ i ], eReady, -1 ); + } +}