diff options
Diffstat (limited to 'spec/rtems')
18 files changed, 989 insertions, 0 deletions
diff --git a/spec/rtems/userext/req/thread-begin-iterate-remove.yml b/spec/rtems/userext/req/thread-begin-iterate-remove.yml new file mode 100644 index 00000000..bd96175f --- /dev/null +++ b/spec/rtems/userext/req/thread-begin-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + begin extensions, when an extension set is removed, the removed extension set + shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-begin-order.yml b/spec/rtems/userext/req/thread-begin-order.yml new file mode 100644 index 00000000..5314defb --- /dev/null +++ b/spec/rtems/userext/req/thread-begin-order.yml @@ -0,0 +1,15 @@ +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: | + The thread begin ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-create-allocator-owner.yml b/spec/rtems/userext/req/thread-create-allocator-owner.yml new file mode 100644 index 00000000..a8525006 --- /dev/null +++ b/spec/rtems/userext/req/thread-create-allocator-owner.yml @@ -0,0 +1,17 @@ +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 +- role: requirement-refinement + uid: /score/object/req/allocator-mutex +functional-type: function +rationale: null +references: [] +requirement-type: functional +text: | + The thread invoking the thread create ${/glossary/userextensions:/term} shall + be the owner of the allocator mutex. +type: requirement diff --git a/spec/rtems/userext/req/thread-create-iterate-remove.yml b/spec/rtems/userext/req/thread-create-iterate-remove.yml new file mode 100644 index 00000000..4fa9e331 --- /dev/null +++ b/spec/rtems/userext/req/thread-create-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + create extensions, when an extension set is removed, the removed extension + set shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-create-order.yml b/spec/rtems/userext/req/thread-create-order.yml new file mode 100644 index 00000000..418d3c11 --- /dev/null +++ b/spec/rtems/userext/req/thread-create-order.yml @@ -0,0 +1,15 @@ +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: | + The thread create ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-delete-allocator-owner.yml b/spec/rtems/userext/req/thread-delete-allocator-owner.yml new file mode 100644 index 00000000..13216996 --- /dev/null +++ b/spec/rtems/userext/req/thread-delete-allocator-owner.yml @@ -0,0 +1,17 @@ +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 +- role: requirement-refinement + uid: /score/object/req/allocator-mutex +functional-type: function +rationale: null +references: [] +requirement-type: functional +text: | + The thread invoking the thread delete ${/glossary/userextensions:/term} shall + be the owner of the allocator mutex. +type: requirement diff --git a/spec/rtems/userext/req/thread-delete-iterate-remove.yml b/spec/rtems/userext/req/thread-delete-iterate-remove.yml new file mode 100644 index 00000000..59a17bd3 --- /dev/null +++ b/spec/rtems/userext/req/thread-delete-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + delete extensions, when an extension set is removed, the removed extension + set shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-delete-order.yml b/spec/rtems/userext/req/thread-delete-order.yml new file mode 100644 index 00000000..d3fc1710 --- /dev/null +++ b/spec/rtems/userext/req/thread-delete-order.yml @@ -0,0 +1,15 @@ +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: | + The thread delete ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-reverse-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-exitted-iterate-remove.yml b/spec/rtems/userext/req/thread-exitted-iterate-remove.yml new file mode 100644 index 00000000..aa53e3b2 --- /dev/null +++ b/spec/rtems/userext/req/thread-exitted-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + exitted extensions, when an extension set is removed, the removed extension + set shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-exitted-order.yml b/spec/rtems/userext/req/thread-exitted-order.yml new file mode 100644 index 00000000..64c3f3ff --- /dev/null +++ b/spec/rtems/userext/req/thread-exitted-order.yml @@ -0,0 +1,15 @@ +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: | + The thread exitted ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-restart-iterate-remove.yml b/spec/rtems/userext/req/thread-restart-iterate-remove.yml new file mode 100644 index 00000000..7b75e5d5 --- /dev/null +++ b/spec/rtems/userext/req/thread-restart-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + restart extensions, when an extension set is removed, the removed extension + set shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-restart-order.yml b/spec/rtems/userext/req/thread-restart-order.yml new file mode 100644 index 00000000..6d1546a5 --- /dev/null +++ b/spec/rtems/userext/req/thread-restart-order.yml @@ -0,0 +1,15 @@ +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: | + The thread restart ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-start-iterate-remove.yml b/spec/rtems/userext/req/thread-start-iterate-remove.yml new file mode 100644 index 00000000..6059efea --- /dev/null +++ b/spec/rtems/userext/req/thread-start-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + start extensions, when an extension set is removed, the removed extension set + shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-start-order.yml b/spec/rtems/userext/req/thread-start-order.yml new file mode 100644 index 00000000..98ff2bd4 --- /dev/null +++ b/spec/rtems/userext/req/thread-start-order.yml @@ -0,0 +1,15 @@ +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: | + The thread start ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-switch-order.yml b/spec/rtems/userext/req/thread-switch-order.yml new file mode 100644 index 00000000..754633f9 --- /dev/null +++ b/spec/rtems/userext/req/thread-switch-order.yml @@ -0,0 +1,15 @@ +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: | + The thread switch ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-forward-order:/term}. +type: requirement diff --git a/spec/rtems/userext/req/thread-terminate-iterate-remove.yml b/spec/rtems/userext/req/thread-terminate-iterate-remove.yml new file mode 100644 index 00000000..f5522854 --- /dev/null +++ b/spec/rtems/userext/req/thread-terminate-iterate-remove.yml @@ -0,0 +1,17 @@ +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 the ${/glossary/userextensions:/term} are iterated to invoke the thread + terminate extensions, when an extension set is removed, the removed extension + set shall not be a next extension set for any iteration in progress after the + removal. +type: requirement diff --git a/spec/rtems/userext/req/thread-terminate-order.yml b/spec/rtems/userext/req/thread-terminate-order.yml new file mode 100644 index 00000000..6ceb4ad7 --- /dev/null +++ b/spec/rtems/userext/req/thread-terminate-order.yml @@ -0,0 +1,15 @@ +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: | + The thread terminate ${/glossary/userextensions:/term} shall be invoked in + ${/glossary/extension-reverse-order:/term}. +type: requirement diff --git a/spec/rtems/userext/val/userext.yml b/spec/rtems/userext/val/userext.yml new file mode 100644 index 00000000..e85f6197 --- /dev/null +++ b/spec/rtems/userext/val/userext.yml @@ -0,0 +1,716 @@ +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 five dynamic extensions. Switch to a started thread. Delete three + dynamic extension during the thread begin invocation. Clean up the used + resources. + action-code: | + rtems_tcb *executing; + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_LOW ); + thread = GetThread( id ); + StartTask( id, BeginWorker, NULL ); + executing = StartTestCase( THREAD_BEGIN ); + SetPriority( id, PRIO_HIGH ); + KillZombies(); + checks: + - brief: | + Check that the thread switch extensions were invoked in the right order + before the thread begin extensions. + code: | + CheckForward( THREAD_SWITCH, 1, 1, executing, thread ); + links: + - role: validation + uid: ../req/thread-switch-order + - brief: | + Check that the thread begin extensions were invoked in the right order. + code: | + CheckForward( THREAD_BEGIN, 8, 1, thread, NULL ); + links: + - role: validation + uid: ../req/thread-begin-iterate-remove + - role: validation + uid: ../req/thread-begin-order + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread begin extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_BEGIN ); + links: + - role: validation + uid: ../req/thread-begin-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Create a thread. Delete three dynamic + extension during the thread create invocation. Clean up the used + resources. + action-code: | + rtems_tcb *executing; + rtems_tcb *thread; + rtems_id id; + + executing = StartTestCase( THREAD_CREATE ); + id = CreateTask( "WORK", PRIO_NORMAL ); + thread = GetThread( id ); + StopTestCase(); + DeleteTask( id ); + KillZombies(); + checks: + - brief: | + Check that the thread create extensions were invoked in the right order. + code: | + CheckForward( THREAD_CREATE, 1, 1, executing, thread ); + links: + - role: validation + uid: ../req/thread-create-iterate-remove + - role: validation + uid: ../req/thread-create-order + - brief: | + Check that the thread create extensions were invoked under protection of + the allocator mutex. + code: | + T_eq_u32( thread_create_allocator_owner_count, 6 ); + links: + - role: validation + uid: ../req/thread-create-allocator-owner + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread create extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_CREATE ); + links: + - role: validation + uid: ../req/thread-create-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Delete a thread. Delete three dynamic + extension during the thread delete invocation. Clean up the used + resources. + action-code: | + rtems_tcb *executing; + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_NORMAL ); + thread = GetThread( id ); + DeleteTask( id ); + executing = StartTestCase( THREAD_DELETE ); + KillZombies(); + StopTestCase(); + checks: + - brief: | + Check that the thread delete extensions were invoked in the right order. + code: | + CheckReverse( THREAD_DELETE, 1, 1, executing, thread ); + links: + - role: validation + uid: ../req/thread-delete-iterate-remove + - role: validation + uid: ../req/thread-delete-order + - brief: | + Check that the thread delete extensions were invoked under protection of + the allocator mutex. + code: | + T_eq_u32( thread_delete_allocator_owner_count, 6 ); + links: + - role: validation + uid: ../req/thread-delete-allocator-owner + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread delete extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_DELETE ); + links: + - role: validation + uid: ../req/thread-delete-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Return from a thread entry. Delete three + dynamic extension during the thread exitted invocation. Clean up the used + resources. + action-code: | + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, ExittedWorker, NULL ); + KillZombies(); + checks: + - brief: | + Check that the thread exitted extensions were invoked in the right order. + code: | + CheckForward( THREAD_EXITTED, 1, 1, thread, NULL ); + links: + - role: validation + uid: ../req/thread-exitted-iterate-remove + - role: validation + uid: ../req/thread-exitted-order + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + CheckReverse( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread exitted extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_EXITTED ); + links: + - role: validation + uid: ../req/thread-exitted-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Restart a thread. Delete three + dynamic extension during the thread restart invocation. Clean up the used + resources. + action-code: | + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, RestartWorker, NULL ); + KillZombies(); + checks: + - brief: | + Check that the thread restart extensions were invoked in the right order. + code: | + CheckForward( THREAD_RESTART, 1, 1, thread, thread ); + links: + - role: validation + uid: ../req/thread-restart-iterate-remove + - role: validation + uid: ../req/thread-restart-order + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + CheckForward( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread restart extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_RESTART ); + links: + - role: validation + uid: ../req/thread-restart-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Start a thread. Delete three dynamic + extension during the thread start invocation. Clean up the used resources. + action-code: | + rtems_tcb *executing; + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_LOW ); + thread = GetThread( id ); + executing = StartTestCase( THREAD_START ); + StartTask( id, StartWorker, NULL ); + StopTestCase(); + DeleteTask( id ); + KillZombies(); + checks: + - brief: | + Check that the thread start extensions were invoked in the right order. + code: | + CheckForward( THREAD_START, 1, 1, executing, thread ); + links: + - role: validation + uid: ../req/thread-start-iterate-remove + - role: validation + uid: ../req/thread-start-order + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + CheckForward( THREAD_TERMINATE, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread start extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_START ); + links: + - role: validation + uid: ../req/thread-start-iterate-remove + links: [] +- action-brief: | + Create five dynamic extensions. Terminate a thread. Delete three dynamic + extension during the thread terminate invocation. Clean up the used + resources. + action-code: | + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, TerminateWorker, NULL ); + KillZombies(); + checks: + - brief: | + Check that the thread terminate extensions were invoked in the right + order. + code: | + CheckReverse( THREAD_TERMINATE, 1, 1, thread, NULL ); + links: + - role: validation + uid: ../req/thread-terminate-iterate-remove + - role: validation + uid: ../req/thread-terminate-order + - brief: | + Check that the other extensions were not invoked. + code: | + CheckForward( THREAD_BEGIN, 0, 0, NULL, NULL ); + CheckForward( THREAD_EXITTED, 0, 0, NULL, NULL ); + CheckForward( THREAD_CREATE, 0, 0, NULL, NULL ); + CheckReverse( THREAD_DELETE, 0, 0, NULL, NULL ); + CheckForward( THREAD_RESTART, 0, 0, NULL, NULL ); + CheckForward( THREAD_START, 0, 0, NULL, NULL ); + CheckForward( THREAD_SWITCH, 0, 0, NULL, NULL ); + links: [] + - brief: | + Check that the thread terminate extension of the extension set deleted + before its turn in the invocation was not invoked. + code: | + CheckDeletedNotInvoked( THREAD_TERMINATE ); + links: + - role: validation + uid: ../req/thread-terminate-iterate-remove + links: [] +test-brief: | + Tests the thread user extensions. +test-context: [] +test-context-support: null +test-description: null +test-header: null +test-includes: +- rtems/score/atomic.h +- rtems/score/apimutex.h +- string.h +test-local-includes: +- tc-userext.h +- tx-support.h +test-setup: + brief: null + code: | + SetSelfPriority( PRIO_NORMAL ); + description: null +test-stop: null +test-support: | + typedef struct { + unsigned int counter; + rtems_tcb *executing; + rtems_tcb *thread; + } ExtensionEvent; + + typedef enum { + THREAD_BEGIN, + THREAD_CREATE, + THREAD_DELETE, + THREAD_EXITTED, + THREAD_RESTART, + THREAD_START, + THREAD_SWITCH, + THREAD_TERMINATE, + EXTENSION_KIND_COUNT + } ExtensionKind; + + static rtems_id extension_ids[ 7 ]; + + static Atomic_Uint extension_counter[ RTEMS_ARRAY_SIZE( extension_ids ) ] + [ EXTENSION_KIND_COUNT ]; + + static ExtensionEvent extension_events[ RTEMS_ARRAY_SIZE( extension_ids ) ] + [ EXTENSION_KIND_COUNT ][ 3 ]; + + static Atomic_Uint global_counter; + + static ExtensionKind extension_under_test = EXTENSION_KIND_COUNT; + + static uint32_t thread_create_allocator_owner_count; + + static uint32_t thread_delete_allocator_owner_count; + + static void StopTestCase( void ) + { + ExtensionKind kind; + rtems_status_code sc; + + kind = extension_under_test; + extension_under_test = EXTENSION_KIND_COUNT; + + sc = rtems_extension_delete( extension_ids[ 2 ] ); + T_rsc_success( sc ); + + if ( kind == THREAD_SWITCH ) { + sc = rtems_extension_delete( extension_ids[ 3 ] ); + T_rsc_success( sc ); + + sc = rtems_extension_delete( extension_ids[ 4 ] ); + T_rsc_success( sc ); + + sc = rtems_extension_delete( extension_ids[ 5 ] ); + T_rsc_success( sc ); + } + + sc = rtems_extension_delete( extension_ids[ 6 ] ); + T_rsc_success( sc ); + } + + static void Extension( + size_t index, + ExtensionKind kind, + rtems_tcb *executing, + rtems_tcb *thread + ) + { + unsigned int gc; + unsigned int c; + rtems_status_code sc; + + if ( extension_under_test == EXTENSION_KIND_COUNT ) { + return; + } + + if ( kind == THREAD_CREATE && _RTEMS_Allocator_is_owner() ) { + ++thread_create_allocator_owner_count; + } + + if ( kind == THREAD_DELETE && _RTEMS_Allocator_is_owner() ) { + ++thread_delete_allocator_owner_count; + } + + gc = _Atomic_Fetch_add_uint( &global_counter, 1, ATOMIC_ORDER_RELAXED ) + 1; + c = _Atomic_Fetch_add_uint( + &extension_counter[ index ][ kind ], + 1, + ATOMIC_ORDER_RELAXED + ); + + if ( c < RTEMS_ARRAY_SIZE( extension_events[ index ][ kind ] ) ) { + extension_events[ index ][ kind ][ c ].counter = gc; + extension_events[ index ][ kind ][ c ].executing = executing; + extension_events[ index ][ kind ][ c ].thread = thread; + } + + if ( kind == THREAD_SWITCH ) { + /* Extension set deletion is not allowed in thread switch extensions */ + return; + } + + if ( kind != extension_under_test ) { + return; + } + + if ( kind == THREAD_DELETE || kind == THREAD_TERMINATE ) { + if ( index == 6 ) { + sc = rtems_extension_delete( extension_ids[ 5 ] ); + T_rsc_success( sc ); + } else if ( index == 3 ) { + sc = rtems_extension_delete( extension_ids[ 3 ] ); + T_rsc_success( sc ); + } else if ( index == 2 ) { + sc = rtems_extension_delete( extension_ids[ 4 ] ); + T_rsc_success( sc ); + } + } else { + if ( index == 2 ) { + sc = rtems_extension_delete( extension_ids[ 3 ] ); + T_rsc_success( sc ); + } else if ( index == 5 ) { + sc = rtems_extension_delete( extension_ids[ 5 ] ); + T_rsc_success( sc ); + } else if ( index == 6 ) { + sc = rtems_extension_delete( extension_ids[ 4 ] ); + T_rsc_success( sc ); + } + } + + if ( index == 6 && ( kind == THREAD_EXITTED || kind == THREAD_RESTART ) ) { + StopTestCase(); + rtems_task_exit(); + } + + if ( index == 0 && kind == THREAD_TERMINATE ) { + StopTestCase(); + } + } + + #define DEFINE_EXTENSIONS( index, linkage ) \ + linkage void ThreadBeginExtension##index( rtems_tcb *executing ) \ + { \ + Extension( index, THREAD_BEGIN, executing, NULL ); \ + } \ + linkage bool ThreadCreateExtension##index( \ + rtems_tcb *executing, \ + rtems_tcb *created \ + ) \ + { \ + Extension( index, THREAD_CREATE, executing, created ); \ + return true; \ + } \ + linkage void ThreadDeleteExtension##index( \ + rtems_tcb *executing, \ + rtems_tcb *deleted \ + ) \ + { \ + Extension( index, THREAD_DELETE, executing, deleted ); \ + } \ + linkage void ThreadExittedExtension##index( rtems_tcb *executing ) \ + { \ + Extension( index, THREAD_EXITTED, executing, NULL ); \ + } \ + linkage void ThreadRestartExtension##index( \ + rtems_tcb *executing, \ + rtems_tcb *restarted \ + ) \ + { \ + Extension( index, THREAD_RESTART, executing, restarted ); \ + } \ + linkage void ThreadStartExtension##index( \ + rtems_tcb *executing, \ + rtems_tcb *started \ + ) \ + { \ + Extension( index, THREAD_START, executing, started ); \ + } \ + linkage void ThreadSwitchExtension##index( \ + rtems_tcb *executing, \ + rtems_tcb *heir \ + ) \ + { \ + Extension( index, THREAD_SWITCH, executing, heir ); \ + } \ + linkage void ThreadTerminateExtension##index( rtems_tcb *executing ) \ + { \ + Extension( index, THREAD_TERMINATE, executing, NULL ); \ + } + + DEFINE_EXTENSIONS( 0, ) + DEFINE_EXTENSIONS( 1, ) + + #define DEFINE_EXTENSIONS_AND_TABLE( index ) \ + DEFINE_EXTENSIONS( index, static ) \ + static const rtems_extensions_table table_##index = { \ + .thread_begin = ThreadBeginExtension##index, \ + .thread_create = ThreadCreateExtension##index, \ + .thread_delete = ThreadDeleteExtension##index, \ + .thread_exitted = ThreadExittedExtension##index, \ + .thread_restart = ThreadRestartExtension##index, \ + .thread_start = ThreadStartExtension##index, \ + .thread_switch = ThreadSwitchExtension##index, \ + .thread_terminate = ThreadTerminateExtension##index \ + } + + DEFINE_EXTENSIONS_AND_TABLE( 2 ); + DEFINE_EXTENSIONS_AND_TABLE( 3 ); + DEFINE_EXTENSIONS_AND_TABLE( 4 ); + DEFINE_EXTENSIONS_AND_TABLE( 5 ); + DEFINE_EXTENSIONS_AND_TABLE( 6 ); + + static const rtems_extensions_table * const tables[] = { + NULL, + NULL, + &table_2, + &table_3, + &table_4, + &table_5, + &table_6 + }; + + static rtems_tcb *StartTestCase( ExtensionKind kind ) + { + size_t i; + + thread_create_allocator_owner_count = 0; + thread_delete_allocator_owner_count = 0; + _Atomic_Store_uint( &global_counter, 0, ATOMIC_ORDER_RELAXED ); + memset( extension_counter, 0, sizeof( extension_counter ) ); + memset( extension_events, 0, sizeof( extension_events ) ); + + extension_under_test = kind; + + for ( i = 2; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) { + rtems_status_code sc; + + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '2' + i ), + tables[ i ], + &extension_ids[ i ] + ); + T_rsc_success( sc ); + } + + return GetExecuting(); + } + + static void CheckForward( + ExtensionKind kind, + unsigned int counter, + unsigned int increment, + rtems_tcb *executing, + rtems_tcb *thread + ) + { + size_t i; + + for ( i = 0; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) { + if ( i == 3 && kind != THREAD_SWITCH ) { + continue; + } + + if ( counter == 0 ) { + T_eq_uint( extension_counter[ i ][ kind ], 0 ); + } else { + T_eq_uint( extension_counter[ i ][ kind ], 1 ); + T_eq_uint( extension_events[ i ][ kind ][ 0 ].counter, counter ); + T_eq_ptr( extension_events[ i ][ kind ][ 0 ].executing, executing ); + T_eq_ptr( extension_events[ i ][ kind ][ 0 ].thread, thread ); + + counter += increment; + } + } + } + + static void CheckReverse( + ExtensionKind kind, + unsigned int counter, + unsigned int increment, + rtems_tcb *executing, + rtems_tcb *thread + ) + { + size_t i; + + for ( i = 0; i < RTEMS_ARRAY_SIZE( extension_ids ); ++i ) { + if ( i == 5 && kind != THREAD_SWITCH ) { + continue; + } + + if ( counter == 0 ) { + T_eq_uint( extension_counter[ i ][ kind ], 0 ); + } else { + T_eq_uint( extension_counter[ i ][ kind ], 1 ); + T_eq_uint( + extension_events[ i ][ kind ][ 0 ].counter, + 7 - counter + ); + T_eq_ptr( extension_events[ i ][ kind ][ 0 ].executing, executing ); + T_eq_ptr( extension_events[ i ][ kind ][ 0 ].thread, thread ); + + counter += increment; + } + } + } + + static void CheckDeletedNotInvoked( ExtensionKind kind ) + { + size_t index; + + if ( kind == THREAD_DELETE || kind == THREAD_TERMINATE ) { + index = 5; + } else { + index = 3; + } + + T_eq_uint( extension_events[ index ][ kind ][ 0 ].counter, 0 ); + T_null( extension_events[ index ][ kind ][ 0 ].executing ); + T_null( extension_events[ index ][ kind ][ 0 ].thread ); + } + + static void BeginWorker( rtems_task_argument arg ) + { + T_eq_u32( arg, 0 ); + StopTestCase(); + rtems_task_exit(); + } + + static void ExittedWorker( rtems_task_argument arg ) + { + T_eq_u32( arg, 0 ); + (void) StartTestCase( THREAD_EXITTED ); + } + + static void RestartWorker( rtems_task_argument arg ) + { + T_eq_u32( arg, 0 ); + (void) StartTestCase( THREAD_RESTART ); + (void) rtems_task_restart( RTEMS_SELF, 1 ); + } + + static void StartWorker( rtems_task_argument arg ) + { + (void) arg; + T_unreachable(); + } + + static void TerminateWorker( rtems_task_argument arg ) + { + T_eq_u32( arg, 0 ); + (void) StartTestCase( THREAD_TERMINATE ); + rtems_task_exit(); + } +test-target: testsuites/validation/tc-userext.c +test-teardown: + brief: null + code: | + RestoreRunnerPriority(); + description: null +type: test-case |