summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-09-17 18:19:27 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-09-24 12:02:01 +0200
commitc72a3122754bee5f9fd0197efe58afa35dd4de40 (patch)
treefd886d3970dfba42240576bf4cef0ec6827c13b3
parentspec: Specify priority change detail (diff)
downloadrtems-central-c72a3122754bee5f9fd0197efe58afa35dd4de40.tar.bz2
spec: Specify timeout with priority inherit
-rw-r--r--spec/rtems/sem/req/timeout.yml29
-rw-r--r--spec/score/tq/req/flush-fifo.yml11
-rw-r--r--spec/score/tq/req/flush-priority-inherit.yml11
-rw-r--r--spec/score/tq/req/flush-priority.yml11
-rw-r--r--spec/score/tq/req/timeout-priority-inherit.yml414
-rw-r--r--spec/score/tq/req/timeout.yml128
6 files changed, 493 insertions, 111 deletions
diff --git a/spec/rtems/sem/req/timeout.yml b/spec/rtems/sem/req/timeout.yml
index 57b32b07..ce7dc3b4 100644
--- a/spec/rtems/sem/req/timeout.yml
+++ b/spec/rtems/sem/req/timeout.yml
@@ -15,6 +15,12 @@ post-conditions:
text: |
The semaphore obtain timeout actions shall be done as specified by
${/score/tq/req/timeout}.
+ - name: TimeoutPriorityInherit
+ test-code: |
+ ${/score/tq/req/timeout-priority-inherit:/test-run}( &ctx->tq_ctx );
+ text: |
+ The semaphore obtain timeout actions shall be done as specified by
+ ${/score/tq/req/timeout-priority-inherit}.
test-epilogue: null
test-prologue: null
pre-conditions:
@@ -123,6 +129,7 @@ test-includes:
- string.h
test-local-includes:
- tr-tq-timeout.h
+- tr-tq-timeout-priority-inherit.h
- tx-thread-queue.h
- tx-support.h
test-prepare: |
@@ -153,18 +160,18 @@ text: |
transition-map:
- enabled-by: true
post-conditions:
- Action: Timeout
+ Action:
+ - if:
+ pre-conditions:
+ Class:
+ - PrioInherit
+ - MrsP
+ then: TimeoutPriorityInherit
+ - else: Timeout
pre-conditions:
Class: all
Discipline: all
- enabled-by: true
- post-conditions: NoMrsP
- pre-conditions:
- Class:
- - MrsP
- Discipline:
- - Priority
-- enabled-by: true
post-conditions: NeedsPriorityDiscipline
pre-conditions:
Class:
@@ -173,9 +180,9 @@ transition-map:
- MrsP
Discipline:
- FIFO
-- enabled-by: RTEMS_SMP
- post-conditions:
- Action: Timeout
+- enabled-by:
+ not: RTEMS_SMP
+ post-conditions: NoMrsP
pre-conditions:
Class:
- MrsP
diff --git a/spec/score/tq/req/flush-fifo.yml b/spec/score/tq/req/flush-fifo.yml
index f7842175..8c543ad7 100644
--- a/spec/score/tq/req/flush-fifo.yml
+++ b/spec/score/tq/req/flush-fifo.yml
@@ -140,13 +140,20 @@ test-support: |
TQFlush( ctx->tq_ctx );
}
- static void SchedulerEvent( void *arg, const T_scheduler_event *event )
+ static void SchedulerEvent(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
{
Context *ctx;
ctx = arg;
- if ( event->operation == T_SCHEDULER_BLOCK ) {
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_BLOCK
+ ) {
ctx->request.handler = Flush;
ctx->request.arg = ctx;
CallWithinISRSubmit( &ctx->request );
diff --git a/spec/score/tq/req/flush-priority-inherit.yml b/spec/score/tq/req/flush-priority-inherit.yml
index 002933ce..eef2856e 100644
--- a/spec/score/tq/req/flush-priority-inherit.yml
+++ b/spec/score/tq/req/flush-priority-inherit.yml
@@ -251,13 +251,20 @@ test-support: |
TQFlush( ctx->tq_ctx );
}
- static void SchedulerEvent( void *arg, const T_scheduler_event *event )
+ static void SchedulerEvent(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
{
Context *ctx;
ctx = arg;
- if ( event->operation == T_SCHEDULER_BLOCK ) {
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_BLOCK
+ ) {
ctx->request.handler = Flush;
ctx->request.arg = ctx;
CallWithinISRSubmit( &ctx->request );
diff --git a/spec/score/tq/req/flush-priority.yml b/spec/score/tq/req/flush-priority.yml
index 322d81dd..c4bb20c5 100644
--- a/spec/score/tq/req/flush-priority.yml
+++ b/spec/score/tq/req/flush-priority.yml
@@ -165,13 +165,20 @@ test-support: |
TQFlush( ctx->tq_ctx );
}
- static void SchedulerEvent( void *arg, const T_scheduler_event *event )
+ static void SchedulerEvent(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
{
Context *ctx;
ctx = arg;
- if ( event->operation == T_SCHEDULER_BLOCK ) {
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_BLOCK
+ ) {
ctx->request.handler = Flush;
ctx->request.arg = ctx;
CallWithinISRSubmit( &ctx->request );
diff --git a/spec/score/tq/req/timeout-priority-inherit.yml b/spec/score/tq/req/timeout-priority-inherit.yml
new file mode 100644
index 00000000..9d963783
--- /dev/null
+++ b/spec/score/tq/req/timeout-priority-inherit.yml
@@ -0,0 +1,414 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+functional-type: action
+links:
+- role: requirement-refinement
+ uid: ../if/group
+post-conditions:
+- name: Status
+ states:
+ - name: Ok
+ test-code: |
+ T_eq_int(
+ ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ TQConvertStatus( ctx->tq_ctx, STATUS_SUCCESSFUL )
+ );
+ text: |
+ The return status of the directive call shall be derived from
+ ${../../status/if/successful:/name}.
+ - name: Timeout
+ test-code: |
+ T_eq_int(
+ ctx->tq_ctx->status[ TQ_BLOCKER_A ],
+ TQConvertStatus( ctx->tq_ctx, STATUS_TIMEOUT )
+ );
+ text: |
+ The return status of the directive call shall be derived from
+ ${../../status/if/timeout:/name}.
+ test-epilogue: null
+ test-prologue: null
+- name: Unblock
+ states:
+ - name: 'Yes'
+ test-code: |
+ T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
+ T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ text: |
+ The thread of the timeout operation shall be unblocked by the timeout
+ operation.
+ - name: 'No'
+ test-code: |
+ T_eq_ptr( GetUnblock( ctx, &i ), NULL );
+ text: |
+ The thread of the timeout operation shall not be unblocked by the timeout
+ operation.
+ test-epilogue: null
+ test-prologue: |
+ size_t i;
+
+ i = 0;
+pre-conditions:
+- name: EnqueueVariant
+ states:
+ - name: Blocking
+ test-code: |
+ if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_BLOCKS ) {
+ ${.:skip}
+ }
+ text: |
+ Where the thread queue enqueue operation is blocking.
+ - name: Sticky
+ test-code: |
+ if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_STICKY ) {
+ ${.:skip}
+ }
+ text: |
+ Where the thread queue enqueue operation is sticky.
+ test-epilogue: null
+ test-prologue: null
+- name: Scheduler
+ states:
+ - name: Same
+ 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
+ );
+ }
+ text: |
+ While the ${/glossary/scheduler-home:/term} of the thread is equal to the
+ ${/glossary/scheduler-home:/term} of the thread queue owner.
+ - name: Other
+ test-code: |
+ ctx->other_scheduler = true;
+
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ SCHEDULER_B_ID,
+ PRIO_NORMAL
+ );
+ text: |
+ While the ${/glossary/scheduler-home:/term} of the thread is not equal to
+ the ${/glossary/scheduler-home:/term} of the thread queue owner.
+ test-epilogue: null
+ test-prologue: null
+- name: WaitState
+ states:
+ - name: 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 );
+ }
+ text: |
+ While the thread of the timeout operation 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 );
+ text: |
+ While the thread of the timeout operation 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
+ );
+ }
+ text: |
+ While the thread of the timeout operation is in the ready again wait
+ state.
+ test-epilogue: null
+ test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons:
+ StickyHasNoBlocking: |
+ When a sticky thread queue enqueue operation is performed, the blocked wait
+ state cannot occur.
+ OnlyOneCPU: |
+ Where the system was built with SMP support disabled, exactly one scheduler
+ is present in an application using exactly one processor.
+test-action: |
+ /*
+ * The action is performed by the ``WaitState`` pre-condition preparation.
+ */
+test-brief: null
+test-cleanup: |
+ if ( ctx->restore_scheduler ) {
+ RemoveProcessor( SCHEDULER_A_ID, 1 );
+ AddProcessor( SCHEDULER_B_ID, 1 );
+ }
+test-context:
+- brief: |
+ This member contains the call within ISR request.
+ description: null
+ 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.
+ description: null
+ member: |
+ bool other_scheduler
+- brief: |
+ If this member is true, then the processor set of the schedulers shall be
+ restored.
+ description: null
+ member: |
+ bool restore_scheduler
+test-context-support: null
+test-description: null
+test-header:
+ code: null
+ freestanding: false
+ includes: []
+ local-includes:
+ - tx-thread-queue.h
+ run-params:
+ - description: |
+ is the thread queue test context.
+ dir: inout
+ name: tq_ctx
+ specifier: TQContext *${.:name}
+ target: testsuites/validation/tr-tq-timeout-priority-inherit.h
+test-includes:
+- rtems/score/smpimpl.h
+- rtems/score/threadimpl.h
+test-local-includes:
+- tx-support.h
+- tr-tq-timeout-priority-inherit.h
+test-prepare: |
+ ctx->restore_scheduler = false;
+test-setup:
+ brief: null
+ code: |
+ ctx->request.arg = ctx;
+ TQReset( ctx->tq_ctx );
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_HELPER_OTHER,
+ SCHEDULER_A_ID,
+ 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;
+ }
+
+ static const rtems_tcb *GetTCB( Context *ctx, TQWorkerKind worker )
+ {
+ return ctx->tq_ctx->worker_tcb[ worker ];
+ }
+
+ static void Tick( void *arg )
+ {
+ Context *ctx;
+
+ ctx = arg;
+ TQSchedulerRecordStart( ctx->tq_ctx );
+ FinalClockTick();
+ TQSchedulerRecordStop( ctx->tq_ctx );
+ }
+
+ static void SchedulerBlock(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
+ {
+ Context *ctx;
+
+ ctx = arg;
+
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_BLOCK
+ ) {
+ T_scheduler_set_event_handler( NULL, NULL );
+ ctx->request.handler = Tick;
+ CallWithinISRSubmit( &ctx->request );
+ }
+ }
+
+ static void ThreadTimeout( void *arg )
+ {
+ Context *ctx;
+
+ ctx = arg;
+ TQSchedulerRecordStart( ctx->tq_ctx );
+ _Thread_Timeout(
+ &ctx->tq_ctx->worker_tcb[ TQ_BLOCKER_A ]->Timer.Watchdog
+ );
+ TQSchedulerRecordStop( ctx->tq_ctx );
+ }
+
+ static void SchedulerUnblock(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
+ {
+ Context *ctx;
+
+ ctx = arg;
+
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_UNBLOCK
+ ) {
+ T_scheduler_set_event_handler( NULL, NULL );
+
+ if ( ctx->other_scheduler ) {
+ #if defined(RTEMS_SMP)
+ _SMP_Unicast_action( 1, ThreadTimeout, ctx );
+ #else
+ T_unreachable();
+ #endif
+ } else {
+ ctx->request.handler = ThreadTimeout;
+ CallWithinISRSubmit( &ctx->request );
+ }
+ }
+ }
+test-target: testsuites/validation/tr-tq-timeout-priority-inherit.c
+test-teardown:
+ brief: null
+ code: |
+ TQReset( ctx->tq_ctx );
+ description: null
+text: |
+ When the thread queue enqueue operation timed out.
+transition-map:
+- enabled-by: true
+ post-conditions:
+ Status: Timeout
+ Unblock: 'Yes'
+ pre-conditions:
+ EnqueueVariant:
+ - Blocking
+ Scheduler: all
+ WaitState:
+ - Blocked
+- enabled-by: true
+ post-conditions:
+ Status: Timeout
+ Unblock: 'No'
+ pre-conditions:
+ EnqueueVariant: all
+ Scheduler: all
+ WaitState:
+ - IntendToBlock
+- enabled-by: true
+ post-conditions:
+ Status: Ok
+ Unblock: 'No'
+ pre-conditions:
+ EnqueueVariant: all
+ Scheduler: all
+ WaitState:
+ - ReadyAgain
+- enabled-by: true
+ post-conditions: StickyHasNoBlocking
+ pre-conditions:
+ EnqueueVariant:
+ - Sticky
+ Scheduler: all
+ WaitState:
+ - Blocked
+- enabled-by:
+ not: RTEMS_SMP
+ post-conditions: OnlyOneCPU
+ pre-conditions:
+ EnqueueVariant: all
+ Scheduler:
+ - Other
+ WaitState: all
+type: requirement
diff --git a/spec/score/tq/req/timeout.yml b/spec/score/tq/req/timeout.yml
index 7e26d5fc..a0aa387f 100644
--- a/spec/score/tq/req/timeout.yml
+++ b/spec/score/tq/req/timeout.yml
@@ -36,13 +36,13 @@ post-conditions:
T_eq_ptr( GetUnblock( ctx, &i ), GetTCB( ctx, TQ_BLOCKER_A ) );
T_eq_ptr( GetUnblock( ctx, &i ), NULL );
text: |
- The thread of the timeout operation shall not be unblocked by the timeout
+ The thread of the timeout operation shall be unblocked by the timeout
operation.
- name: 'No'
test-code: |
T_eq_ptr( GetUnblock( ctx, &i ), NULL );
text: |
- The thread of the timeout operation shall be unblocked by the timeout
+ The thread of the timeout operation shall not be unblocked by the timeout
operation.
test-epilogue: null
test-prologue: |
@@ -50,70 +50,23 @@ post-conditions:
i = 0;
pre-conditions:
-- name: EnqueueVariant
- states:
- - name: Blocking
- test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_BLOCKS ) {
- ${.:skip}
- }
- text: |
- Where the thread queue enqueue operation is blocking.
- - name: Sticky
- test-code: |
- if ( ctx->tq_ctx->enqueue_variant != TQ_ENQUEUE_STICKY ) {
- ${.:skip}
- }
- text: |
- Where the thread queue enqueue operation is sticky.
- 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 );
- TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
- Yield();
- Tick( ctx );
- TQEnqueueDone( ctx->tq_ctx );
- }
+ TQEnqueuePrepare( ctx->tq_ctx );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
+ Yield();
+ Tick( ctx );
+ TQEnqueueDone( ctx->tq_ctx );
text: |
While the thread of the timeout operation 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 );
- TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
- Yield();
- }
-
+ T_scheduler_set_event_handler( SchedulerBlock, ctx );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
+ Yield();
TQEnqueueDone( ctx->tq_ctx );
text: |
While the thread of the timeout operation is in the intend to block wait
@@ -121,24 +74,11 @@ pre-conditions:
- 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 {
- TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
- Yield();
- T_scheduler_set_event_handler( SchedulerUnblock, ctx );
- TQEnqueueDone( ctx->tq_ctx );
- TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_SURRENDER );
- }
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
+ Yield();
+ T_scheduler_set_event_handler( SchedulerUnblock, ctx );
+ TQEnqueueDone( ctx->tq_ctx );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_SURRENDER );
text: |
While the thread of the timeout operation is in the ready again wait
state.
@@ -147,10 +87,7 @@ pre-conditions:
rationale: null
references: []
requirement-type: functional
-skip-reasons:
- StickyHasNoBlocking: |
- When a sticky thread queue enqueue operation is performed, the blocked wait
- state cannot occur.
+skip-reasons: {}
test-action: |
/*
* The action is performed by the ``WaitState`` pre-condition preparation.
@@ -225,13 +162,20 @@ test-support: |
TQSchedulerRecordStop( ctx->tq_ctx );
}
- static void SchedulerBlock( void *arg, const T_scheduler_event *event )
+ static void SchedulerBlock(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
{
Context *ctx;
ctx = arg;
- if ( event->operation == T_SCHEDULER_BLOCK ) {
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_BLOCK
+ ) {
T_scheduler_set_event_handler( NULL, NULL );
ctx->request.handler = Tick;
CallWithinISRSubmit( &ctx->request );
@@ -250,13 +194,20 @@ test-support: |
TQSchedulerRecordStop( ctx->tq_ctx );
}
- static void SchedulerUnblock( void *arg, const T_scheduler_event *event )
+ static void SchedulerUnblock(
+ void *arg,
+ const T_scheduler_event *event,
+ T_scheduler_when when
+ )
{
Context *ctx;
ctx = arg;
- if ( event->operation == T_SCHEDULER_UNBLOCK ) {
+ if (
+ when == T_SCHEDULER_BEFORE &&
+ event->operation == T_SCHEDULER_UNBLOCK
+ ) {
T_scheduler_set_event_handler( NULL, NULL );
ctx->request.handler = ThreadTimeout;
CallWithinISRSubmit( &ctx->request );
@@ -276,8 +227,6 @@ transition-map:
Status: Timeout
Unblock: 'Yes'
pre-conditions:
- EnqueueVariant:
- - Blocking
WaitState:
- Blocked
- enabled-by: true
@@ -285,7 +234,6 @@ transition-map:
Status: Timeout
Unblock: 'No'
pre-conditions:
- EnqueueVariant: all
WaitState:
- IntendToBlock
- enabled-by: true
@@ -293,14 +241,6 @@ transition-map:
Status: Ok
Unblock: 'No'
pre-conditions:
- EnqueueVariant: all
WaitState:
- ReadyAgain
-- enabled-by: true
- post-conditions: StickyHasNoBlocking
- pre-conditions:
- EnqueueVariant:
- - Sticky
- WaitState:
- - Blocked
type: requirement