diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-09-08 13:35:02 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-09-08 13:48:08 +0200 |
commit | b71014376cedbe70f329324035af9ee86c569ae6 (patch) | |
tree | 7ab9254f32acbfab79a86c23655e60aec6ca8117 | |
parent | 4e5ce1eb8766ebf044f4b18bd29a06b3e554f744 (diff) |
valiation: Test MrsP special casequal-35
-rw-r--r-- | testsuites/validation/tc-sem-smp.c | 266 |
1 files changed, 262 insertions, 4 deletions
diff --git a/testsuites/validation/tc-sem-smp.c b/testsuites/validation/tc-sem-smp.c index 24ced13333..29593115e7 100644 --- a/testsuites/validation/tc-sem-smp.c +++ b/testsuites/validation/tc-sem-smp.c @@ -53,7 +53,6 @@ #endif #include <rtems.h> -#include <setjmp.h> #include <rtems/score/threaddispatch.h> #include "ts-config.h" @@ -70,9 +69,50 @@ * * This test case performs the following actions: * - * - Create a worker thread and a mutex. Use the mutex and the worker to + * - Create a worker thread and a MrsP mutex. Use the mutex and the worker to * perform a bad sticky thread queue enqueue. * + * - Create two worker threads, a MrsP mutex, and a priority inheritance mutex. + * Use the mutexes and the workers to raise the current priority to a higher + * priority than the ceiling priority of the mutex while one of the workers + * waits on the mutex. + * + * - Let the first worker try to obtain the MrsP mutex. Check that it + * acquired the ceiling priority. + * + * - Let the second worker try to obtain the priority inheritance mutex. + * Check that the first worker inherited the priority from the second + * worker. + * + * - Set the real priority of the first worker. Check that it defines the + * current priority. + * + * - Release the MrsP mutex so that the first worker can to obtain it. It + * will replace a temporary priority node which is the maximum priority + * node. This is the first scenario we want to test. + * + * - Obtain the MrsP mutex for the runner thread to start the second scenario + * we would like to test. + * + * - Let the first worker try to obtain the MrsP mutex. Check that it + * acquired the ceiling priority. + * + * - Let the second worker try to obtain the priority inheritance mutex. + * Check that the first worker inherited the priority from the second + * worker. + * + * - Lower the priority of the second worker. Check that the inherited + * priority of the first worker reflects this priority change. + * + * - Change the real priority of the first worker so that it defines its + * current priority. + * + * - Release the MrsP mutex so that the first worker can to obtain it. It + * will replace a temporary priority node which is between the minimum and + * maximum priority node. This is the second scenario we want to test. + * + * - Clean up all used resources. + * * @{ */ @@ -86,9 +126,19 @@ typedef struct { rtems_id mutex_id;; /** + * @brief This member contains the second mutex identifier. + */ + rtems_id mutex_2_id;; + + /** * @brief If this member is true, then the worker is done. */ volatile bool done; + + /** + * @brief If this member is true, then the second worker is done. + */ + volatile bool done_2; } RtemsSemValSmp_Context; static RtemsSemValSmp_Context @@ -166,9 +216,35 @@ static void BadEnqueueTask( rtems_task_argument arg ) ObtainMutex( ctx->mutex_id ); } +static void ObtainReleaseMrsPTask( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = (Context *) arg; + ObtainMutex( ctx->mutex_2_id ); + ctx->done = true; + ObtainMutex( ctx->mutex_id ); + ReleaseMutex( ctx->mutex_id ); + ReleaseMutex( ctx->mutex_2_id ); + ctx->done = true; + SuspendSelf(); +} + +static void ObtainRelease2Task( rtems_task_argument arg ) +{ + Context *ctx; + + ctx = (Context *) arg; + ctx->done_2 = true; + ObtainMutex( ctx->mutex_2_id ); + ReleaseMutex( ctx->mutex_2_id ); + ctx->done_2 = true; + SuspendSelf(); +} + /** - * @brief Create a worker thread and a mutex. Use the mutex and the worker to - * perform a bad sticky thread queue enqueue. + * @brief Create a worker thread and a MrsP mutex. Use the mutex and the + * worker to perform a bad sticky thread queue enqueue. */ static void RtemsSemValSmp_Action_0( RtemsSemValSmp_Context *ctx ) { @@ -189,6 +265,7 @@ static void RtemsSemValSmp_Action_0( RtemsSemValSmp_Context *ctx ) PRIO_HIGH, &ctx->mutex_id ); + T_rsc_success( sc ); worker_id = CreateTask( "WORK", PRIO_NORMAL ); SetScheduler( worker_id, scheduler_b_id, PRIO_NORMAL ); @@ -207,6 +284,186 @@ static void RtemsSemValSmp_Action_0( RtemsSemValSmp_Context *ctx ) } /** + * @brief Create two worker threads, a MrsP mutex, and a priority inheritance + * mutex. Use the mutexes and the workers to raise the current priority to a + * higher priority than the ceiling priority of the mutex while one of the + * workers waits on the mutex. + */ +static void RtemsSemValSmp_Action_1( RtemsSemValSmp_Context *ctx ) +{ + rtems_status_code sc; + rtems_id worker_id; + rtems_id worker_2_id; + rtems_id scheduler_b_id; + rtems_task_priority prio; + + sc = rtems_scheduler_ident( TEST_SCHEDULER_B_NAME, &scheduler_b_id ); + T_rsc_success( sc ); + + sc = rtems_semaphore_create( + rtems_build_name( 'M', 'U', 'T', 'X' ), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | + RTEMS_MULTIPROCESSOR_RESOURCE_SHARING, + PRIO_HIGH, + &ctx->mutex_id + ); + T_rsc_success( sc ); + + sc = rtems_semaphore_set_priority( + ctx->mutex_id, + scheduler_b_id, + PRIO_HIGH, + &prio + ); + T_rsc_success( sc ); + + ctx->mutex_2_id = CreateMutex(); + + worker_id = CreateTask( "WORK", PRIO_NORMAL ); + SetScheduler( worker_id, scheduler_b_id, PRIO_NORMAL ); + + worker_2_id = CreateTask( "WRK2", PRIO_NORMAL ); + SetScheduler( worker_2_id, scheduler_b_id, PRIO_VERY_HIGH ); + + /* + * Let the first worker try to obtain the MrsP mutex. Check that it acquired + * the ceiling priority. + */ + ObtainMutex( ctx->mutex_id ); + ctx->done = false; + StartTask( worker_id, ObtainReleaseMrsPTask, ctx ); + + while ( !ctx->done ) { + /* Wait */ + } + + ctx->done = false; + WaitForIntendToBlock( worker_id ); + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_HIGH ); + + /* + * Let the second worker try to obtain the priority inheritance mutex. Check + * that the first worker inherited the priority from the second worker. + */ + ctx->done_2 = false; + StartTask( worker_2_id, ObtainRelease2Task, ctx ); + + while ( !ctx->done_2 ) { + /* Wait */ + } + + ctx->done_2 = false; + WaitForExecutionStop( worker_2_id ); + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_VERY_HIGH ); + + /* + * Set the real priority of the first worker. Check that it defines the + * current priority. + */ + SetPriority( worker_id, PRIO_ULTRA_HIGH ); + + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_ULTRA_HIGH ); + + /* + * Release the MrsP mutex so that the first worker can to obtain it. It will + * replace a temporary priority node which is the maximum priority node. + * This is the first scenario we want to test. + */ + ReleaseMutex( ctx->mutex_id ); + + while ( !ctx->done || !ctx->done_2 ) { + /* Wait */ + } + + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_ULTRA_HIGH ); + + /* + * Obtain the MrsP mutex for the runner thread to start the second scenario + * we would like to test. + */ + ObtainMutex( ctx->mutex_id ); + + /* + * Let the first worker try to obtain the MrsP mutex. Check that it acquired + * the ceiling priority. + */ + ctx->done = false; + sc = rtems_task_restart( worker_id, (rtems_task_argument) ctx ); + T_rsc_success( sc ); + + while ( !ctx->done ) { + /* Wait */ + } + + ctx->done = false; + WaitForIntendToBlock( worker_id ); + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_HIGH ); + + /* + * Let the second worker try to obtain the priority inheritance mutex. Check + * that the first worker inherited the priority from the second worker. + */ + ctx->done_2 = false; + sc = rtems_task_restart( worker_2_id, (rtems_task_argument) ctx ); + T_rsc_success( sc ); + + while ( !ctx->done_2 ) { + /* Wait */ + } + + ctx->done_2 = false; + WaitForExecutionStop( worker_2_id ); + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_VERY_HIGH ); + + /* + * Lower the priority of the second worker. Check that the inherited + * priority of the first worker reflects this priority change. + */ + SetPriority( worker_2_id, PRIO_LOW ); + + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_HIGH ); + + /* + * Change the real priority of the first worker so that it defines its + * current priority. + */ + SetPriority( worker_id, PRIO_ULTRA_HIGH ); + + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_ULTRA_HIGH ); + + /* + * Release the MrsP mutex so that the first worker can to obtain it. It will + * replace a temporary priority node which is between the minimum and maximum + * priority node. This is the second scenario we want to test. + */ + ReleaseMutex( ctx->mutex_id ); + + while ( !ctx->done || !ctx->done_2 ) { + /* Wait */ + } + + prio = GetPriorityByScheduler( worker_id, scheduler_b_id ); + T_eq_u32( prio, PRIO_ULTRA_HIGH ); + + /* + * Clean up all used resources. + */ + DeleteTask( worker_id ); + DeleteTask( worker_2_id ); + DeleteMutex( ctx->mutex_id ); + DeleteMutex( ctx->mutex_2_id ); +} + +/** * @fn void T_case_body_RtemsSemValSmp( void ) */ T_TEST_CASE_FIXTURE( RtemsSemValSmp, &RtemsSemValSmp_Fixture ) @@ -216,6 +473,7 @@ T_TEST_CASE_FIXTURE( RtemsSemValSmp, &RtemsSemValSmp_Fixture ) ctx = T_fixture_context(); RtemsSemValSmp_Action_0( ctx ); + RtemsSemValSmp_Action_1( ctx ); } /** @} */ |