diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-11-12 09:09:01 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-11-12 10:15:21 +0100 |
commit | 8fbd33c5480ad01b4dc0c17320d8fb409ed6594e (patch) | |
tree | 1f9cdc3d9d125b41b65992634a17975db865afe7 | |
parent | spec: Use third processor if available (diff) | |
download | rtems-central-8fbd33c5480ad01b4dc0c17320d8fb409ed6594e.tar.bz2 |
spec: Specify an SMP scheduler detail
-rw-r--r-- | spec/score/sched/smp/req/idle-to-scheduled.yml | 17 | ||||
-rw-r--r-- | spec/score/sched/smp/val/smp.yml | 100 |
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 */ |