summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2022-07-04 16:12:53 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2022-07-05 09:26:14 +0200
commit4bae3f03ec895919829d7d1fcdca70f922d194b9 (patch)
tree4d839eac455b87a98496c47efa8c6436504f4730
parentspec: Update due to API changes (diff)
downloadrtems-central-4bae3f03ec895919829d7d1fcdca70f922d194b9.tar.bz2
spec: Specify scheduler detail
-rw-r--r--spec/score/sched/smp/req/reconsider-help-keep-ready.yml18
-rw-r--r--spec/score/sched/smp/val/smp.yml119
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;