summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-08 15:34:05 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-08 15:37:35 +0200
commitc85c24e365acbeb8849dddb0f0ef1d1a00481a69 (patch)
tree7762dd249812b6a85b11658be1d0e76d650b3627
parentspec: Add TQ enqueue priority inherit spec (diff)
downloadrtems-central-c85c24e365acbeb8849dddb0f0ef1d1a00481a69.tar.bz2
spec: Refine TQ surrender priority inherit spec
-rw-r--r--spec/score/mtx/req/surrender.yml14
-rw-r--r--spec/score/tq/req/surrender-mrsp.yml504
-rw-r--r--spec/score/tq/req/surrender-priority-inherit.yml488
3 files changed, 857 insertions, 149 deletions
diff --git a/spec/score/mtx/req/surrender.yml b/spec/score/mtx/req/surrender.yml
index 5d1749e5..fd31ad29 100644
--- a/spec/score/mtx/req/surrender.yml
+++ b/spec/score/mtx/req/surrender.yml
@@ -7,6 +7,8 @@ links:
- role: function-implementation
uid: /score/tq/req/surrender
- role: function-implementation
+ uid: /score/tq/req/surrender-mrsp
+- role: function-implementation
uid: /score/tq/req/surrender-priority-inherit
- role: requirement-refinement
uid: ../if/group
@@ -85,7 +87,14 @@ post-conditions:
${../../tq/req/surrender-priority-inherit:/test-run}( &ctx->tq_ctx->base );
text: |
The thread queue of the mutex shall be surrendered in priority order
- priority inheritance.
+ with priority inheritance.
+ - name: MrsP
+ test-code: |
+ T_eq_u32( ctx->counter, 1 );
+ ${../../tq/req/surrender-mrsp:/test-run}( &ctx->tq_ctx->base );
+ text: |
+ The thread queue of the mutex shall be surrendered in priority order
+ with MrsP.
test-epilogue: null
test-prologue: null
- name: Priority
@@ -367,6 +376,7 @@ test-includes: []
test-local-includes:
- tr-mtx-surrender.h
- tr-tq-surrender.h
+- tr-tq-surrender-mrsp.h
- tr-tq-surrender-priority-inherit.h
test-prepare: |
ctx->owner_caller = false;
@@ -588,7 +598,7 @@ transition-map:
Owner: First
- pre-conditions:
Protocol: MrsP
- then: PriorityInherit
+ then: MrsP
- if:
post-conditions:
Owner: First
diff --git a/spec/score/tq/req/surrender-mrsp.yml b/spec/score/tq/req/surrender-mrsp.yml
new file mode 100644
index 00000000..6b0c26ab
--- /dev/null
+++ b/spec/score/tq/req/surrender-mrsp.yml
@@ -0,0 +1,504 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+functional-type: action
+links:
+- role: requirement-refinement
+ uid: ../if/group
+post-conditions:
+- name: Dequeue
+ states:
+ - name: Priority
+ test-code: |
+ /* Validation is done by spec:/score/tq/req/enqueue-priority */
+ text: |
+ The first thread in priority order shall be dequeued from the thread
+ queue.
+ test-epilogue: null
+ test-prologue: null
+- name: Unblock
+ states:
+ - name: 'No'
+ test-code: |
+ T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ text: |
+ The dequeued thread shall not be unblocked by the thread queue surrender
+ operation.
+ test-epilogue: null
+ test-prologue: |
+ size_t i;
+
+ i = 0;
+- name: PreviousOwnerPriority
+ states:
+ - name: Drop
+ test-code: |
+ T_eq_u32( ctx->priority_after, PRIO_NORMAL );
+ text: |
+ Each ${/glossary/priority-eligible:/term} of the previous owner which had
+ the highest priority inherited through the thread queue shall be updated.
+ - name: Nop
+ test-code: |
+ T_eq_u32( ctx->priority_after, ctx->priority_before );
+ text: |
+ No ${/glossary/priority-eligible:/term} of the previous owner shall be
+ updated.
+ test-epilogue: null
+ test-prologue: null
+- name: RemoveHelper
+ states:
+ - name: 'Yes'
+ test-code: |
+ sc = rtems_task_get_priority(
+ ctx->previous_owner,
+ SCHEDULER_B_ID,
+ &priority
+ );
+ T_rsc( sc, RTEMS_NOT_DEFINED );
+ text: |
+ Each ${/glossary/scheduler-helping:/term} of the previous owner which was
+ only available due to a priority inherited through the thread queue shall
+ be removed from the previous owner.
+ - name: 'No'
+ test-code: |
+ sc = rtems_task_get_priority(
+ ctx->previous_owner,
+ SCHEDULER_B_ID,
+ &priority
+ );
+ #if defined(RTEMS_SMP)
+ T_rsc_success( sc );
+
+ if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
+ T_eq_u32( priority, PRIO_LOW );
+ } else {
+ T_eq_u32( priority, PRIO_HIGH );
+ }
+ #else
+ T_rsc( sc, RTEMS_INVALID_ID );
+ #endif
+ text: |
+ No ${/glossary/scheduler-helping:/term} shall be removed from the
+ previous owner.
+ test-epilogue: null
+ test-prologue: |
+ rtems_status_code sc;
+ rtems_task_priority priority;
+- name: AddHelper
+ states:
+ - name: 'Yes'
+ test-code: |
+ sc = rtems_task_get_priority(
+ ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
+ SCHEDULER_A_ID,
+ &priority
+ );
+ T_rsc_success( sc );
+
+ if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
+ T_eq_u32( priority, PRIO_VERY_HIGH );
+ } else {
+ T_eq_u32( priority, PRIO_LOW );
+ }
+ text: |
+ Each ${/glossary/scheduler-helping:/term} of the new owner which is only
+ available due to a priority inherited through the thread queue shall be
+ added to the new owner.
+ - name: 'No'
+ test-code: |
+ sc = rtems_task_get_priority(
+ ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
+ SCHEDULER_A_ID,
+ &priority
+ );
+ #if defined(RTEMS_SMP)
+ T_rsc( sc, RTEMS_NOT_DEFINED );
+ #else
+ T_rsc_success( sc );
+ T_eq_u32( priority, PRIO_HIGH );
+ #endif
+ text: |
+ No ${/glossary/scheduler-helping:/term} shall added to the new owner.
+ test-epilogue: null
+ test-prologue: |
+ rtems_status_code sc;
+ rtems_task_priority priority;
+- name: Suspended
+ states:
+ - name: 'Yes'
+ test-code: |
+ T_true( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
+ text: |
+ The new owner shall be suspended.
+ - name: 'No'
+ test-code: |
+ T_false( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
+ text: |
+ The new owner shall be not suspended.
+ test-epilogue: null
+ test-prologue: null
+pre-conditions:
+- name: InheritedPriority
+ states:
+ - name: Vital
+ test-code: |
+ ctx->inherited_priorities_are_dispensible = false;
+ text: |
+ While at least one priority inherited through the thread queue for the
+ previous owner is the highest priority of the previous owner.
+ - name: Dispensable
+ test-code: |
+ ctx->inherited_priorities_are_dispensible = true;
+ text: |
+ While all priorities inherited through the thread queue for the previous
+ owner are not the highest priority of the previous owner.
+ test-epilogue: null
+ test-prologue: null
+- name: PreviousHelping
+ states:
+ - name: Vital
+ test-code: |
+ ctx->helping_schedules_are_dispensible = false;
+ text: |
+ While at least one ${/glossary/scheduler-helping:/term} of the previous
+ owner is only available due to a priority inherited through the thread
+ queue.
+ - name: Dispensable
+ test-code: |
+ ctx->helping_schedules_are_dispensible = true;
+ text: |
+ While all ${/glossary/scheduler-helping:/term} of the previous owner are
+ not only available due to a priority inherited through the thread queue.
+ test-epilogue: null
+ test-prologue: null
+- name: Scheduler
+ states:
+ - name: Home
+ test-code: |
+ ctx->use_helping_scheduler = false;
+ text: |
+ While the previous owner executes in its
+ ${/glossary/scheduler-home:/term}.
+ - name: Helping
+ test-code: |
+ ctx->use_helping_scheduler = true;
+ text: |
+ While the previous owner executes in a
+ ${/glossary/scheduler-helping:/term} which is available due to a priority
+ inherited through the thread queue.
+ test-epilogue: null
+ test-prologue: null
+- name: NewHelping
+ states:
+ - name: Vital
+ test-code: |
+ ctx->gains_new_helping_scheduler = true;
+ text: |
+ While at least one ${/glossary/scheduler-helping:/term} of the new owner
+ is only available due to a priority inherited through the thread queue.
+ - name: Dispensable
+ test-code: |
+ ctx->gains_new_helping_scheduler = false;
+ text: |
+ While all ${/glossary/scheduler-helping:/term} of the new owner are not
+ only available due to a priority inherited through the thread queue.
+ test-epilogue: null
+ test-prologue: null
+- name: Suspended
+ states:
+ - name: 'Yes'
+ test-code: |
+ ctx->suspended = true;
+ text: |
+ Whiel the new owner is suspended.
+ - name: 'No'
+ test-code: |
+ ctx->suspended = false;
+ text: |
+ Whiel the new owner is not suspended.
+ test-epilogue: null
+ test-prologue: null
+- name: WaitState
+ states:
+ - name: IntendToBlock
+ test-code: |
+ ctx->intend_to_block = true;
+ text: |
+ While the new owner is in the intend to block wait
+ state.
+ test-epilogue: null
+ test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons: {}
+test-action: |
+ ctx->previous_owner = ctx->tq_ctx->worker_id[ TQ_HELPER_A ];
+
+ SetSelfPriority( PRIO_LOW );
+
+ if (
+ ctx->inherited_priorities_are_dispensible ||
+ ctx->helping_schedules_are_dispensible
+ ) {
+ TQSend( ctx->tq_ctx, TQ_HELPER_A, TQ_EVENT_MUTEX_A_OBTAIN );
+
+ if ( ctx->inherited_priorities_are_dispensible ) {
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_OBTAIN );
+ }
+
+ if ( ctx->helping_schedules_are_dispensible ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ TQ_BLOCKER_C,
+ TQ_EVENT_MUTEX_A_OBTAIN
+ );
+ }
+ }
+
+ /*
+ * Take only the priorities into account which are inherited from the
+ * priority inheritance mutex. This avoids having to deal with the ceiling
+ * priority.
+ */
+ ctx->priority_before = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
+
+ SetSelfScheduler( SCHEDULER_B_ID, PRIO_ULTRA_HIGH );
+ ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = true;
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_HELPER_A,
+ TQ_EVENT_ENQUEUE | TQ_EVENT_BUSY_WAIT
+ );
+ SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
+
+ TQSendAndWaitForIntendToBlock(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_ENQUEUE
+ );
+
+ SetSelfScheduler( SCHEDULER_B_ID, PRIO_ULTRA_HIGH );
+
+ if ( ctx->gains_new_helping_scheduler ) {
+ TQSend(
+ ctx->tq_ctx,
+ TQ_BLOCKER_D,
+ TQ_EVENT_ENQUEUE
+ );
+ YieldTask( ctx->tq_ctx->worker_id[ TQ_HELPER_A ] );
+ TQWaitForEventsReceived( ctx->tq_ctx, TQ_BLOCKER_D );
+ TQWaitForIntendToBlock( ctx->tq_ctx, TQ_BLOCKER_D );
+ YieldTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_D ] );
+ }
+
+ if ( ctx->use_helping_scheduler ) {
+ SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
+ }
+
+ if ( ctx->suspended ) {
+ SuspendTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ }
+
+ ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = false;
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ TQ_HELPER_A,
+ TQ_EVENT_SCHEDULER_RECORD_START |
+ TQ_EVENT_SURRENDER
+ );
+ TQSchedulerRecordStop( ctx->tq_ctx );
+ T_eq_ptr(
+ TQGetOwner( ctx->tq_ctx ),
+ ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]
+ );
+ ctx->priority_after = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
+test-brief: null
+test-cleanup: |
+ SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
+
+ if ( ctx->suspended ) {
+ ResumeTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ }
+
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_SURRENDER
+ );
+
+ if ( ctx->gains_new_helping_scheduler ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_BLOCKER_D,
+ TQ_EVENT_SURRENDER
+ );
+ }
+
+ if (
+ ctx->inherited_priorities_are_dispensible ||
+ ctx->helping_schedules_are_dispensible
+ ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_HELPER_A,
+ TQ_EVENT_MUTEX_A_RELEASE
+ );
+
+ if ( ctx->inherited_priorities_are_dispensible ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_BLOCKER_B,
+ TQ_EVENT_MUTEX_A_RELEASE
+ );
+ }
+
+ if ( ctx->helping_schedules_are_dispensible ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ TQ_BLOCKER_C,
+ TQ_EVENT_MUTEX_A_RELEASE
+ );
+ }
+ }
+
+ T_eq_u32( rtems_scheduler_get_processor(), 0 );
+test-context:
+- brief: |
+ If this member is true, then all priorities of the previous owner inherited
+ from the thread queue thread shall be dispensable.
+ description: null
+ member: |
+ bool inherited_priorities_are_dispensible
+- brief: |
+ If this member is true, then all helping schedulers of the previous owner
+ thread gained through the thread queue shall be dispensable.
+ description: null
+ member: |
+ bool helping_schedules_are_dispensible
+- brief: |
+ If this member is true, then the previous owner thread shall use helping
+ scheduler.
+ description: null
+ member: |
+ bool use_helping_scheduler
+- brief: |
+ If this member is true, then the new owner thread shall gain a vital
+ helping scheduler.
+ description: null
+ member: |
+ bool gains_new_helping_scheduler
+- brief: |
+ If this member is true, then the new owner thread shall be suspended.
+ description: null
+ member: |
+ bool suspended
+- brief: |
+ If this member is true, then the new owner thread shall be in the intend to
+ block wait state.
+ description: null
+ member: |
+ bool intend_to_block
+- brief: |
+ This member contains the current priority of the previous owner thread
+ before the thread queue surrender operation.
+ description: null
+ member: |
+ rtems_task_priority priority_before
+- brief: |
+ This member contains the current priority of the previous owner thread
+ after the thread queue surrender operation.
+ description: null
+ member: |
+ rtems_task_priority priority_after
+- brief: |
+ This member contains the identifier of the previous owner thread.
+ description: null
+ member: |
+ rtems_id previous_owner
+test-context-support: null
+test-description: null
+test-header:
+ code: null
+ freestanding: false
+ includes: []
+ local-includes:
+ - tx-thread-queue.h
+ run-params:
+ - description: |
+ is the thread queue test context.
+ dir: inout
+ name: tq_ctx
+ specifier: TQContext *${.:name}
+ target: testsuites/validation/tr-tq-surrender-mrsp.h
+test-includes:
+- rtems/score/threadimpl.h
+test-local-includes:
+- tx-support.h
+- tr-tq-surrender-mrsp.h
+test-prepare: |
+ ctx->inherited_priorities_are_dispensible = true;
+ ctx->helping_schedules_are_dispensible = true;
+ ctx->use_helping_scheduler = false;
+ ctx->gains_new_helping_scheduler = false;
+ ctx->intend_to_block = false;
+test-setup:
+ brief: null
+ code: |
+ TQReset( ctx->tq_ctx );
+ TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, SCHEDULER_B_ID, PRIO_NORMAL );
+ TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B, PRIO_VERY_HIGH );
+ TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_C, SCHEDULER_B_ID, PRIO_LOW );
+ TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_VERY_HIGH );
+ TQSetPriority( ctx->tq_ctx, TQ_HELPER_A, PRIO_NORMAL );
+ description: null
+test-stop: null
+test-support: |
+ typedef ${.:/test-context-type} Context;
+
+ static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
+ {
+ return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
+ }
+test-target: testsuites/validation/tr-tq-surrender-mrsp.c
+test-teardown:
+ brief: null
+ code: |
+ SetSelfScheduler( SCHEDULER_A_ID, PRIO_NORMAL );
+ description: null
+text: |
+ When the thread queue enqueue operation timed out.
+transition-map:
+- enabled-by: true
+ post-conditions:
+ Dequeue: Priority
+ Unblock: 'No'
+ RemoveHelper:
+ - if:
+ pre-conditions:
+ PreviousHelping: Dispensable
+ then: 'No'
+ - else: 'Yes'
+ AddHelper:
+ - if:
+ pre-conditions:
+ NewHelping: Dispensable
+ then: 'No'
+ - else: 'Yes'
+ PreviousOwnerPriority:
+ - if:
+ pre-conditions:
+ InheritedPriority: Vital
+ then: Drop
+ - else: Nop
+ Suspended:
+ - specified-by: Suspended
+ pre-conditions:
+ InheritedPriority: all
+ PreviousHelping: all
+ Scheduler: all
+ NewHelping: all
+ Suspended: all
+ WaitState: all
+type: requirement
diff --git a/spec/score/tq/req/surrender-priority-inherit.yml b/spec/score/tq/req/surrender-priority-inherit.yml
index 2ec5871a..40d203f3 100644
--- a/spec/score/tq/req/surrender-priority-inherit.yml
+++ b/spec/score/tq/req/surrender-priority-inherit.yml
@@ -21,7 +21,7 @@ post-conditions:
states:
- name: 'Yes'
test-code: |
- T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
+ T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, NEW_OWNER ) );
T_eq_ptr( GetUnblock( ctx, &i ), NULL );
text: |
The dequeued thread shall be unblocked by the thread queue surrender
@@ -53,6 +53,46 @@ post-conditions:
updated.
test-epilogue: null
test-prologue: null
+- name: NewPriority
+ states:
+ - name: Raise
+ test-code: |
+ sc = rtems_task_get_priority(
+ ctx->tq_ctx->worker_id[ NEW_OWNER ],
+ SCHEDULER_A_ID,
+ &priority
+ );
+ T_rsc_success( sc );
+ T_eq_u32( priority, PRIO_LOW );
+ text: |
+ Each ${/glossary/priority-eligible:/term} of the new owner which
+ inherited the highest priority through the thread queue shall be updated.
+ - name: Nop
+ test-code: |
+ if ( ctx->gains_new_helping_scheduler ) {
+ scheduler_id = SCHEDULER_C_ID;
+ } else {
+ scheduler_id = SCHEDULER_A_ID;
+ }
+
+ sc = rtems_task_get_priority(
+ ctx->tq_ctx->worker_id[ NEW_OWNER ],
+ scheduler_id,
+ &priority
+ );
+ #if defined(RTEMS_SMP)
+ T_rsc( sc, RTEMS_NOT_DEFINED );
+ #else
+ T_rsc_success( sc );
+ T_eq_u32( priority, PRIO_HIGH );
+ #endif
+ text: |
+ No highest priority of the new owner shall be changed.
+ test-epilogue: null
+ test-prologue: |
+ rtems_id scheduler_id;
+ rtems_task_priority priority;
+ rtems_status_code sc;
- name: RemoveHelper
states:
- name: 'Yes'
@@ -90,15 +130,21 @@ post-conditions:
previous owner.
test-epilogue: null
test-prologue: |
- rtems_status_code sc;
rtems_task_priority priority;
+ rtems_status_code sc;
- name: AddHelper
states:
- name: 'Yes'
test-code: |
+ if ( ctx->gains_new_priority ) {
+ scheduler_id = SCHEDULER_C_ID;
+ } else {
+ scheduler_id = SCHEDULER_A_ID;
+ }
+
sc = rtems_task_get_priority(
- ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
- SCHEDULER_A_ID,
+ ctx->tq_ctx->worker_id[ NEW_OWNER ],
+ scheduler_id,
&priority
);
T_rsc_success( sc );
@@ -114,9 +160,15 @@ post-conditions:
added to the new owner.
- name: 'No'
test-code: |
+ if ( ctx->gains_new_priority ) {
+ scheduler_id = SCHEDULER_C_ID;
+ } else {
+ scheduler_id = SCHEDULER_A_ID;
+ }
+
sc = rtems_task_get_priority(
- ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ],
- SCHEDULER_A_ID,
+ ctx->tq_ctx->worker_id[ NEW_OWNER ],
+ scheduler_id,
&priority
);
#if defined(RTEMS_SMP)
@@ -129,39 +181,47 @@ post-conditions:
No ${/glossary/scheduler-helping:/term} shall added to the new owner.
test-epilogue: null
test-prologue: |
- rtems_status_code sc;
+ rtems_id scheduler_id;
rtems_task_priority priority;
+ rtems_status_code sc;
- name: Suspended
states:
- name: 'Yes'
test-code: |
- T_true( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
+ T_true( IsTaskSuspended( ctx->tq_ctx->worker_id[ NEW_OWNER ] ) );
text: |
The new owner shall be suspended.
- name: 'No'
test-code: |
- T_false( IsTaskSuspended( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] ) );
+ T_false( IsTaskSuspended( ctx->tq_ctx->worker_id[ NEW_OWNER ] ) );
text: |
The new owner shall be not suspended.
test-epilogue: null
test-prologue: null
pre-conditions:
-- name: EnqueueVariant
+- name: SchedulerCount
states:
- - name: Blocking
+ - name: One
+ test-code: |
+ if ( rtems_scheduler_get_processor_maximum() != 1 ) {
+ ${.:skip}
+ }
+ text: |
+ Where the system has exactly one schedulers.
+ - name: Two
test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_BLOCKS ) {
+ if ( rtems_scheduler_get_processor_maximum() != 2 ) {
${.:skip}
}
text: |
- Where the thread queue enqueue operation is blocking.
- - name: Sticky
+ Where the system has exactly two schedulers.
+ - name: More
test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_STICKY ) {
+ if ( rtems_scheduler_get_processor_maximum() < 3 ) {
${.:skip}
}
text: |
- Where the thread queue enqueue operation is sticky.
+ Where the system has at least three schedulers.
test-epilogue: null
test-prologue: null
- name: InheritedPriority
@@ -197,7 +257,7 @@ pre-conditions:
not only available due to a priority inherited through the thread queue.
test-epilogue: null
test-prologue: null
-- name: Scheduler
+- name: UsedScheduler
states:
- name: Home
test-code: |
@@ -214,6 +274,22 @@ pre-conditions:
inherited through the thread queue.
test-epilogue: null
test-prologue: null
+- name: NewPriority
+ states:
+ - name: Vital
+ test-code: |
+ ctx->gains_new_priority = true;
+ text: |
+ While at least one highest priority of the new owner is only available
+ due to a priority inherited through the thread queue.
+ - name: Dispensable
+ test-code: |
+ ctx->gains_new_priority = false;
+ text: |
+ While all highest priorities of the new owner are not only available due
+ to a priority inherited through the thread queue.
+ test-epilogue: null
+ test-prologue: null
- name: NewHelping
states:
- name: Vital
@@ -263,15 +339,18 @@ rationale: null
references: []
requirement-type: functional
skip-reasons:
- StickyHasNoBlocking: |
- When a sticky thread queue enqueue operation is performed, the blocked wait
- state cannot occur.
- OnlyOneCPU: |
+ NeedsSecondCPUForIntentToBlock: |
Where the system was built with SMP support disabled, exactly one scheduler
is present in an application using exactly one processor. There is at most
one executing thread. Thread queues with an owner can only be surrendered
by the previous owner. Thus, the new owner of the thread queue cannot be
in the intend to block wait state.
+ NeedsSecondScheduler: |
+ A second scheduler is required to get a
+ ${/glossary/scheduler-helping:/term}.
+ NeedsThirdScheduler: |
+ A third scheduler is required to get a vital scheduler and a vital priority
+ for the new owner at the same time.
test-action: |
if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
ActionSticky( ctx );
@@ -318,6 +397,12 @@ test-context:
bool use_helping_scheduler
- brief: |
If this member is true, then the new owner thread shall gain a vital
+ priority.
+ description: null
+ member: |
+ bool gains_new_priority
+- brief: |
+ If this member is true, then the new owner thread shall gain a vital
helping scheduler.
description: null
member: |
@@ -381,6 +466,7 @@ test-prepare: |
ctx->inherited_priorities_are_dispensible = true;
ctx->helping_schedules_are_dispensible = true;
ctx->use_helping_scheduler = false;
+ ctx->gains_new_priority = false;
ctx->gains_new_helping_scheduler = false;
ctx->intend_to_block = false;
test-setup:
@@ -399,6 +485,24 @@ test-stop: null
test-support: |
typedef ${.:/test-context-type} Context;
+ #define NEW_OWNER TQ_BLOCKER_A
+
+ #define PREV_OWNER_HELPER_A TQ_BLOCKER_B
+
+ #define PREV_OWNER_HELPER_B TQ_BLOCKER_C
+
+ #define PREV_OWNER_HELPER_C TQ_BLOCKER_D
+
+ #define NEW_OWNER_NEW_HELPER TQ_BLOCKER_E
+
+ #define NEW_OWNER_NEW_PRIORITY TQ_WORKER_F
+
+ #define NEW_OWNER_OLD_PRIORITY TQ_HELPER_C
+
+ #define PREV_OWNER_MOVER TQ_HELPER_A
+
+ #define PREV_OWNER TQ_HELPER_A
+
static const rtems_tcb *GetUnblock( Context *ctx, size_t *index )
{
return TQGetNextUnblock( ctx->tq_ctx, index )->thread;
@@ -414,7 +518,7 @@ test-support: |
Status_Control status;
if ( ctx->suspended ) {
- SuspendTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ SuspendTask( ctx->tq_ctx->worker_id[ NEW_OWNER ] );
}
ctx->priority_before = GetSelfPriority();
@@ -422,7 +526,7 @@ test-support: |
status = TQSurrender( ctx->tq_ctx );
T_eq_int( status, TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL ) );
TQSchedulerRecordStop( ctx->tq_ctx );
- T_eq_ptr( TQGetOwner( ctx->tq_ctx ), ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ] );
+ T_eq_ptr( TQGetOwner( ctx->tq_ctx ), ctx->tq_ctx->worker_tcb[ NEW_OWNER ] );
ctx->priority_after = GetSelfPriority();
}
@@ -466,17 +570,33 @@ test-support: |
static void Setup( Context *ctx )
{
#if defined(RTEMS_SMP)
- TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, SCHEDULER_B_ID, PRIO_NORMAL );
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B, PRIO_VERY_HIGH );
- TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_C, SCHEDULER_B_ID, PRIO_HIGH );
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_LOW );
- TQSetPriority( ctx->tq_ctx, TQ_HELPER_A, PRIO_ULTRA_HIGH );
+ TQSetScheduler( ctx->tq_ctx, NEW_OWNER, SCHEDULER_B_ID, PRIO_NORMAL );
+ TQSetPriority( ctx->tq_ctx, PREV_OWNER_HELPER_A, PRIO_VERY_HIGH );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ PREV_OWNER_HELPER_B,
+ SCHEDULER_B_ID,
+ PRIO_HIGH
+ );
+ TQSetPriority( ctx->tq_ctx, NEW_OWNER_OLD_PRIORITY, PRIO_VERY_LOW );
+ TQSetPriority( ctx->tq_ctx, NEW_OWNER_NEW_PRIORITY, PRIO_LOW );
+
+ TQSetPriority( ctx->tq_ctx, PREV_OWNER_MOVER, PRIO_ULTRA_HIGH );
+
+ if ( rtems_scheduler_get_processor_maximum() >= 3 ) {
+ TQSetScheduler(
+ ctx->tq_ctx,
+ PREV_OWNER_HELPER_C,
+ SCHEDULER_C_ID,
+ PRIO_HIGH
+ );
+ }
#else
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_A, PRIO_HIGH );
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B, PRIO_HIGH );
+ TQSetPriority( ctx->tq_ctx, NEW_OWNER, PRIO_HIGH );
+ TQSetPriority( ctx->tq_ctx, PREV_OWNER_HELPER_A, PRIO_HIGH );
#endif
- TQSetPriority( ctx->tq_ctx, TQ_HELPER_B, PRIO_VERY_LOW );
+ TQSetPriority( ctx->tq_ctx, TQ_HELPER_B, PRIO_ULTRA_LOW );
}
static void Action( Context *ctx )
@@ -488,29 +608,40 @@ test-support: |
ctx->action_performed = true;
ctx->previous_owner = ctx->tq_ctx->runner_id;
-
- if (
- ctx->inherited_priorities_are_dispensible
+ TQMutexObtain( ctx->tq_ctx, TQ_MUTEX_A );
#if defined(RTEMS_SMP)
- || ctx->helping_schedules_are_dispensible
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ NEW_OWNER,
+ TQ_EVENT_MUTEX_B_OBTAIN
+ );
#endif
- ) {
- TQMutexObtain( ctx->tq_ctx, TQ_MUTEX_A );
- if ( ctx->inherited_priorities_are_dispensible ) {
- TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_OBTAIN );
- }
+ if ( ctx->inherited_priorities_are_dispensible ) {
+ TQSend(
+ ctx->tq_ctx,
+ PREV_OWNER_HELPER_A,
+ TQ_EVENT_MUTEX_A_OBTAIN | TQ_EVENT_MUTEX_A_RELEASE
+ );
+ }
#if defined(RTEMS_SMP)
- if ( ctx->helping_schedules_are_dispensible ) {
+ if ( ctx->helping_schedules_are_dispensible ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ PREV_OWNER_HELPER_B,
+ TQ_EVENT_MUTEX_A_OBTAIN | TQ_EVENT_MUTEX_A_RELEASE
+ );
+
+ if ( ctx->gains_new_priority && ctx->gains_new_helping_scheduler ) {
TQSendAndWaitForExecutionStop(
ctx->tq_ctx,
- TQ_BLOCKER_C,
- TQ_EVENT_MUTEX_A_OBTAIN
+ PREV_OWNER_HELPER_C,
+ TQ_EVENT_MUTEX_A_OBTAIN | TQ_EVENT_MUTEX_A_RELEASE
);
}
- #endif
}
+ #endif
status = TQEnqueue( ctx->tq_ctx, TQ_NO_WAIT );
T_eq_int( status, TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL ) );
@@ -521,23 +652,56 @@ test-support: |
_SMP_barrier_State_initialize( &state );
T_scheduler_set_event_handler( SchedulerBlock, ctx );
- TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
+ TQSend( ctx->tq_ctx, NEW_OWNER, TQ_EVENT_ENQUEUE );
/* B0 */
_SMP_barrier_Wait( &ctx->barrier, &state, 2 );
} else {
TQSendAndWaitForExecutionStop(
ctx->tq_ctx,
- TQ_BLOCKER_A,
+ NEW_OWNER,
TQ_EVENT_ENQUEUE
);
}
- if ( ctx->gains_new_helping_scheduler ) {
+ if ( ctx->gains_new_priority ) {
+ TQSend(
+ ctx->tq_ctx,
+ NEW_OWNER_OLD_PRIORITY,
+ TQ_EVENT_HELPER_B_SYNC | TQ_EVENT_MUTEX_B_OBTAIN
+ );
+ TQSynchronizeRunner();
+ TQSend(
+ ctx->tq_ctx,
+ NEW_OWNER_NEW_PRIORITY,
+ TQ_EVENT_HELPER_B_SYNC | TQ_EVENT_ENQUEUE
+ );
+ TQSynchronizeRunner();
+
+ if ( ctx->gains_new_helping_scheduler ) {
+ TQSetScheduler(
+ ctx->tq_ctx,
+ NEW_OWNER_NEW_HELPER,
+ SCHEDULER_C_ID,
+ PRIO_LOW
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ NEW_OWNER_NEW_HELPER,
+ TQ_EVENT_ENQUEUE
+ );
+ }
+ } else if ( ctx->gains_new_helping_scheduler ) {
+ TQSetScheduler(
+ ctx->tq_ctx,
+ NEW_OWNER_NEW_HELPER,
+ SCHEDULER_A_ID,
+ PRIO_LOW
+ );
TQSend(
ctx->tq_ctx,
- TQ_BLOCKER_D,
- TQ_EVENT_ENQUEUE | TQ_EVENT_HELPER_B_SYNC
+ NEW_OWNER_NEW_HELPER,
+ TQ_EVENT_HELPER_B_SYNC | TQ_EVENT_ENQUEUE
);
TQSynchronizeRunner();
}
@@ -547,20 +711,20 @@ test-support: |
* wait state, we would need at least three processors. Skip it for now.
*/
if ( ctx->use_helping_scheduler && !ctx->intend_to_block ) {
- ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = true;
- TQSend( ctx->tq_ctx, TQ_HELPER_A, TQ_EVENT_BUSY_WAIT );
+ ctx->tq_ctx->busy_wait[ PREV_OWNER_MOVER ] = true;
+ TQSend( ctx->tq_ctx, PREV_OWNER_MOVER, TQ_EVENT_BUSY_WAIT );
while ( rtems_scheduler_get_processor() != 1 ) {
/* Wait */
}
- ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = false;
+ ctx->tq_ctx->busy_wait[ PREV_OWNER_MOVER ] = false;
}
#else
TQSend(
ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE | TQ_EVENT_HELPER_B_SYNC
+ NEW_OWNER,
+ TQ_EVENT_HELPER_B_SYNC | TQ_EVENT_ENQUEUE
);
TQSynchronizeRunner();
#endif
@@ -578,48 +742,48 @@ test-support: |
static void Cleanup( Context *ctx )
{
if ( ctx->suspended ) {
- ResumeTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ ResumeTask( ctx->tq_ctx->worker_id[ NEW_OWNER ] );
}
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_A,
+ NEW_OWNER,
TQ_EVENT_SURRENDER
);
- TQWaitForExecutionStop( ctx->tq_ctx, TQ_BLOCKER_A );
+ TQWaitForExecutionStop( ctx->tq_ctx, NEW_OWNER );
#if defined(RTEMS_SMP)
- if ( ctx->gains_new_helping_scheduler ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ NEW_OWNER,
+ TQ_EVENT_MUTEX_B_RELEASE
+ );
+
+ if ( ctx->gains_new_priority ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ NEW_OWNER_OLD_PRIORITY,
+ TQ_EVENT_MUTEX_B_RELEASE
+ );
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_D,
+ NEW_OWNER_NEW_PRIORITY,
TQ_EVENT_SURRENDER
);
}
- #endif
- if (
- ctx->inherited_priorities_are_dispensible
- #if defined(RTEMS_SMP)
- || ctx->helping_schedules_are_dispensible
+ if ( ctx->gains_new_helping_scheduler ) {
+ TQSendAndSynchronizeRunner(
+ ctx->tq_ctx,
+ NEW_OWNER_NEW_HELPER,
+ TQ_EVENT_SURRENDER
+ );
+ }
#endif
- ) {
- TQMutexRelease( ctx->tq_ctx, TQ_MUTEX_A );
-
- if ( ctx->inherited_priorities_are_dispensible ) {
- TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_RELEASE );
- }
- #if defined(RTEMS_SMP)
- if ( ctx->helping_schedules_are_dispensible ) {
- TQSendAndWaitForExecutionStop(
- ctx->tq_ctx,
- TQ_BLOCKER_C,
- TQ_EVENT_MUTEX_A_RELEASE
- );
- }
- #endif
- }
+ TQMutexRelease( ctx->tq_ctx, TQ_MUTEX_A );
+ TQMutexObtain( ctx->tq_ctx, TQ_MUTEX_A );
+ TQMutexRelease( ctx->tq_ctx, TQ_MUTEX_A );
T_eq_u32( rtems_scheduler_get_processor(), 0 );
}
@@ -627,11 +791,15 @@ test-support: |
static void SetupSticky( Context *ctx )
{
#if defined(RTEMS_SMP)
- TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_A, SCHEDULER_B_ID, PRIO_NORMAL );
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_B, PRIO_VERY_HIGH );
- TQSetScheduler( ctx->tq_ctx, TQ_BLOCKER_C, SCHEDULER_B_ID, PRIO_LOW );
- TQSetPriority( ctx->tq_ctx, TQ_BLOCKER_D, PRIO_VERY_HIGH );
- TQSetPriority( ctx->tq_ctx, TQ_HELPER_A, PRIO_NORMAL );
+ TQSetScheduler( ctx->tq_ctx, NEW_OWNER, SCHEDULER_B_ID, PRIO_NORMAL );
+ TQSetPriority( ctx->tq_ctx, PREV_OWNER_HELPER_A, PRIO_VERY_HIGH );
+ TQSetScheduler( ctx->tq_ctx,
+ PREV_OWNER_HELPER_B,
+ SCHEDULER_B_ID,
+ PRIO_LOW
+ );
+ TQSetPriority( ctx->tq_ctx, NEW_OWNER_NEW_HELPER, PRIO_VERY_HIGH );
+ TQSetPriority( ctx->tq_ctx, PREV_OWNER, PRIO_NORMAL );
#endif
}
@@ -639,7 +807,7 @@ test-support: |
{
#if defined(RTEMS_SMP)
ctx->action_performed = true;
- ctx->previous_owner = ctx->tq_ctx->worker_id[ TQ_HELPER_A ];
+ ctx->previous_owner = ctx->tq_ctx->worker_id[ PREV_OWNER ];
SetSelfPriority( PRIO_LOW );
@@ -647,16 +815,16 @@ test-support: |
ctx->inherited_priorities_are_dispensible ||
ctx->helping_schedules_are_dispensible
) {
- TQSend( ctx->tq_ctx, TQ_HELPER_A, TQ_EVENT_MUTEX_A_OBTAIN );
+ TQSend( ctx->tq_ctx, PREV_OWNER, TQ_EVENT_MUTEX_A_OBTAIN );
if ( ctx->inherited_priorities_are_dispensible ) {
- TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_OBTAIN );
+ TQSend( ctx->tq_ctx, PREV_OWNER_HELPER_A, TQ_EVENT_MUTEX_A_OBTAIN );
}
if ( ctx->helping_schedules_are_dispensible ) {
TQSendAndWaitForExecutionStop(
ctx->tq_ctx,
- TQ_BLOCKER_C,
+ PREV_OWNER_HELPER_B,
TQ_EVENT_MUTEX_A_OBTAIN
);
}
@@ -667,20 +835,20 @@ test-support: |
* priority inheritance mutex. This avoids having to deal with the ceiling
* priority.
*/
- ctx->priority_before = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
+ ctx->priority_before = TQGetPriority( ctx->tq_ctx, PREV_OWNER );
SetSelfScheduler( SCHEDULER_B_ID, PRIO_ULTRA_HIGH );
- ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = true;
+ ctx->tq_ctx->busy_wait[ PREV_OWNER ] = true;
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_HELPER_A,
+ PREV_OWNER,
TQ_EVENT_ENQUEUE | TQ_EVENT_BUSY_WAIT
);
SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
TQSendAndWaitForIntendToBlock(
ctx->tq_ctx,
- TQ_BLOCKER_A,
+ NEW_OWNER,
TQ_EVENT_ENQUEUE
);
@@ -689,13 +857,13 @@ test-support: |
if ( ctx->gains_new_helping_scheduler ) {
TQSend(
ctx->tq_ctx,
- TQ_BLOCKER_D,
+ NEW_OWNER_NEW_HELPER,
TQ_EVENT_ENQUEUE
);
- YieldTask( ctx->tq_ctx->worker_id[ TQ_HELPER_A ] );
- TQWaitForEventsReceived( ctx->tq_ctx, TQ_BLOCKER_D );
- TQWaitForIntendToBlock( ctx->tq_ctx, TQ_BLOCKER_D );
- YieldTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_D ] );
+ YieldTask( ctx->tq_ctx->worker_id[ PREV_OWNER ] );
+ TQWaitForEventsReceived( ctx->tq_ctx, NEW_OWNER_NEW_HELPER );
+ TQWaitForIntendToBlock( ctx->tq_ctx, NEW_OWNER_NEW_HELPER );
+ YieldTask( ctx->tq_ctx->worker_id[ NEW_OWNER_NEW_HELPER ] );
}
if ( ctx->use_helping_scheduler ) {
@@ -703,22 +871,22 @@ test-support: |
}
if ( ctx->suspended ) {
- SuspendTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ SuspendTask( ctx->tq_ctx->worker_id[ NEW_OWNER ] );
}
- ctx->tq_ctx->busy_wait[ TQ_HELPER_A ] = false;
+ ctx->tq_ctx->busy_wait[ PREV_OWNER ] = false;
TQSendAndWaitForExecutionStop(
ctx->tq_ctx,
- TQ_HELPER_A,
+ PREV_OWNER,
TQ_EVENT_SCHEDULER_RECORD_START |
TQ_EVENT_SURRENDER
);
TQSchedulerRecordStop( ctx->tq_ctx );
T_eq_ptr(
TQGetOwner( ctx->tq_ctx ),
- ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]
+ ctx->tq_ctx->worker_tcb[ NEW_OWNER ]
);
- ctx->priority_after = TQGetPriority( ctx->tq_ctx, TQ_HELPER_A );
+ ctx->priority_after = TQGetPriority( ctx->tq_ctx, PREV_OWNER );
#endif
}
@@ -728,19 +896,19 @@ test-support: |
SetSelfScheduler( SCHEDULER_A_ID, PRIO_ULTRA_HIGH );
if ( ctx->suspended ) {
- ResumeTask( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ ResumeTask( ctx->tq_ctx->worker_id[ NEW_OWNER ] );
}
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_A,
+ NEW_OWNER,
TQ_EVENT_SURRENDER
);
if ( ctx->gains_new_helping_scheduler ) {
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_D,
+ NEW_OWNER_NEW_HELPER,
TQ_EVENT_SURRENDER
);
}
@@ -751,14 +919,14 @@ test-support: |
) {
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_HELPER_A,
+ PREV_OWNER,
TQ_EVENT_MUTEX_A_RELEASE
);
if ( ctx->inherited_priorities_are_dispensible ) {
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_B,
+ PREV_OWNER_HELPER_A,
TQ_EVENT_MUTEX_A_RELEASE
);
}
@@ -766,7 +934,7 @@ test-support: |
if ( ctx->helping_schedules_are_dispensible ) {
TQSendAndSynchronizeRunner(
ctx->tq_ctx,
- TQ_BLOCKER_C,
+ PREV_OWNER_HELPER_B,
TQ_EVENT_MUTEX_A_RELEASE
);
}
@@ -797,6 +965,18 @@ transition-map:
WaitState: IntendToBlock
then: 'No'
- else: 'Yes'
+ PreviousOwnerPriority:
+ - if:
+ pre-conditions:
+ InheritedPriority: Vital
+ then: Drop
+ - else: Nop
+ NewPriority:
+ - if:
+ pre-conditions:
+ NewPriority: Vital
+ then: Raise
+ - else: Nop
RemoveHelper:
- if:
pre-conditions:
@@ -809,78 +989,92 @@ transition-map:
NewHelping: Dispensable
then: 'No'
- else: 'Yes'
- PreviousOwnerPriority:
- - if:
- pre-conditions:
- InheritedPriority: Vital
- then: Drop
- - else: Nop
Suspended:
- specified-by: Suspended
pre-conditions:
- EnqueueVariant: all
+ SchedulerCount: all
InheritedPriority: all
PreviousHelping: all
- Scheduler: all
+ UsedScheduler: all
+ NewPriority: all
NewHelping: all
Suspended: all
WaitState: all
-- enabled-by: true
- post-conditions: StickyHasNoBlocking
- pre-conditions:
- EnqueueVariant:
- - Sticky
- InheritedPriority: all
- PreviousHelping: all
- Scheduler: all
- NewHelping: all
- Suspended: all
- WaitState:
- - Blocked
- enabled-by:
not: RTEMS_SMP
- post-conditions: OnlyOneCPU
+ post-conditions: NeedsSecondCPUForIntentToBlock
pre-conditions:
- EnqueueVariant: all
+ SchedulerCount: all
InheritedPriority: all
PreviousHelping: all
- Scheduler: all
+ UsedScheduler: all
+ NewPriority: all
NewHelping: all
Suspended: all
WaitState:
- IntendToBlock
-- enabled-by:
- not: RTEMS_SMP
- post-conditions: OnlyOneCPU
+- enabled-by: true
+ post-conditions: NeedsSecondScheduler
pre-conditions:
- EnqueueVariant: all
+ SchedulerCount:
+ - One
InheritedPriority: all
PreviousHelping:
- Vital
- Scheduler: all
+ UsedScheduler: all
+ NewPriority: all
NewHelping: all
Suspended: all
WaitState: all
-- enabled-by:
- not: RTEMS_SMP
- post-conditions: OnlyOneCPU
+- enabled-by: true
+ post-conditions: NeedsSecondScheduler
pre-conditions:
- EnqueueVariant: all
+ SchedulerCount:
+ - One
InheritedPriority: all
PreviousHelping: all
- Scheduler:
+ UsedScheduler:
- Helping
+ NewPriority: all
NewHelping: all
Suspended: all
WaitState: all
-- enabled-by:
- not: RTEMS_SMP
- post-conditions: OnlyOneCPU
+- enabled-by: true
+ post-conditions: NeedsSecondScheduler
pre-conditions:
- EnqueueVariant: all
+ SchedulerCount:
+ - One
InheritedPriority: all
PreviousHelping: all
- Scheduler: all
+ UsedScheduler: all
+ NewPriority:
+ - Vital
+ NewHelping: all
+ Suspended: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: NeedsSecondScheduler
+ pre-conditions:
+ SchedulerCount:
+ - One
+ InheritedPriority: all
+ PreviousHelping: all
+ UsedScheduler: all
+ NewPriority: all
+ NewHelping:
+ - Vital
+ Suspended: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: NeedsThirdScheduler
+ pre-conditions:
+ SchedulerCount:
+ - Two
+ InheritedPriority: all
+ PreviousHelping: all
+ UsedScheduler: all
+ NewPriority:
+ - Vital
NewHelping:
- Vital
Suspended: all