[PATCH] validation: Test scheduler detail

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Jul 5 06:35:07 UTC 2022


This particular state during a reconsider help request scheduler operation was
only covered by the existing test suites under some timing conditions.
---
 testsuites/validation/tc-sched-smp.c | 137 ++++++++++++++++++++++++++-
 1 file changed, 135 insertions(+), 2 deletions(-)

diff --git a/testsuites/validation/tc-sched-smp.c b/testsuites/validation/tc-sched-smp.c
index 957a978980..6eb98b5360 100644
--- a/testsuites/validation/tc-sched-smp.c
+++ b/testsuites/validation/tc-sched-smp.c
@@ -7,7 +7,7 @@
  */
 
 /*
- * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ * Copyright (C) 2021, 2022 embedded brains GmbH (http://www.embedded-brains.de)
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -55,6 +55,7 @@
 #include <rtems.h>
 #include <rtems/test-scheduler.h>
 #include <rtems/score/percpu.h>
+#include <rtems/score/schedulersmp.h>
 #include <rtems/score/threadimpl.h>
 
 #include "tx-support.h"
@@ -213,6 +214,24 @@
  *
  *   - Clean up all used resources.
  *
+ * - Create three worker threads and a mutex.  Use the mutex and the worker to
+ *   check that a not scheduled thread does not get removed from the set of
+ *   ready threads of a scheduler when a help request is reconsidered.
+ *
+ *   - Prevent that worker B can perform a post-switch cleanup.
+ *
+ *   - Give worker C a lower priority than worker B.  Worker B will try to
+ *     finish the thread dispatch by doing a post-switch cleanup.  The
+ *     post-switch cleanup cannot progress since the runner owns the thread
+ *     state lock.  Wait until the other processor waits on the thread state
+ *     lock of worker B.
+ *
+ *   - Give worker C a higher priority than worker B.  Let worker B do its
+ *     post-switch cleanup which will carry out the reconsider help requests
+ *     for a not scheduled thread.
+ *
+ *   - Clean up all used resources.
+ *
  * @{
  */
 
