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 );
+ }
+}