diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-08 15:45:55 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2021-10-08 16:10:12 +0200 |
commit | a384c7655af1f238b3627b604f3102b0dac7b077 (patch) | |
tree | 862f897be0da1b91f5267c7333be947307d25fd0 /spec/score/tq/req/timeout-priority-inherit.yml | |
parent | spec: Refine TQ surrender priority inherit spec (diff) | |
download | rtems-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.yml | 1104 |
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 |