@@ -250,7 +269,17 @@ typedef struct {
   /**
    * @brief This member contains the worker busy status.
    */
-  volatile bool busy[ WORKER_COUNT ];;
+  volatile bool busy[ WORKER_COUNT ];
+
+  /**
+   * @brief This member contains an ISR lock context.
+   */
+  ISR_lock_Context lock_context;
+
+  /**
+   * @brief This member contains a counter.
+   */
+  uint32_t counter;
 
   /**
    * @brief If this member is true, then the worker shall be in the busy loop.
@@ -686,6 +715,51 @@ static void CleanupOwnerBlocked( Context *ctx )
   SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_A_ID, PRIO_HIGH );
 }
 
+static void ReconsiderHelpRequestB(
+  void                    *arg,
+  const T_scheduler_event *event,
+  T_scheduler_when         when
+)
+{
+  Context *ctx;
+
+  (void) when;
+  ctx = arg;
+
+  if ( event->operation == T_SCHEDULER_RECONSIDER_HELP_REQUEST ) {
+    Scheduler_SMP_Node *node;
+
+    node = (Scheduler_SMP_Node *) event->node;
+    T_eq_int( node->state, SCHEDULER_SMP_NODE_READY );
+    ++ctx->counter;
+  }
+}
+
+static void ReleaseThreadLockB(
+  void                    *arg,
+  const T_scheduler_event *event,
+  T_scheduler_when         when
+)
+{
+  Context *ctx;
+
+  ctx = arg;
+
+  if (
+    when == T_SCHEDULER_AFTER &&
+    event->operation == T_SCHEDULER_UPDATE_PRIORITY
+  ) {
+    Thread_Control *worker_b;
+
+    T_scheduler_set_event_handler( ReconsiderHelpRequestB, ctx );
+
+    worker_b = GetThread( ctx->worker_id[ WORKER_B ] );
+    T_eq_int( worker_b->Scheduler.state, THREAD_SCHEDULER_READY );
+
+    _Thread_State_release_critical( worker_b, &ctx->lock_context );
+  }
+}
+
 static void Worker( rtems_task_argument arg, WorkerIndex worker )
 {
   Context *ctx;
@@ -1232,6 +1306,64 @@ static void ScoreSchedSmpValSmp_Action_16( ScoreSchedSmpValSmp_Context *ctx )
   CleanupOwnerBlocked( ctx );
 }
 
+/**
+ * @brief Create three worker threads and a mutex.  Use the mutex and the
+ *   worker to check that a not scheduled thread does not get removed from the
+ *   set of ready threads of a scheduler when a help request is reconsidered.
+ */
+static void ScoreSchedSmpValSmp_Action_17( ScoreSchedSmpValSmp_Context *ctx )
+{
+  Thread_Control *worker_b;
+
+  SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_B_ID, PRIO_NORMAL );
+  SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_B_ID, PRIO_HIGH );
+  SendAndSync( ctx, WORKER_B, EVENT_OBTAIN );
+  SendEvents( ctx->worker_id[ WORKER_A ], EVENT_OBTAIN );
+  SetPriority( ctx->worker_id[ WORKER_A ], PRIO_LOW );
+  MakeBusy( ctx, WORKER_B );
+  WaitForBusy( ctx, WORKER_B );
+  MakeBusy( ctx, WORKER_C );
+  WaitForBusy( ctx, WORKER_C );
+
+  /*
+   * Prevent that worker B can perform a post-switch cleanup.
+   */
+  worker_b = GetThread( ctx->worker_id[ WORKER_B ] );
+  _Thread_State_acquire( worker_b, &ctx->lock_context );
+  _ISR_lock_ISR_enable( &ctx->lock_context );
+
+  /*
+   * Give worker C a lower priority than worker B.  Worker B will try to finish
+   * the thread dispatch by doing a post-switch cleanup.  The post-switch
+   * cleanup cannot progress since the runner owns the thread state lock.  Wait
+   * until the other processor waits on the thread state lock of worker B.
+   */
+  SetPriority( ctx->worker_id[ WORKER_C ], PRIO_LOW );
+  TicketLockWaitForOthers( &worker_b->Join_queue.Queue.Lock, 1 );
+
+  /*
+   * Give worker C a higher priority than worker B.  Let worker B do its
+   * post-switch cleanup which will carry out the reconsider help requests for
+   * a not scheduled thread.
+   */
+  ctx->counter = 0;
+  T_scheduler_set_event_handler( ReleaseThreadLockB, ctx );
+  SetPriority( ctx->worker_id[ WORKER_C ], PRIO_HIGH );
+  T_scheduler_set_event_handler( NULL, NULL );
+  T_eq_u32( ctx->counter, 4 );
+
+  /*
+   * Clean up all used resources.
+   */
+  StopBusy( ctx, WORKER_B );
+  StopBusy( ctx, WORKER_C );
+  SendAndSync( ctx, WORKER_B, EVENT_RELEASE );
+  SetPriority( ctx->worker_id[ WORKER_A ], PRIO_HIGH );
+  SendEvents( ctx->worker_id[ WORKER_A ], EVENT_RELEASE );
+  SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_A_ID, PRIO_HIGH );
+  SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_A_ID, PRIO_HIGH );
+}
+
 /**
  * @fn void T_case_body_ScoreSchedSmpValSmp( void )
  */
@@ -1258,6 +1390,7 @@ T_TEST_CASE_FIXTURE( ScoreSchedSmpValSmp, &ScoreSchedSmpValSmp_Fixture )
   ScoreSchedSmpValSmp_Action_14( ctx );
   ScoreSchedSmpValSmp_Action_15( ctx );
   ScoreSchedSmpValSmp_Action_16( ctx );
+  ScoreSchedSmpValSmp_Action_17( ctx );
 }
 
 /** @} */
-- 
2.35.3



More information about the devel mailing list