diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2022-07-04 16:12:53 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2022-07-05 09:26:14 +0200 |
commit | 4bae3f03ec895919829d7d1fcdca70f922d194b9 (patch) | |
tree | 4d839eac455b87a98496c47efa8c6436504f4730 | |
parent | spec: Update due to API changes (diff) | |
download | rtems-central-4bae3f03ec895919829d7d1fcdca70f922d194b9.tar.bz2 |
spec: Specify scheduler detail
-rw-r--r-- | spec/score/sched/smp/req/reconsider-help-keep-ready.yml | 18 | ||||
-rw-r--r-- | spec/score/sched/smp/val/smp.yml | 119 |
2 files changed, 135 insertions, 2 deletions
diff --git a/spec/score/sched/smp/req/reconsider-help-keep-ready.yml b/spec/score/sched/smp/req/reconsider-help-keep-ready.yml new file mode 100644 index 00000000..1d8e2ac8 --- /dev/null +++ b/spec/score/sched/smp/req/reconsider-help-keep-ready.yml @@ -0,0 +1,18 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 +copyrights: +- Copyright (C) 2022 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 not a ${/glossary/scheduledtask:/term}, while the thread is + in the set of ${/glossary/readytask:/plural} of an + ${/glossary/scheduler-eligible:/term}, when a help request is reconsidered + for the thread on the scheduler, the thread shall not get removed from the + set of ${/glossary/readytask:/plural} of the scheduler. +type: requirement diff --git a/spec/score/sched/smp/val/smp.yml b/spec/score/sched/smp/val/smp.yml index 5588e739..0054e7d4 100644 --- a/spec/score/sched/smp/val/smp.yml +++ b/spec/score/sched/smp/val/smp.yml @@ -1,6 +1,6 @@ SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause copyrights: -- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) +- Copyright (C) 2021, 2022 embedded brains GmbH (http://www.embedded-brains.de) enabled-by: RTEMS_SMP links: [] test-actions: @@ -421,6 +421,65 @@ test-actions: CleanupOwnerBlocked( ctx ); links: [] links: [] +- action-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. + action-code: | + 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 ); + checks: + - brief: | + Prevent that worker B can perform a post-switch cleanup. + code: | + worker_b = GetThread( ctx->worker_id[ WORKER_B ] ); + _Thread_State_acquire( worker_b, &ctx->lock_context ); + _ISR_lock_ISR_enable( &ctx->lock_context ); + links: [] + - brief: | + 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. + code: | + SetPriority( ctx->worker_id[ WORKER_C ], PRIO_LOW ); + TicketLockWaitForOthers( &worker_b->Join_queue.Queue.Lock, 1 ); + links: [] + - brief: | + 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. + code: | + 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 ); + links: + - role: validation + uid: ../req/reconsider-help-keep-ready + - brief: | + Clean up all used resources. + code: | + 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 ); + links: [] + links: [] test-brief: | Tests SMP-specific scheduler behaviour. test-context: @@ -448,7 +507,17 @@ test-context: This member contains the worker busy status. description: null member: | - volatile bool busy[ WORKER_COUNT ]; + volatile bool busy[ WORKER_COUNT ] +- brief: | + This member contains an ISR lock context. + description: null + member: | + ISR_lock_Context lock_context +- brief: | + This member contains a counter. + description: null + member: | + uint32_t counter - brief: | If this member is true, then the worker shall be in the busy loop. description: null @@ -482,6 +551,7 @@ test-includes: - rtems.h - rtems/test-scheduler.h - rtems/score/percpu.h +- rtems/score/schedulersmp.h - rtems/score/threadimpl.h test-local-includes: - tx-support.h @@ -932,6 +1002,51 @@ test-support: | 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; |