[rtems-central commit] spec: Specify SMP scheduler detail

Sebastian Huber sebh at rtems.org
Wed Nov 24 09:17:34 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    3d51ce69a90db1a85ab4bcb88dbcf7e41276beb8
Changeset: http://git.rtems.org/rtems-central/commit/?id=3d51ce69a90db1a85ab4bcb88dbcf7e41276beb8

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Nov 24 09:23:09 2021 +0100

spec: Specify SMP scheduler detail

---

 spec/score/sched/smp/req/preempt-blocked.yml | 16 +++++++
 spec/score/sched/smp/val/smp.yml             | 67 ++++++++++++++++++++++++++++
 2 files changed, 83 insertions(+)

diff --git a/spec/score/sched/smp/req/preempt-blocked.yml b/spec/score/sched/smp/req/preempt-blocked.yml
new file mode 100644
index 0000000..ecc95f1
--- /dev/null
+++ b/spec/score/sched/smp/req/preempt-blocked.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: RTEMS_SMP
+links:
+- role: requirement-refinement
+  uid: group
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+  While a thread is scheduled by a ${/glossary/scheduler-helping:/term}, while
+  the thread is blocked, when the thread is preempted by the helping scheduler,
+  the thread shall be blocked by the helping scheduler.
+type: requirement
diff --git a/spec/score/sched/smp/val/smp.yml b/spec/score/sched/smp/val/smp.yml
index 36b9c0a..28963f0 100644
--- a/spec/score/sched/smp/val/smp.yml
+++ b/spec/score/sched/smp/val/smp.yml
@@ -5,6 +5,41 @@ enabled-by: RTEMS_SMP
 links: []
 test-actions:
 - action-brief: |
+    Construct a system state in which a thread is preempted while it is
+    blocked.
+  action-code: |
+    SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_B_ID, PRIO_NORMAL );
+    SendEvents( ctx->worker_id[ WORKER_A ], EVENT_OBTAIN );
+    SendAndSync( ctx, WORKER_B, EVENT_OBTAIN );
+    SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_B_ID, PRIO_HIGH );
+    SetPriority( ctx->worker_id[ WORKER_A ], PRIO_NORMAL );
+    MakeBusy( ctx, WORKER_A );
+    WaitForBusy( ctx, WORKER_A );
+  checks:
+  - brief: |
+      Block worker A and preempt it before the withdraw node operations are
+      performed for worker A.
+    code: |
+      T_scheduler_set_event_handler( BlockAndPreempt, ctx );
+      SuspendTask( ctx->worker_id[ WORKER_A ] );
+    links:
+    - role: validation
+      uid: ../req/preempt-blocked
+  - brief: |
+      Clean up all used resources.
+    code: |
+      ResumeTask( ctx->worker_id[ WORKER_A ] );
+      StopBusy( ctx, WORKER_C );
+      StopBusy( ctx, WORKER_A );
+      SetPriority( ctx->worker_id[ WORKER_A ], PRIO_HIGH );
+      SetSelfPriority( PRIO_NORMAL );
+      SendEvents( ctx->worker_id[ WORKER_A ], EVENT_RELEASE );
+      SendAndSync( ctx, WORKER_B, EVENT_RELEASE );
+      SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_A_ID, PRIO_HIGH );
+      SetScheduler( ctx->worker_id[ WORKER_C ], SCHEDULER_A_ID, PRIO_HIGH );
+    links: []
+  links: []
+- action-brief: |
     Construct a system state in which a thread is rescheduled  while it is not
     scheduled on another scheduler.
   action-code: |
@@ -776,6 +811,38 @@ test-support: |
     ResumeTask( ctx->runner_id );
   }
 
+  static void Preempt( void *arg )
+  {
+    Context *ctx;
+
+    ctx = arg;
+    MakeBusy( ctx, WORKER_C );
+  }
+
+  static void BlockAndPreempt(
+    void                    *arg,
+    const T_scheduler_event *event,
+    T_scheduler_when         when
+  )
+  {
+    Context *ctx;
+
+    ctx = arg;
+
+    if ( when == T_SCHEDULER_AFTER && event->operation == T_SCHEDULER_BLOCK ) {
+      Thread_Control  *thread;
+
+      T_scheduler_set_event_handler( NULL, NULL );
+
+      thread = GetThread( ctx->worker_id[ WORKER_A ] );
+      T_eq_int( thread->Scheduler.state, THREAD_SCHEDULER_BLOCKED );
+
+      ctx->job_context[ 0 ].handler = Preempt;
+      _Per_CPU_Submit_job( _Per_CPU_Get_by_index( 1 ), &ctx->job[ 0 ] );
+      _Per_CPU_Wait_for_job( _Per_CPU_Get_by_index( 1 ), &ctx->job[ 0 ] );
+    }
+  }
+
   static void PrepareOwnerScheduled( Context *ctx )
   {
     SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_B_ID, PRIO_NORMAL );



More information about the vc mailing list