[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