summaryrefslogtreecommitdiffstats
path: root/spec/score/tq/req/timeout-priority-inherit.yml
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-08 15:45:55 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-10-08 16:10:12 +0200
commita384c7655af1f238b3627b604f3102b0dac7b077 (patch)
tree862f897be0da1b91f5267c7333be947307d25fd0 /spec/score/tq/req/timeout-priority-inherit.yml
parentspec: Refine TQ surrender priority inherit spec (diff)
downloadrtems-central-a384c7655af1f238b3627b604f3102b0dac7b077.tar.bz2
spec: Refine TQ timeout priority inherit spec
Diffstat (limited to 'spec/score/tq/req/timeout-priority-inherit.yml')
-rw-r--r--spec/score/tq/req/timeout-priority-inherit.yml1104
1 files changed, 926 insertions, 178 deletions
diff --git a/spec/score/tq/req/timeout-priority-inherit.yml b/spec/score/tq/req/timeout-priority-inherit.yml
index 50486d2c..df4ed949 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