[rtems-central commit] spec: Refine TQ surrender priority inherit spec

Sebastian Huber sebh at rtems.org
Fri Oct 8 14:17:35 UTC 2021


Module:    rtems-central
Branch:    master
Commit:    c85c24e365acbeb8849dddb0f0ef1d1a00481a69
Changeset: http://git.rtems.org/rtems-central/commit/?id=c85c24e365acbeb8849dddb0f0ef1d1a00481a69

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Oct  8 15:34:05 2021 +0200

spec: Refine TQ surrender priority inherit spec

---

 spec/score/mtx/req/surrender.yml                 |  14 +-
 spec/score/tq/req/surrender-mrsp.yml             | 504 +++++++++++++++++++++++
 spec/score/tq/req/surrender-priority-inherit.yml | 488 +++++++++++++++-------
 3 files changed, 857 insertions(+), 149 deletions(-)

diff --git a/spec/score/mtx/req/surrender.yml b/spec/score/mtx/req/surrender.yml
index 5d1749e..fd31ad2 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 0000000..6b0c26a
--- /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 2ec5871..40d203f 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



More information about the vc mailing list