summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-08-10 13:59:04 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-08-10 13:59:04 +0200
commit5008d31bef18c0c3d76b9ed6ad4daecee5d3fa7c (patch)
treea6239d60bfafcb8c7a2465719d9ada29ed958d7f
parentspec: Improve rtems_partition_return_buffer() (diff)
downloadrtems-central-5008d31bef18c0c3d76b9ed6ad4daecee5d3fa7c.tar.bz2
spec: Specify a thread termination error condition
-rw-r--r--spec/score/thread/req/cancel-killer.yml16
-rw-r--r--spec/score/thread/val/thread.yml134
2 files changed, 150 insertions, 0 deletions
diff --git a/spec/score/thread/req/cancel-killer.yml b/spec/score/thread/req/cancel-killer.yml
new file mode 100644
index 00000000..77be068b
--- /dev/null
+++ b/spec/score/thread/req/cancel-killer.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+enabled-by: true
+links:
+- role: requirement-refinement
+ uid: ../if/group
+functional-type: function
+rationale: null
+references: []
+requirement-type: functional
+text: |
+ While a terminating thread has exactly one joining thread, while the joining
+ thread can be cancelled, if the terminating thread cancels the joining
+ thread, then the terminating thread shall wait for threads to join.
+type: requirement
diff --git a/spec/score/thread/val/thread.yml b/spec/score/thread/val/thread.yml
new file mode 100644
index 00000000..61ea71c5
--- /dev/null
+++ b/spec/score/thread/val/thread.yml
@@ -0,0 +1,134 @@
+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
+links: []
+test-actions:
+- action-brief: |
+ Create an extension set with a thread terminate extension which deletes the
+ killer task if it is invoked for the worker task. Create and start the
+ worker task. Create and start the killer task. The killer task deletes
+ the worker task.
+ action-code: |
+ rtems_extensions_table table = {
+ .thread_terminate = TaskTerminate
+ };
+ rtems_status_code sc;
+ rtems_id id;
+ rtems_tcb *worker_tcb;
+
+ sc = rtems_extension_create(
+ rtems_build_name( 'T', 'E', 'S', 'T' ),
+ &table,
+ &id
+ );
+ T_rsc_success( sc );
+
+ SetSelfPriority( PRIO_NORMAL );
+ ctx->worker_id = CreateTask( "WORK", PRIO_HIGH );
+ worker_tcb = GetThread( ctx->worker_id );
+ StartTask( ctx->worker_id, WorkerTask, NULL );
+ ctx->killer_id = CreateTask( "KILL", PRIO_HIGH );
+ StartTask( ctx->killer_id, KillerTask, ctx );
+ checks:
+ - brief: |
+ Check that the killer task was deleted.
+ code: |
+ sc = rtems_event_send( ctx->killer_id, RTEMS_EVENT_0 );
+ T_rsc( sc, RTEMS_INVALID_ID );
+ links: []
+ - brief: |
+ Check that the worker task still exists.
+ code: |
+ sc = rtems_event_send( ctx->worker_id, RTEMS_EVENT_0 );
+ T_rsc_success( sc );
+ links: []
+ - brief: |
+ Check that the life of the worker task is protected and terminating.
+ code: |
+ T_eq_int(
+ worker_tcb->Life.state,
+ THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING
+ );
+ links: []
+ - brief: |
+ Check that the worker task is waiting for a joining thread.
+ code: |
+ T_eq_u32(
+ worker_tcb->current_state,
+ STATES_WAITING_FOR_JOIN_AT_EXIT
+ );
+ links: []
+ - brief: |
+ Delete the worker task using brute force.
+ code: |
+ worker_tcb->Life.state = THREAD_LIFE_DETACHED |
+ THREAD_LIFE_PROTECTED | THREAD_LIFE_TERMINATING;
+ _Thread_Clear_state( worker_tcb, STATES_WAITING_FOR_JOIN_AT_EXIT );
+ links: []
+ - brief: |
+ Clean up all used resources.
+ code: |
+ KillZombies();
+ RestoreRunnerPriority();
+
+ sc = rtems_extension_delete( id );
+ T_rsc_success( sc );
+ links: []
+ links:
+ - role: validation
+ uid: ../req/cancel-killer
+test-brief: |
+ Tests general thread behaviour.
+test-context:
+- brief: |
+ This member contains the worker task identifier.
+ description: null
+ member: |
+ rtems_id worker_id
+- brief: |
+ This member contains the killer task identifier.
+ description: null
+ member: |
+ rtems_id killer_id
+test-context-support: null
+test-description: null
+test-header: null
+test-includes:
+- rtems.h
+- rtems/score/statesimpl.h
+- rtems/score/threadimpl.h
+test-local-includes:
+- tx-support.h
+test-setup: null
+test-stop: null
+test-support: |
+ typedef ScoreThreadValThread_Context Context;
+
+ static void TaskTerminate( rtems_tcb *executing )
+ {
+ Context *ctx;
+
+ ctx = T_fixture_context();
+
+ if ( ctx->worker_id == executing->Object.id ) {
+ DeleteTask( ctx->killer_id );
+ }
+ }
+
+ static void WorkerTask( rtems_task_argument arg )
+ {
+ (void) arg;
+ SuspendSelf();
+ }
+
+ static void KillerTask( rtems_task_argument arg )
+ {
+ Context *ctx;
+
+ ctx = (Context *) arg;
+ DeleteTask( ctx->worker_id );
+ }
+test-target: testsuites/validation/tc-score-thread.c
+test-teardown: null
+type: test-case