summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-11-12 09:09:01 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-11-12 10:15:21 +0100
commit8fbd33c5480ad01b4dc0c17320d8fb409ed6594e (patch)
tree1f9cdc3d9d125b41b65992634a17975db865afe7
parentspec: Use third processor if available (diff)
downloadrtems-central-8fbd33c5480ad01b4dc0c17320d8fb409ed6594e.tar.bz2
spec: Specify an SMP scheduler detail
-rw-r--r--spec/score/sched/smp/req/idle-to-scheduled.yml17
-rw-r--r--spec/score/sched/smp/val/smp.yml100
2 files changed, 115 insertions, 2 deletions
diff --git a/spec/score/sched/smp/req/idle-to-scheduled.yml b/spec/score/sched/smp/req/idle-to-scheduled.yml
new file mode 100644
index 00000000..f2c9ca51
--- /dev/null
+++ b/spec/score/sched/smp/req/idle-to-scheduled.yml
@@ -0,0 +1,17 @@
+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 an idle thread is scheduled on behalf of a thread by the
+ ${/glossary/scheduler-home:/term}, while the thread is not scheduled by
+ another scheduler, when the thread is rescheduled by the home scheduler, the
+ thread shall be scheduled.
+type: requirement
diff --git a/spec/score/sched/smp/val/smp.yml b/spec/score/sched/smp/val/smp.yml
index 7306d187..34da60c6 100644
--- a/spec/score/sched/smp/val/smp.yml
+++ b/spec/score/sched/smp/val/smp.yml
@@ -5,6 +5,40 @@ enabled-by: RTEMS_SMP
links: []
test-actions:
- action-brief: |
+ Construct a system state in which a thread is rescheduled while it is not
+ scheduled on another scheduler.
+ 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 );
+ SendAndSync( ctx, WORKER_A, EVENT_STICKY_OBTAIN );
+ MakeBusy( ctx, WORKER_A );
+ checks:
+ - brief: |
+ Reschedule worker A by the home scheduler while worker A is not scheduled
+ on another scheduler.
+ code: |
+ CallWithinISR( ReadyToScheduled, ctx );
+ links:
+ - role: validation
+ uid: ../req/idle-to-scheduled
+ - brief: |
+ Clean up all used resources.
+ code: |
+ StopBusy( ctx, WORKER_C );
+ StopBusy( ctx, WORKER_A );
+ SendAndSync( ctx, WORKER_A, EVENT_STICKY_RELEASE );
+ 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 an ask for help request is cancelled
while it is processed on another processor.
action-code: |
@@ -420,8 +454,10 @@ test-support: |
typedef enum {
EVENT_OBTAIN = RTEMS_EVENT_0,
EVENT_RELEASE = RTEMS_EVENT_1,
- EVENT_SYNC_RUNNER = RTEMS_EVENT_2,
- EVENT_BUSY = RTEMS_EVENT_3
+ EVENT_STICKY_OBTAIN = RTEMS_EVENT_2,
+ EVENT_STICKY_RELEASE = RTEMS_EVENT_3,
+ EVENT_SYNC_RUNNER = RTEMS_EVENT_4,
+ EVENT_BUSY = RTEMS_EVENT_5
} Event;
static void SendAndSync( Context *ctx, WorkerIndex worker, Event event )
@@ -674,6 +710,58 @@ test-support: |
ResumeTask( ctx->runner_id );
}
+ static void MakeReady( void *arg )
+ {
+ Context *ctx;
+
+ ctx = arg;
+ MakeBusy( ctx, WORKER_C );
+ }
+
+ static void UpdatePriorityMakeReady(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
+ {
+ Context *ctx;
+
+ ctx = arg;
+
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_UPDATE_PRIORITY
+ ) {
+ 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_SCHEDULED );
+
+ ctx->job_context[ 0 ].handler = MakeReady;
+ _Per_CPU_Submit_job( _Per_CPU_Get_by_index( 1 ), &ctx->job[ 0 ] );
+
+ while ( thread->Scheduler.state != THREAD_SCHEDULER_READY ) {
+ RTEMS_COMPILER_MEMORY_BARRIER();
+ }
+ }
+ }
+
+ static void ReadyToScheduled( void *arg )
+ {
+ Context *ctx;
+
+ ctx = arg;
+ SuspendTask( ctx->runner_id );
+
+ T_scheduler_set_event_handler( UpdatePriorityMakeReady, ctx );
+ SetPriority( ctx->worker_id[ WORKER_A ], PRIO_HIGH );
+
+ SetPriority( ctx->runner_id, PRIO_VERY_HIGH );
+ ResumeTask( ctx->runner_id );
+ }
+
static void PrepareOwnerScheduled( Context *ctx )
{
SetScheduler( ctx->worker_id[ WORKER_B ], SCHEDULER_B_ID, PRIO_NORMAL );
@@ -742,6 +830,14 @@ test-support: |
ReleaseMutex( ctx->mutex_id );
}
+ if ( ( events & EVENT_STICKY_OBTAIN ) != 0 ) {
+ ObtainMutex( ctx->sticky_id );
+ }
+
+ if ( ( events & EVENT_STICKY_RELEASE ) != 0 ) {
+ ReleaseMutex( ctx->sticky_id );
+ }
+
if ( ( events & EVENT_BUSY ) != 0 ) {
while ( ctx->busy[ worker ] ) {
/* Wait */