[rtems-central commit] spec: Refine TQ timeout priority inherit spec
Sebastian Huber
sebh at rtems.org
Fri Oct 8 14:17:35 UTC 2021
Module: rtems-central
Branch: master
Commit: a384c7655af1f238b3627b604f3102b0dac7b077
Changeset: http://git.rtems.org/rtems-central/commit/?id=a384c7655af1f238b3627b604f3102b0dac7b077
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Fri Oct 8 15:45:55 2021 +0200
spec: Refine TQ timeout priority inherit spec
---
spec/newlib/val/sys-lock.yml | 4 +-
spec/rtems/sem/req/timeout.yml | 21 +-
spec/score/tq/req/timeout-mrsp.yml | 223 +++++
spec/score/tq/req/timeout-priority-inherit.yml | 1104 ++++++++++++++++++++----
4 files changed, 1168 insertions(+), 184 deletions(-)
diff --git a/spec/newlib/val/sys-lock.yml b/spec/newlib/val/sys-lock.yml
index c6358b2..f8d90eb 100644
--- a/spec/newlib/val/sys-lock.yml
+++ b/spec/newlib/val/sys-lock.yml
@@ -77,7 +77,7 @@ test-actions:
Validate the ${../if/sys-lock-mutex-acquire-timed:/name} timeout
behaviour.
code: |
- ctx->tq_mtx_ctx.base.wait = TQ_WAIT_TIMED;
+ ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_DEADLOCK;
${/score/tq/req/timeout-priority-inherit:/test-run}(
&ctx->tq_mtx_ctx.base
@@ -199,7 +199,7 @@ test-actions:
Validate the ${../if/sys-lock-mutex-recursive-acquire-timed:/name}
timeout behaviour.
code: |
- ctx->tq_mtx_ctx.base.wait = TQ_WAIT_TIMED;
+ ctx->tq_mtx_ctx.base.wait = TQ_WAIT_FOREVER;
ctx->tq_mtx_ctx.recursive = TQ_MTX_RECURSIVE_ALLOWED;
${/score/tq/req/timeout-priority-inherit:/test-run}(
&ctx->tq_mtx_ctx.base
diff --git a/spec/rtems/sem/req/timeout.yml b/spec/rtems/sem/req/timeout.yml
index bf4ca66..568e39b 100644
--- a/spec/rtems/sem/req/timeout.yml
+++ b/spec/rtems/sem/req/timeout.yml
@@ -9,18 +9,29 @@ links:
- role: function-implementation
uid: /score/tq/req/timeout
- role: function-implementation
+ uid: /score/tq/req/timeout-mrsp
+- role: function-implementation
uid: /score/tq/req/timeout-priority-inherit
post-conditions:
- name: Action
states:
- name: Timeout
test-code: |
+ ctx->tq_ctx.wait = TQ_WAIT_TIMED;
${/score/tq/req/timeout:/test-run}( &ctx->tq_ctx );
text: |
The semaphore obtain timeout actions shall be done as specified by
${/score/tq/req/timeout}.
+ - name: TimeoutMrsP
+ test-code: |
+ ctx->tq_ctx.wait = TQ_WAIT_TIMED;
+ ${/score/tq/req/timeout-mrsp:/test-run}( &ctx->tq_ctx );
+ text: |
+ The semaphore obtain timeout actions shall be done as specified by
+ ${/score/tq/req/timeout-mrsp}.
- name: TimeoutPriorityInherit
test-code: |
+ ctx->tq_ctx.wait = TQ_WAIT_FOREVER;
${/score/tq/req/timeout-priority-inherit:/test-run}( &ctx->tq_ctx );
text: |
The semaphore obtain timeout actions shall be done as specified by
@@ -133,6 +144,7 @@ test-includes:
- string.h
test-local-includes:
- tr-tq-timeout.h
+- tr-tq-timeout-mrsp.h
- tr-tq-timeout-priority-inherit.h
- tx-thread-queue.h
- tx-support.h
@@ -143,7 +155,6 @@ test-setup:
brief: null
code: |
memset( ctx, 0, sizeof( *ctx ) );
- ctx->tq_ctx.wait = TQ_WAIT_TIMED;
ctx->tq_ctx.enqueue_prepare = TQEnqueuePrepareDefault;
ctx->tq_ctx.enqueue_done = TQEnqueueDoneDefault;
ctx->tq_ctx.enqueue = TQEnqueueClassicSem;
@@ -167,9 +178,11 @@ transition-map:
Action:
- if:
pre-conditions:
- Class:
- - PrioInherit
- - MrsP
+ Class: MrsP
+ then: TimeoutMrsP
+ - if:
+ pre-conditions:
+ Class: PrioInherit
then: TimeoutPriorityInherit
- else: Timeout
pre-conditions:
diff --git a/spec/score/tq/req/timeout-mrsp.yml b/spec/score/tq/req/timeout-mrsp.yml
new file mode 100644
index 0000000..9d78655
--- /dev/null
+++ b/spec/score/tq/req/timeout-mrsp.yml
@@ -0,0 +1,223 @@
+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: Status
+ states:
+ - name: Ok
+ test-code: |
+ T_eq_int(
+ ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
+ );
+ text: |
+ The return status of the directive call shall be derived from
+ ${../../status/if/successful:/name}.
+ - name: Timeout
+ test-code: |
+ T_eq_int(
+ ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
+ );
+ text: |
+ The return status of the directive call shall be derived from
+ ${../../status/if/timeout:/name}.
+ test-epilogue: null
+ test-prologue: null
+- name: Unblock
+ states:
+ - name: 'No'
+ test-code: |
+ T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ text: |
+ The thread of the timeout operation shall not be unblocked by the timeout
+ operation.
+ test-epilogue: null
+ test-prologue: |
+ size_t i;
+
+ i = 0;
+pre-conditions:
+- name: Scheduler
+ states:
+ - name: Same
+ test-code: |
+ ctx->other_scheduler = false;
+
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ SCHEDULER_A_ID,
+ PRIO_LOW
+ );
+ RemoveProcessor( SCHEDULER_B_ID, 1 );
+ AddProcessor( SCHEDULER_A_ID, 1 );
+ ctx->restore_scheduler = true;
+ text: |
+ While the ${/glossary/scheduler-home:/term} of the thread is equal to the
+ ${/glossary/scheduler-home:/term} of the thread queue owner.
+ - name: Other
+ test-code: |
+ ctx->other_scheduler = true;
+
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ SCHEDULER_B_ID,
+ PRIO_NORMAL
+ );
+ text: |
+ While the ${/glossary/scheduler-home:/term} of the thread is not equal to
+ the ${/glossary/scheduler-home:/term} of the thread queue owner.
+ test-epilogue: null
+ test-prologue: null
+- name: WaitState
+ states:
+ - name: IntendToBlock
+ test-code: |
+ Per_CPU_Control *cpu;
+
+ TQEnqueuePrepare( ctx->tq_ctx );
+ TQSendAndWaitForIntendToBlock(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_ENQUEUE
+ );
+ cpu = _Thread_Get_CPU( ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ] );
+
+ /*
+ * We have to make sure that the worker thread inserted its thread
+ * timer. Checking the intend to block wait state is not enough to
+ * ensure this.
+ */
+ while ( cpu->thread_dispatch_disable_level != 0 ) {
+ /* Wait */
+ }
+
+ Tick( ctx );
+ WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ TQEnqueueDone( ctx->tq_ctx );
+ text: |
+ While the thread of the timeout operation is in the intend to block wait
+ state.
+ - name: ReadyAgain
+ test-code: |
+ TQEnqueuePrepare( ctx->tq_ctx );
+ TQSendAndWaitForIntendToBlock(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_ENQUEUE | TQ_EVENT_TIMEOUT | TQ_EVENT_SURRENDER |
+ TQ_EVENT_SCHEDULER_RECORD_STOP
+ );
+ TQSchedulerRecordStart( ctx->tq_ctx );
+ TQEnqueueDone( ctx->tq_ctx );
+ WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
+ text: |
+ While the thread of the timeout operation is in the ready again wait
+ state.
+ test-epilogue: null
+ test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons: {}
+test-action: |
+ /*
+ * The action is performed by the ``WaitState`` pre-condition preparation.
+ */
+test-brief: null
+test-cleanup: |
+ if ( ctx->restore_scheduler ) {
+ RemoveProcessor( SCHEDULER_A_ID, 1 );
+ AddProcessor( SCHEDULER_B_ID, 1 );
+ }
+test-context:
+- brief: |
+ If this member is true, then the enqueued thread shall use a home scheduler
+ other than the home scheduler of the owner.
+ description: null
+ member: |
+ bool other_scheduler
+- brief: |
+ If this member is true, then the processor set of the schedulers shall be
+ restored.
+ description: null
+ member: |
+ bool restore_scheduler
+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-timeout-mrsp.h
+test-includes:
+- rtems/score/smpimpl.h
+- rtems/score/threadimpl.h
+test-local-includes:
+- tx-support.h
+- tr-tq-timeout-mrsp.h
+test-prepare: |
+ ctx->restore_scheduler = false;
+test-setup:
+ brief: null
+ code: |
+ TQReset( ctx->tq_ctx );
+ 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;
+ }
+
+ static void Tick( void *arg )
+ {
+ Context *ctx;
+
+ ctx = arg;
+ TQSchedulerRecordStart( ctx->tq_ctx );
+ FinalClockTick();
+ TQSchedulerRecordStop( ctx->tq_ctx );
+ }
+test-target: testsuites/validation/tr-tq-timeout-mrsp.c
+test-teardown:
+ brief: null
+ code: |
+ TQReset( ctx->tq_ctx );
+ description: null
+text: |
+ When the thread queue enqueue operation timed out.
+transition-map:
+- enabled-by: true
+ post-conditions:
+ Status: Timeout
+ Unblock: 'No'
+ pre-conditions:
+ Scheduler: all
+ WaitState:
+ - IntendToBlock
+- enabled-by: true
+ post-conditions:
+ Status: Ok
+ Unblock: 'No'
+ pre-conditions:
+ Scheduler: all
+ WaitState:
+ - ReadyAgain
+type: requirement
diff --git a/spec/score/tq/req/timeout-priority-inherit.yml b/spec/score/tq/req/timeout-priority-inherit.yml
index 50486d2..df4ed94 100644
--- a/spec/score/tq/req/timeout-priority-inherit.yml
+++ b/spec/score/tq/req/timeout-priority-inherit.yml
@@ -12,7 +12,7 @@ post-conditions:
- name: Ok
test-code: |
T_eq_int(
- ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ ctx->tq_ctx->status[ THREAD ],
TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
);
text: |
@@ -21,7 +21,7 @@ post-conditions:
- name: Timeout
test-code: |
T_eq_int(
- ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ ctx->tq_ctx->status[ THREAD ],
TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
);
text: |
@@ -33,193 +33,375 @@ post-conditions:
states:
- name: 'Yes'
test-code: |
- T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
- T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ T_true( GetUnblock( ctx, &i ) );
+ T_false( GetUnblock( ctx, &i ) );
text: |
- The thread of the timeout operation shall be unblocked by the timeout
- operation.
+ The thread shall be unblocked by the timeout operation.
- name: 'No'
test-code: |
- T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ T_false( GetUnblock( ctx, &i ) );
text: |
- The thread of the timeout operation shall not be unblocked by the timeout
- operation.
+ The thread shall not be unblocked by the timeout operation.
test-epilogue: null
test-prologue: |
size_t i;
i = 0;
-pre-conditions:
-- name: EnqueueVariant
+- name: OwnerPriority
states:
- - name: Blocking
+ - name: Nop
test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_BLOCKS ) {
- ${.:skip}
- }
+ T_eq_u32( ctx->owner_priority_after, ctx->owner_priority );
text: |
- Where the thread queue enqueue operation is blocking.
- - name: Sticky
+ The priority of the owner with respect to the scheduler shall not change
+ by the timeout operation.
+ - name: Lower
test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_STICKY ) {
- ${.:skip}
- }
+ T_eq_u32( ctx->owner_priority_after, ctx->owner_priority + 1 );
+ text: |
+ The priority of the owner with respect to the scheduler shall be lowered
+ to the next highest priority.
+ - name: Drop
+ test-code: |
+ T_eq_u32( ctx->owner_priority_after, PRIO_INVALID );
+ text: |
+ The owner shall not have a priority with respect to the scheduler.
+ test-epilogue: null
+ test-prologue: null
+- name: OwnerOwnerPriority
+ states:
+ - name: Nop
+ test-code: |
+ T_eq_u32( ctx->owner_owner_priority_after, ctx->owner_owner_priority );
text: |
- Where the thread queue enqueue operation is sticky.
+ The priority of the owner of the thread queue on which the owner is
+ enqueued with respect to the scheduler shall not change by the timeout
+ operation.
+ - name: Lower
+ test-code: |
+ T_eq_u32( ctx->owner_owner_priority_after, ctx->owner_owner_priority + 1 );
+ text: |
+ The priority of the owner of the thread queue on which the owner is
+ enqueued with respect to the scheduler shall be lowered to the next
+ highest priority.
+ - name: Drop
+ test-code: |
+ T_eq_u32( ctx->owner_owner_priority_after, PRIO_INVALID );
+ text: |
+ The owner of the thread queue on which the owner is enqueued shall not
+ have a priority with respect to the scheduler.
test-epilogue: null
test-prologue: null
+pre-conditions:
- name: Scheduler
states:
- - name: Same
+ - name: Home
test-code: |
- ctx->other_scheduler = false;
-
- if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
- TQSetScheduler(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- SCHEDULER_A_ID,
- PRIO_LOW
- );
- RemoveProcessor( SCHEDULER_B_ID, 1 );
- AddProcessor( SCHEDULER_A_ID, 1 );
- ctx->restore_scheduler = true;
- } else {
- TQSetScheduler(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- SCHEDULER_A_ID,
- PRIO_ULTRA_HIGH
- );
- }
+ ctx->scheduler_id = SCHEDULER_A_ID;
text: |
- While the ${/glossary/scheduler-home:/term} of the thread is equal to the
+ While the ${/glossary/scheduler-home:/term} of the thread is the
${/glossary/scheduler-home:/term} of the thread queue owner.
- - name: Other
+ - name: Helping
test-code: |
- ctx->other_scheduler = true;
-
- TQSetScheduler(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- SCHEDULER_B_ID,
- PRIO_NORMAL
- );
+ ctx->scheduler_id = SCHEDULER_B_ID;
text: |
- While the ${/glossary/scheduler-home:/term} of the thread is not equal to
- the ${/glossary/scheduler-home:/term} of the thread queue owner.
+ While the ${/glossary/scheduler-home:/term} of the thread is a
+ ${/glossary/scheduler-helping:/term} of the thread queue owner.
+ test-epilogue: null
+ test-prologue: null
+- name: Queue
+ states:
+ - name: Only
+ test-code: |
+ ctx->queue_node = TQ_NODE_ONLY;
+ text: |
+ While the priority node of the thread is the only priority node in the
+ priority queue associated with the scheduler of the thread queue.
+ - name: Vital
+ test-code: |
+ ctx->queue_node = TQ_NODE_VITAL;
+ text: |
+ While the priority node of the thread is not the only priority node in
+ the priority queue associated with the scheduler of the thread queue,
+ while the priority node of the thread is the highest priority node in the
+ priority queue.
+ - name: Dispensable
+ test-code: |
+ ctx->queue_node = TQ_NODE_DISPENSABLE;
+ text: |
+ While the priority node of the thread is not the only priority node in
+ the priority queue associated with the scheduler of the thread queue,
+ while the priority node of the thread is not the highest priority node in
+ the priority queue.
+ test-epilogue: null
+ test-prologue: null
+- name: OwnerPriority
+ states:
+ - name: Only
+ test-code: |
+ ctx->owner_node = TQ_NODE_ONLY;
+ text: |
+ While the priority node of the thread queue is the only priority node
+ associated with the scheduler available to the owner.
+ - name: Vital
+ test-code: |
+ ctx->owner_node = TQ_NODE_VITAL;
+ text: |
+ While the priority node of the thread queue is not the only priority node
+ associated with the scheduler available to the owner,
+ while the priority node of the thread queue is the highest priority node
+ available to the owner.
+ - name: Dispensable
+ test-code: |
+ ctx->owner_node = TQ_NODE_DISPENSABLE;
+ text: |
+ While the priority node of the thread queue is not the only priority node
+ associated with the scheduler available to the owner,
+ while the priority node of the thread queue is not the highest priority
+ node available to the owner.
+ test-epilogue: null
+ test-prologue: null
+- name: OwnerState
+ states:
+ - name: NotEnqueued
+ test-code: |
+ ctx->owner_obtain = 0;
+ ctx->owner_release = 0;
+ text: |
+ While the owner of the thread queue is not enqueued on a thread queue.
+ - name: FIFO
+ test-code: |
+ ctx->owner_obtain = TQ_EVENT_MUTEX_FIFO_OBTAIN;
+ ctx->owner_release = TQ_EVENT_MUTEX_FIFO_RELEASE;
+ text: |
+ While the owner of the thread queue is enqueued on a thread queue in FIFO
+ order.
+ - name: Priority
+ test-code: |
+ ctx->owner_obtain = TQ_EVENT_MUTEX_NO_PROTOCOL_OBTAIN;
+ ctx->owner_release = TQ_EVENT_MUTEX_NO_PROTOCOL_RELEASE;
+ text: |
+ While the owner of the thread queue is enqueued on a thread queue in
+ priority order.
+ - name: PriorityInherit
+ test-code: |
+ ctx->owner_obtain = TQ_EVENT_MUTEX_C_OBTAIN;
+ ctx->owner_release = TQ_EVENT_MUTEX_C_RELEASE;
+ text: |
+ While the owner of the thread queue is enqueued on a thread queue in
+ priority order with priority inheritance.
+ test-epilogue: null
+ test-prologue: null
+- name: OwnerQueue
+ states:
+ - name: Only
+ test-code: |
+ ctx->owner_queue_node = TQ_NODE_ONLY;
+ text: |
+ While the priority node of the owner is the only priority node in the
+ priority queue associated with the scheduler of the thread queue on which
+ the owner is enqueued.
+ - name: Vital
+ test-code: |
+ ctx->owner_queue_node = TQ_NODE_VITAL;
+ text: |
+ While the priority node of the owner is not the only priority node in the
+ priority queue associated with the scheduler of the thread queue on which
+ the owner is enqueued,
+ while the priority node of the owner is the highest priority node in the
+ priority queue.
+ - name: Dispensable
+ test-code: |
+ ctx->owner_queue_node = TQ_NODE_DISPENSABLE;
+ text: |
+ While the priority node of the owner is not the only priority node in the
+ priority queue associated with the scheduler of the thread queue on which
+ the owner is enqueued,
+ while the priority node of the owner is not the highest priority node in
+ the priority queue.
+ test-epilogue: null
+ test-prologue: null
+- name: OwnerOwnerPriority
+ states:
+ - name: Only
+ test-code: |
+ ctx->owner_owner_node = TQ_NODE_ONLY;
+ text: |
+ While the priority node of the thread queue on which the owner is
+ enqueued is the only priority node associated with the scheduler
+ available to the owner of the thread queue on which the owner is
+ enqueued.
+ - name: Vital
+ test-code: |
+ ctx->owner_owner_node = TQ_NODE_VITAL;
+ text: |
+ While the priority node of the thread queue on which the owner is
+ enqueued is not the only priority node associated with the scheduler
+ available to the owner of the thread queue on which the owner is
+ enqueued,
+ while the priority node of the thread queue on which the owner is
+ enqueued is the highest priority node available to the owner of the
+ thread queue on which the owner is enqueued.
+ - name: Dispensable
+ test-code: |
+ ctx->owner_owner_node = TQ_NODE_DISPENSABLE;
+ text: |
+ While the priority node of the thread queue on which the owner is
+ enqueued is not the only priority node associated with the scheduler
+ available to the owner of the thread queue on which the owner is
+ enqueued,
+ while the priority node of the thread queue is on which the owner is
+ enqueued not the highest priority node available to the owner of the
+ thread queue on which the owner is enqueued.
test-epilogue: null
test-prologue: null
- name: WaitState
states:
- name: Blocked
test-code: |
- if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
- T_unreachable();
- } else {
- TQEnqueuePrepare( ctx->tq_ctx );
- TQClearDone( ctx->tq_ctx, TQ_BLOCKER_A );
- TQSendAndWaitForExecutionStop(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE
- );
- Tick( ctx );
- TQWaitForDone( ctx->tq_ctx, TQ_BLOCKER_A );
- TQEnqueueDone( ctx->tq_ctx );
- }
+ ctx->wait_state = TQ_WAIT_STATE_BLOCKED;
text: |
- While the thread of the timeout operation is in the blocked wait state.
+ While the thread is in the blocked wait state.
- name: IntendToBlock
test-code: |
- TQEnqueuePrepare( ctx->tq_ctx );
-
- if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
- Per_CPU_Control *cpu;
-
- TQSendAndWaitForIntendToBlock(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE
- );
- cpu = _Thread_Get_CPU( ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ] );
-
- /*
- * We have to make sure that the worker thread inserted its thread
- * timer. Checking the intend to block wait state is not enough to
- * ensure this.
- */
- while ( cpu->thread_dispatch_disable_level != 0 ) {
- /* Wait */
- }
-
- Tick( ctx );
- WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
- } else {
- T_scheduler_set_event_handler( SchedulerBlock, ctx );
- TQSendAndWaitForExecutionStop(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE
- );
- }
-
- TQEnqueueDone( ctx->tq_ctx );
+ ctx->wait_state = TQ_WAIT_STATE_INTEND_TO_BLOCK;
text: |
- While the thread of the timeout operation is in the intend to block wait
- state.
+ While the thread is in the intend to block wait state.
- name: ReadyAgain
test-code: |
- TQEnqueuePrepare( ctx->tq_ctx );
-
- if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
- TQSendAndWaitForIntendToBlock(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE | TQ_EVENT_TIMEOUT | TQ_EVENT_SURRENDER |
- TQ_EVENT_SCHEDULER_RECORD_STOP
- );
- TQSchedulerRecordStart( ctx->tq_ctx );
- TQEnqueueDone( ctx->tq_ctx );
- WaitForExecutionStop( ctx->tq_ctx->worker_id[ TQ_BLOCKER_A ] );
- } else {
- TQSendAndWaitForExecutionStop(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_ENQUEUE
- );
- T_scheduler_set_event_handler( SchedulerUnblock, ctx );
- TQEnqueueDone( ctx->tq_ctx );
- TQSendAndWaitForExecutionStop(
- ctx->tq_ctx,
- TQ_BLOCKER_A,
- TQ_EVENT_SURRENDER
- );
- }
+ ctx->wait_state = TQ_WAIT_STATE_READY_AGAIN;
text: |
- While the thread of the timeout operation is in the ready again wait
- state.
+ While the thread is in the ready again wait state.
test-epilogue: null
test-prologue: null
rationale: null
references: []
requirement-type: functional
skip-reasons:
- StickyHasNoBlocking: |
- When a sticky thread queue enqueue operation is performed, the blocked wait
- state cannot occur.
+ ReadyAgainNeedsSurrender: |
+ For the ready again wait state, the owner must surrender the thread queue
+ to the thread.
OnlyOneCPU: |
Where the system was built with SMP support disabled, exactly one scheduler
is present in an application using exactly one processor.
+ HomeHasRealPriority: |
+ There is always at least the ${/glosssary/priority-real:/term} available
+ for the ${/glossary/scheduler-home:/term}.
+ DispensableStopsVital: |
+ Vital priority nodes cannot be after a dispensable priority node.
test-action: |
- /*
- * The action is performed by the ``WaitState`` pre-condition preparation.
- */
+ rtems_task_priority priority;
+
+ priority = PRIO_FLEXIBLE;
+ TQSetScheduler( ctx->tq_ctx, THREAD, ctx->scheduler_id, priority );
+
+ TQSend(
+ ctx->tq_ctx,
+ OWNER,
+ TQ_EVENT_MUTEX_A_OBTAIN | TQ_EVENT_ENQUEUE
+ );
+
+ if ( ctx->owner_obtain != 0 ) {
+ TQSend(
+ ctx->tq_ctx,
+ OWNER_OWNER,
+ TQ_EVENT_MUTEX_B_OBTAIN | ctx->owner_obtain
+ );
+ TQSend( ctx->tq_ctx, OWNER, ctx->owner_obtain | ctx->owner_release );
+ }
+
+ priority = PrepareQueue( ctx, priority );
+ priority = PrepareOwner( ctx, priority );
+ priority = PrepareOwnerQueue( ctx, priority );
+ PrepareOwnerOwner( ctx, priority );
+
+ TQClearDone( ctx->tq_ctx, THREAD );
+
+ switch ( ctx->wait_state ) {
+ case TQ_WAIT_STATE_BLOCKED:
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ THREAD,
+ TQ_EVENT_ENQUEUE_TIMED
+ );
+ Tick( ctx );
+ TQSend( ctx->tq_ctx, OWNER, TQ_EVENT_SURRENDER );
+ break;
+ case TQ_WAIT_STATE_INTEND_TO_BLOCK:
+ T_scheduler_set_event_handler( SchedulerBlock, ctx );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ THREAD,
+ TQ_EVENT_ENQUEUE_TIMED
+ );
+ TQSend( ctx->tq_ctx, OWNER, TQ_EVENT_SURRENDER );
+ break;
+ case TQ_WAIT_STATE_READY_AGAIN:
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ THREAD,
+ TQ_EVENT_ENQUEUE_TIMED
+ );
+ T_scheduler_set_event_handler( SchedulerUnblock, ctx );
+ TQSend( ctx->tq_ctx, OWNER, TQ_EVENT_SURRENDER );
+
+ ctx->owner_priority_after = GetPriorityByScheduler(
+ ctx->tq_ctx->worker_id[ OWNER ],
+ ctx->scheduler_id
+ );
+ ctx->owner_owner_priority_after = GetPriorityByScheduler(
+ ctx->tq_ctx->worker_id[ OWNER_OWNER ],
+ ctx->scheduler_id
+ );
+
+ TQSend( ctx->tq_ctx, THREAD, TQ_EVENT_SURRENDER );
+ break;
+ }
+
+ TQWaitForDone( ctx->tq_ctx, THREAD );
+ TQWaitForExecutionStop( ctx->tq_ctx, THREAD );
test-brief: null
test-cleanup: |
- if ( ctx->restore_scheduler ) {
- RemoveProcessor( SCHEDULER_A_ID, 1 );
- AddProcessor( SCHEDULER_B_ID, 1 );
+ if ( ctx->owner_obtain != 0 ) {
+ TQSend(
+ ctx->tq_ctx,
+ OWNER_OWNER,
+ TQ_EVENT_MUTEX_B_RELEASE | ctx->owner_release
+ );
+
+ if ( ctx->owner_queue_helper_release ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_QUEUE_HELPER,
+ ctx->owner_release
+ );
+ }
+
+ if ( ctx->owner_owner_helper_release ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_OWNER_HELPER,
+ TQ_EVENT_MUTEX_B_RELEASE
+ );
+ }
+ }
+
+ TQSend( ctx->tq_ctx, OWNER, TQ_EVENT_MUTEX_A_RELEASE );
+
+ if ( ctx->queue_helper_surrender ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ QUEUE_HELPER,
+ TQ_EVENT_SURRENDER
+ );
+ }
+
+ if ( ctx->owner_helper_release ) {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_HELPER,
+ TQ_EVENT_MUTEX_A_RELEASE
+ );
}
test-context:
- brief: |
@@ -228,17 +410,104 @@ test-context:
member: |
CallWithinISRRequest request;
- brief: |
- If this member is true, then the enqueued thread shall use a home scheduler
- other than the home scheduler of the owner.
+ This member specifies the scheduler of the thread.
+ description: null
+ member: |
+ rtems_id scheduler_id
+- brief: |
+ This member specifies the queue node kind.
description: null
member: |
- bool other_scheduler
+ TQNodeKind queue_node
- brief: |
- If this member is true, then the processor set of the schedulers shall be
- restored.
+ This member specifies the owner priority node kind.
description: null
member: |
- bool restore_scheduler
+ TQNodeKind owner_node
+- brief: |
+ This member specifies which mutex obtain event shall be used to block the
+ thread queue owner.
+ description: null
+ member: |
+ rtems_event_set owner_obtain
+- brief: |
+ This member specifies which mutex release event shall be used to unblock
+ the thread queue owner.
+ description: null
+ member: |
+ rtems_event_set owner_release
+- brief: |
+ This member specifies the owner queue node kind.
+ description: null
+ member: |
+ TQNodeKind owner_queue_node
+- brief: |
+ This member specifies the kind of the priority node of the owner of the
+ thread queue on which the owner of the thread queue is blocked.
+ description: null
+ member: |
+ TQNodeKind owner_owner_node
+- brief: |
+ This member specifies the wait state.
+ description: null
+ member: |
+ TQWaitState wait_state
+- brief: |
+ This member contains the thread queue priority.
+ description: null
+ member: |
+ rtems_task_priority queue_priority
+- brief: |
+ This member contains the owner priority.
+ description: null
+ member: |
+ rtems_task_priority owner_priority
+- brief: |
+ This member contains the owner priority after the timeout or surrender.
+ description: null
+ member: |
+ rtems_task_priority owner_priority_after
+- brief: |
+ This member contains the priority of the thread queue on which the owner is
+ enqueued.
+ description: null
+ member: |
+ rtems_task_priority owner_queue_priority
+- brief: |
+ This member contains the priority of the owner of the thread queue on which
+ the owner is enqueued.
+ description: null
+ member: |
+ rtems_task_priority owner_owner_priority
+- brief: |
+ This member contains the priority after the timeout or surrender of the
+ owner of the thread queue on which the owner is enqueued.
+ description: null
+ member: |
+ rtems_task_priority owner_owner_priority_after
+- brief: |
+ If this member is true, then the queue helper shall surrender the thread
+ queue.
+ description: null
+ member: |
+ bool queue_helper_surrender
+- brief: |
+ If this member is true, then the owner helper shall release mutex A.
+ description: null
+ member: |
+ bool owner_helper_release
+- brief: |
+ If this member is true, then the owner queue helper shall release the mutex
+ on which the owner is blocked.
+ description: null
+ member: |
+ bool owner_queue_helper_release
+- brief: |
+ If this member is true, then helper of the owner of the mutex which the
+ owner blocked shall release mutex B.
+ description: null
+ member: |
+ bool owner_owner_helper_release
test-context-support: null
test-description: null
test-header:
@@ -261,25 +530,50 @@ test-local-includes:
- tx-support.h
- tr-tq-timeout-priority-inherit.h
test-prepare: |
- ctx->restore_scheduler = false;
+ ctx->queue_helper_surrender = false;
+ ctx->owner_helper_release = false;
+ ctx->owner_queue_helper_release = false;
+ ctx->owner_owner_helper_release = false;
test-setup:
brief: null
code: |
ctx->request.arg = ctx;
TQReset( ctx->tq_ctx );
+ SetSelfPriority( PRIO_NEARLY_IDLE );
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;
- }
+ #define THREAD TQ_BLOCKER_A
+
+ #define QUEUE_HELPER TQ_BLOCKER_B
+
+ #define OWNER TQ_BLOCKER_C
+
+ #define OWNER_HELPER TQ_BLOCKER_D
- static const rtems_tcb *GetTCB( Context *ctx, TQWorkerKind worker )
+ #define OWNER_QUEUE_HELPER TQ_BLOCKER_E
+
+ #define OWNER_OWNER TQ_WORKER_F
+
+ #define OWNER_OWNER_HELPER TQ_HELPER_A
+
+ static bool GetUnblock( const Context *ctx, size_t *index )
{
- return ctx->tq_ctx->worker_tcb[ worker ];
+ while ( true ) {
+ const T_scheduler_event *event;
+
+ event = TQGetNextUnblock( ctx->tq_ctx, index );
+
+ if ( event == &T_scheduler_event_null ) {
+ return false;
+ }
+
+ if ( event->thread == ctx->tq_ctx->worker_tcb[ THREAD ] ) {
+ return true;
+ }
+ }
}
static void Tick( void *arg )
@@ -290,6 +584,15 @@ test-support: |
TQSchedulerRecordStart( ctx->tq_ctx );
FinalClockTick();
TQSchedulerRecordStop( ctx->tq_ctx );
+
+ ctx->owner_priority_after = GetPriorityByScheduler(
+ ctx->tq_ctx->worker_id[ OWNER ],
+ ctx->scheduler_id
+ );
+ ctx->owner_owner_priority_after = GetPriorityByScheduler(
+ ctx->tq_ctx->worker_id[ OWNER_OWNER ],
+ ctx->scheduler_id
+ );
}
static void SchedulerBlock(
@@ -304,7 +607,8 @@ test-support: |
if (
when == T_SCHEDULER_BEFORE &&
- event->operation == T_SCHEDULER_BLOCK
+ event->operation == T_SCHEDULER_BLOCK &&
+ event->thread == ctx->tq_ctx->worker_tcb[ THREAD ]
) {
T_scheduler_set_event_handler( NULL, NULL );
ctx->request.handler = Tick;
@@ -319,7 +623,7 @@ test-support: |
ctx = arg;
TQSchedulerRecordStart( ctx->tq_ctx );
_Thread_Timeout(
- &ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]->Timer.Watchdog
+ &ctx->tq_ctx->worker_tcb[ THREAD ]->Timer.Watchdog
);
TQSchedulerRecordStop( ctx->tq_ctx );
}
@@ -336,11 +640,12 @@ test-support: |
if (
when == T_SCHEDULER_BEFORE &&
- event->operation == T_SCHEDULER_UNBLOCK
+ event->operation == T_SCHEDULER_UNBLOCK &&
+ event->thread == ctx->tq_ctx->worker_tcb[ THREAD ]
) {
T_scheduler_set_event_handler( NULL, NULL );
- if ( ctx->other_scheduler ) {
+ if ( ctx->scheduler_id == SCHEDULER_B_ID ) {
#if defined(RTEMS_SMP)
_SMP_Unicast_action( 1, ThreadTimeout, ctx );
#else
@@ -352,6 +657,211 @@ test-support: |
}
}
}
+
+ static rtems_task_priority PrepareQueue(
+ Context *ctx,
+ rtems_task_priority priority
+ )
+ {
+ switch ( ctx->queue_node ) {
+ case TQ_NODE_ONLY:
+ ctx->queue_helper_surrender = false;
+ break;
+ case TQ_NODE_VITAL:
+ ctx->queue_helper_surrender = true;
+ TQSetScheduler(
+ ctx->tq_ctx,
+ QUEUE_HELPER,
+ ctx->scheduler_id,
+ priority + 1
+ );
+ TQSend( ctx->tq_ctx, QUEUE_HELPER, TQ_EVENT_ENQUEUE );
+ break;
+ case TQ_NODE_DISPENSABLE:
+ ctx->queue_helper_surrender = true;
+ --priority;
+ TQSetScheduler(
+ ctx->tq_ctx,
+ QUEUE_HELPER,
+ ctx->scheduler_id,
+ priority
+ );
+ TQSend( ctx->tq_ctx, QUEUE_HELPER, TQ_EVENT_ENQUEUE );
+ break;
+ }
+
+ ctx->queue_priority = priority;
+
+ return priority;
+ }
+
+ static rtems_task_priority PrepareOwner(
+ Context *ctx,
+ rtems_task_priority priority
+ )
+ {
+ switch ( ctx->owner_node ) {
+ case TQ_NODE_ONLY:
+ ctx->owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER, PRIO_FLEXIBLE );
+ break;
+ case TQ_NODE_VITAL:
+ if ( ctx->scheduler_id == SCHEDULER_A_ID ) {
+ ctx->owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER, priority + 1 );
+ } else {
+ ctx->owner_helper_release = true;
+ TQSetPriority( ctx->tq_ctx, OWNER, PRIO_FLEXIBLE );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_HELPER,
+ ctx->scheduler_id,
+ priority + 1
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_HELPER,
+ TQ_EVENT_MUTEX_A_OBTAIN
+ );
+ }
+ break;
+ case TQ_NODE_DISPENSABLE:
+ --priority;
+
+ if ( ctx->scheduler_id == SCHEDULER_A_ID ) {
+ ctx->owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER, priority );
+ } else {
+ ctx->owner_helper_release = true;
+ TQSetPriority( ctx->tq_ctx, OWNER, PRIO_FLEXIBLE );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_HELPER,
+ ctx->scheduler_id,
+ priority
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_HELPER,
+ TQ_EVENT_MUTEX_A_OBTAIN
+ );
+ }
+ break;
+ }
+
+ ctx->owner_priority = priority;
+
+ return priority;
+ }
+
+ static rtems_task_priority PrepareOwnerQueue(
+ Context *ctx,
+ rtems_task_priority priority
+ )
+ {
+ if ( ctx->owner_obtain != 0 ) {
+ switch ( ctx->owner_queue_node ) {
+ case TQ_NODE_ONLY:
+ ctx->owner_queue_helper_release = false;
+ break;
+ case TQ_NODE_VITAL:
+ ctx->owner_queue_helper_release = true;
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_QUEUE_HELPER,
+ ctx->scheduler_id,
+ priority + 1
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_QUEUE_HELPER,
+ ctx->owner_obtain
+ );
+ break;
+ case TQ_NODE_DISPENSABLE:
+ ctx->owner_queue_helper_release = true;
+ --priority;
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_QUEUE_HELPER,
+ ctx->scheduler_id,
+ priority
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_QUEUE_HELPER,
+ ctx->owner_obtain
+ );
+ break;
+ }
+
+ ctx->owner_queue_priority = priority;
+ } else {
+ ctx->owner_queue_helper_release = false;
+ ctx->owner_queue_priority = PRIO_INVALID;
+ }
+
+ return priority;
+ }
+
+ static void PrepareOwnerOwner( Context *ctx, rtems_task_priority priority )
+ {
+ if ( ctx->owner_obtain != 0 ) {
+ switch ( ctx->owner_owner_node ) {
+ case TQ_NODE_ONLY:
+ ctx->owner_owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER_OWNER, PRIO_FLEXIBLE );
+ break;
+ case TQ_NODE_VITAL:
+ if ( ctx->scheduler_id == SCHEDULER_A_ID ) {
+ ctx->owner_owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER_OWNER, priority + 1 );
+ } else {
+ ctx->owner_owner_helper_release = true;
+ TQSetPriority( ctx->tq_ctx, OWNER_OWNER, PRIO_FLEXIBLE );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_OWNER_HELPER,
+ ctx->scheduler_id,
+ priority + 1
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_OWNER_HELPER,
+ TQ_EVENT_MUTEX_B_OBTAIN
+ );
+ }
+ break;
+ case TQ_NODE_DISPENSABLE:
+ --priority;
+
+ if ( ctx->scheduler_id == SCHEDULER_A_ID ) {
+ ctx->owner_owner_helper_release = false;
+ TQSetPriority( ctx->tq_ctx, OWNER_OWNER, priority );
+ } else {
+ ctx->owner_owner_helper_release = true;
+ TQSetPriority( ctx->tq_ctx, OWNER_OWNER, PRIO_FLEXIBLE );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ OWNER_OWNER_HELPER,
+ ctx->scheduler_id,
+ priority
+ );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ OWNER_OWNER_HELPER,
+ TQ_EVENT_MUTEX_B_OBTAIN
+ );
+ }
+ break;
+ }
+
+ ctx->owner_owner_priority = priority;
+ } else {
+ ctx->owner_owner_helper_release = false;
+ ctx->owner_owner_priority = PRIO_INVALID;
+ }
+ }
test-target: testsuites/validation/tr-tq-timeout-priority-inherit.c
test-teardown:
brief: null
@@ -363,46 +873,284 @@ text: |
transition-map:
- enabled-by: true
post-conditions:
- Status: Timeout
- Unblock: 'Yes'
+ Status:
+ - if:
+ pre-conditions:
+ WaitState: ReadyAgain
+ then: Ok
+ - else: Timeout
+ Unblock:
+ - if:
+ pre-conditions:
+ WaitState: Blocked
+ then: 'Yes'
+ - else: 'No'
+ OwnerPriority:
+ - if:
+ - pre-conditions:
+ Queue: Only
+ OwnerPriority: Only
+ - pre-conditions:
+ OwnerPriority: Only
+ WaitState: ReadyAgain
+ then: Drop
+ - if:
+ - pre-conditions:
+ OwnerPriority: Vital
+ - pre-conditions:
+ Queue: Vital
+ OwnerPriority: Only
+ then: Lower
+ - else: Nop
+ OwnerOwnerPriority: N/A
pre-conditions:
- EnqueueVariant:
- - Blocking
Scheduler: all
- WaitState:
- - Blocked
+ Queue: all
+ OwnerPriority: all
+ OwnerState:
+ - NotEnqueued
+ - FIFO
+ OwnerQueue: N/A
+ OwnerOwnerPriority: N/A
+ WaitState: all
- enabled-by: true
post-conditions:
- Status: Timeout
- Unblock: 'No'
+ Status:
+ - if:
+ pre-conditions:
+ WaitState: ReadyAgain
+ then: Ok
+ - else: Timeout
+ Unblock:
+ - if:
+ pre-conditions:
+ WaitState: Blocked
+ then: 'Yes'
+ - else: 'No'
+ OwnerPriority:
+ - if:
+ - pre-conditions:
+ Queue: Only
+ OwnerPriority: Only
+ - pre-conditions:
+ OwnerPriority: Only
+ WaitState: ReadyAgain
+ then: Drop
+ - if:
+ - pre-conditions:
+ OwnerPriority: Vital
+ - pre-conditions:
+ Queue: Vital
+ OwnerPriority: Only
+ then: Lower
+ - else: Nop
+ OwnerOwnerPriority: N/A
pre-conditions:
- EnqueueVariant: all
Scheduler: all
- WaitState:
- - IntendToBlock
+ Queue: all
+ OwnerPriority: all
+ OwnerState:
+ - Priority
+ OwnerQueue: all
+ OwnerOwnerPriority: N/A
+ WaitState: all
- enabled-by: true
post-conditions:
- Status: Ok
- Unblock: 'No'
+ Status:
+ - if:
+ pre-conditions:
+ WaitState: ReadyAgain
+ then: Ok
+ - else: Timeout
+ Unblock:
+ - if:
+ pre-conditions:
+ WaitState: Blocked
+ then: 'Yes'
+ - else: 'No'
+ OwnerPriority:
+ - if:
+ - pre-conditions:
+ Queue: Only
+ OwnerPriority: Only
+ - pre-conditions:
+ OwnerPriority: Only
+ WaitState: ReadyAgain
+ then: Drop
+ - if:
+ - pre-conditions:
+ OwnerPriority: Vital
+ - pre-conditions:
+ Queue: Vital
+ OwnerPriority: Only
+ then: Lower
+ - else: Nop
+ OwnerOwnerPriority:
+ - if:
+ and:
+ - post-conditions:
+ OwnerPriority: Drop
+ - pre-conditions:
+ OwnerQueue: Only
+ OwnerOwnerPriority: Only
+ then: Drop
+ - if:
+ and:
+ - post-conditions:
+ OwnerPriority:
+ - Lower
+ - Drop
+ - or:
+ - pre-conditions:
+ OwnerOwnerPriority: Vital
+ - pre-conditions:
+ OwnerQueue:
+ - Only
+ - Vital
+ OwnerOwnerPriority: Only
+ then: Lower
+ - else: Nop
+ pre-conditions:
+ Scheduler: all
+ Queue: all
+ OwnerPriority: all
+ OwnerState:
+ - PriorityInherit
+ OwnerQueue: all
+ OwnerOwnerPriority: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: ReadyAgainNeedsSurrender
pre-conditions:
- EnqueueVariant: all
Scheduler: all
+ Queue: all
+ OwnerPriority: all
+ OwnerState:
+ - FIFO
+ - Priority
+ - PriorityInherit
+ OwnerQueue: all
+ OwnerOwnerPriority: all
WaitState:
- ReadyAgain
- enabled-by: true
- post-conditions: StickyHasNoBlocking
+ post-conditions: ReadyAgainNeedsSurrender
pre-conditions:
- EnqueueVariant:
- - Sticky
Scheduler: all
+ Queue:
+ - Dispensable
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority: all
WaitState:
- - Blocked
+ - ReadyAgain
+- enabled-by: true
+ post-conditions: HomeHasRealPriority
+ pre-conditions:
+ Scheduler:
+ - Home
+ Queue: all
+ OwnerPriority:
+ - Only
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: HomeHasRealPriority
+ pre-conditions:
+ Scheduler:
+ - Home
+ Queue: all
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority:
+ - Only
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue:
+ - Dispensable
+ OwnerPriority:
+ - Vital
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue:
+ - Dispensable
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue:
+ - Vital
+ OwnerOwnerPriority: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue: all
+ OwnerPriority:
+ - Dispensable
+ OwnerState: all
+ OwnerQueue:
+ - Vital
+ OwnerOwnerPriority: all
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue:
+ - Dispensable
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority:
+ - Vital
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue: all
+ OwnerPriority:
+ - Dispensable
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority:
+ - Vital
+ WaitState: all
+- enabled-by: true
+ post-conditions: DispensableStopsVital
+ pre-conditions:
+ Scheduler: all
+ Queue: all
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue:
+ - Dispensable
+ OwnerOwnerPriority:
+ - Vital
+ WaitState: all
- enabled-by:
not: RTEMS_SMP
post-conditions: OnlyOneCPU
pre-conditions:
- EnqueueVariant: all
Scheduler:
- - Other
+ - Helping
+ Queue: all
+ OwnerPriority: all
+ OwnerState: all
+ OwnerQueue: all
+ OwnerOwnerPriority: all
WaitState: all
type: requirement
More information about the vc
mailing list