diff options
Diffstat (limited to 'spec/score/tq/req/enqueue-deadlock.yml')
-rw-r--r-- | spec/score/tq/req/enqueue-deadlock.yml | 142 |
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 |