summaryrefslogtreecommitdiffstats
path: root/spec/score/tq/req/enqueue-deadlock.yml
diff options
context:
space:
mode:
Diffstat (limited to 'spec/score/tq/req/enqueue-deadlock.yml')
-rw-r--r--spec/score/tq/req/enqueue-deadlock.yml142
1 files changed, 142 insertions, 0 deletions
diff --git a/spec/score/tq/req/enqueue-deadlock.yml b/spec/score/tq/req/enqueue-deadlock.yml
new file mode 100644
index 00000000..14008cab
--- /dev/null
+++ b/spec/score/tq/req/enqueue-deadlock.yml
@@ -0,0 +1,142 @@
+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: []
+post-conditions:
+- name: Status
+ states:
+ - name: Deadlock
+ test-code: |
+ /* Checked by action */
+ text: |
+ The return status of the directive call shall be derived from
+ ${../../status/if/deadlock:/name}.
+ test-epilogue: null
+ test-prologue: null
+pre-conditions:
+- name: Deadlock
+ states:
+ - name: One
+ test-code: |
+ ctx->more = false;
+ text: |
+ While the owner of the thread queue is enqueued on another thread queue
+ owned by the calling thread.
+ - name: More
+ test-code: |
+ ctx->more = true;
+ text: |
+ While the owner of the thread queue is enqueued on another thread queue
+ owned by a thread other than the calling thread, and so on, while the
+ owner of the last thread queue of this dependency chain is enqueued on a
+ thread queue owned by the calling thread.
+ test-epilogue: null
+ test-prologue: null
+rationale: null
+references: []
+requirement-type: functional
+skip-reasons: {}
+test-action: |
+ Status_Control status;
+
+ TQMutexObtain( ctx->tq_ctx, TQ_MUTEX_A );
+
+ if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ ctx->tq_ctx->other_scheduler_id,
+ PRIO_HIGH
+ );
+ }
+
+ TQSendAndWaitForExecutionStop( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_ENQUEUE );
+
+ if ( ctx->more ) {
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_B_OBTAIN );
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_MUTEX_B_OBTAIN
+ );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_OBTAIN );
+ } else {
+ TQSendAndWaitForExecutionStop(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_MUTEX_A_OBTAIN
+ );
+ }
+
+ status = TQEnqueue( ctx->tq_ctx, TQ_WAIT_FOREVER );
+ T_eq_int( status, TQConvertStatus( ctx->tq_ctx, STATUS_DEADLOCK ) );
+
+ TQMutexRelease( ctx->tq_ctx, TQ_MUTEX_A );
+
+ if ( ctx->more ) {
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_A_RELEASE );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_B, TQ_EVENT_MUTEX_B_RELEASE );
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_MUTEX_B_RELEASE );
+ } else {
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_MUTEX_A_RELEASE );
+ }
+
+ if ( ctx->tq_ctx->enqueue_variant == TQ_ENQUEUE_STICKY ) {
+ TQSend(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ TQ_EVENT_SURRENDER | TQ_EVENT_RUNNER_SYNC
+ );
+ TQSynchronizeRunner();
+ TQSetScheduler(
+ ctx->tq_ctx,
+ TQ_BLOCKER_A,
+ ctx->tq_ctx->runner_scheduler_id,
+ PRIO_HIGH
+ );
+ } else {
+ TQSend( ctx->tq_ctx, TQ_BLOCKER_A, TQ_EVENT_SURRENDER );
+ }
+test-brief: null
+test-cleanup: null
+test-context:
+- brief: |
+ If this member is true, then more than one mutex shall be used for the
+ deadlock scenario.
+ description: null
+ member: |
+ bool more
+test-context-support: null
+test-description: null
+test-header:
+ code: null
+ includes: []
+ local-includes:
+ - tx-thread-queue.h
+ run-params:
+ - description: |
+ is the thread queue context.
+ dir: inout
+ name: tq_ctx
+ specifier: TQContext *${.:name}
+ target: testsuites/validation/tr-tq-enqueue-deadlock.h
+test-includes: []
+test-local-includes:
+- tr-tq-enqueue-deadlock.h
+test-prepare: null
+test-setup: null
+test-stop: null
+test-support: null
+test-target: testsuites/validation/tr-tq-enqueue-deadlock.c
+test-teardown: null
+text: |
+ When the calling thread attempts to be enqueued on the thread queue.
+transition-map:
+- enabled-by: true
+ post-conditions:
+ Status: Deadlock
+ pre-conditions:
+ Deadlock: all
+type: requirement