From bc8f3b910572ae325777c54e86d6f4e5f5416512 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sun, 8 Aug 2021 16:12:39 +0200 Subject: validation: Test user extensions --- spec/build/testsuites/validation/grp.yml | 2 + spec/build/testsuites/validation/userext.yml | 21 + testsuites/validation/tc-terminate.c | 154 +++-- testsuites/validation/tc-terminate.h | 61 -- testsuites/validation/tc-userext.c | 849 +++++++++++++++++++++++++++ testsuites/validation/tc-userext.h | 93 +++ testsuites/validation/ts-default.h | 2 +- testsuites/validation/ts-terminate.c | 4 +- testsuites/validation/ts-userext.c | 97 +++ 9 files changed, 1171 insertions(+), 112 deletions(-) create mode 100644 spec/build/testsuites/validation/userext.yml delete mode 100644 testsuites/validation/tc-terminate.h create mode 100644 testsuites/validation/tc-userext.c create mode 100644 testsuites/validation/tc-userext.h create mode 100644 testsuites/validation/ts-userext.c diff --git a/spec/build/testsuites/validation/grp.yml b/spec/build/testsuites/validation/grp.yml index 3f3b93922f..746894b891 100644 --- a/spec/build/testsuites/validation/grp.yml +++ b/spec/build/testsuites/validation/grp.yml @@ -42,6 +42,8 @@ links: uid: performance-0 - role: build-dependency uid: terminate +- role: build-dependency + uid: userext - role: build-dependency uid: validation-0 - role: build-dependency diff --git a/spec/build/testsuites/validation/userext.yml b/spec/build/testsuites/validation/userext.yml new file mode 100644 index 0000000000..665f2e9622 --- /dev/null +++ b/spec/build/testsuites/validation/userext.yml @@ -0,0 +1,21 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +build-type: test-program +cflags: [] +copyrights: +- Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) +cppflags: [] +cxxflags: [] +enabled-by: true +features: c cprogram +includes: [] +ldflags: [] +links: [] +source: +- testsuites/validation/tc-userext.c +- testsuites/validation/ts-userext.c +stlib: [] +target: testsuites/validation/ts-userext.exe +type: build +use-after: +- validation +use-before: [] diff --git a/testsuites/validation/tc-terminate.c b/testsuites/validation/tc-terminate.c index 3d31f4720b..ae21d205cd 100644 --- a/testsuites/validation/tc-terminate.c +++ b/testsuites/validation/tc-terminate.c @@ -61,7 +61,7 @@ #include #include -#include "tc-terminate.h" +#include "tc-userext.h" #include @@ -75,8 +75,8 @@ * * This test case performs the following actions: * - * - Create three dynamic extensions. Call the system termination procedure. - * Delete one dynamic extension during the fatal extension invocation. + * - Create five dynamic extensions. Call the system termination procedure. + * Delete three dynamic extension during the fatal extension invocation. * Delete the two remaining dynamic extensions. * * - Check that the fatal extensions were invoked with the expected source. @@ -114,7 +114,7 @@ typedef struct { static Atomic_Uint counter; -static FatalInfo info[ 5 ]; +static FatalInfo info[ 7 ]; static bool test_case_active; @@ -128,7 +128,7 @@ static rtems_fatal_source halt_source; static rtems_fatal_code halt_code; -static rtems_id extension_id_4; +static rtems_id extension_ids[ 7 ]; static unsigned int GetCounter( void ) { @@ -195,7 +195,12 @@ static void FatalExtension2( rtems_fatal_code code ) { + rtems_status_code sc; + FatalExtension( source, always_set_to_false, code, 2 ); + + sc = rtems_extension_delete( extension_ids[ 3 ] ); + T_quiet_rsc_success( sc ); } static void FatalExtension3( @@ -203,35 +208,56 @@ static void FatalExtension3( bool always_set_to_false, rtems_fatal_code code ) +{ + FatalExtension( source, always_set_to_false, code, 3 ); +} + +static void FatalExtension4( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) +{ + FatalExtension( source, always_set_to_false, code, 4 ); +} + +static void FatalExtension5( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +) { rtems_status_code sc; - FatalExtension( source, always_set_to_false, code, 3 ); + FatalExtension( source, always_set_to_false, code, 5 ); - sc = rtems_extension_delete( extension_id_4 ); + sc = rtems_extension_delete( extension_ids[ 5 ] ); T_quiet_rsc_success( sc ); } -static void FatalExtension4( +static void FatalExtension6( rtems_fatal_source source, bool always_set_to_false, rtems_fatal_code code ) { - FatalExtension( source, always_set_to_false, code, 3 ); + rtems_status_code sc; + + FatalExtension( source, always_set_to_false, code, 6 ); + + sc = rtems_extension_delete( extension_ids[ 4 ] ); + T_quiet_rsc_success( sc ); } /** - * @brief Create three dynamic extensions. Call the system termination - * procedure. Delete one dynamic extension during the fatal extension - * invocation. Delete the two remaining dynamic extensions. + * @brief Create five dynamic extensions. Call the system termination + * procedure. Delete three dynamic extension during the fatal extension + * invocation. Delete the two remaining dynamic extensions. */ static void ScoreInterrValTerminate_Action_0( void ) { rtems_status_code sc; rtems_extensions_table table; - rtems_id id_2; - rtems_id id_3; bool shutdown_ok; #if defined(RTEMS_SMP) @@ -246,7 +272,7 @@ static void ScoreInterrValTerminate_Action_0( void ) sc = rtems_extension_create( rtems_build_name( ' ', ' ', ' ', '2' ), &table, - &id_2 + &extension_ids[ 2 ] ); T_step_rsc_success( 0, sc ); @@ -254,7 +280,7 @@ static void ScoreInterrValTerminate_Action_0( void ) sc = rtems_extension_create( rtems_build_name( ' ', ' ', ' ', '3' ), &table, - &id_3 + &extension_ids[ 3 ] ); T_step_rsc_success( 1, sc ); @@ -262,10 +288,26 @@ static void ScoreInterrValTerminate_Action_0( void ) sc = rtems_extension_create( rtems_build_name( ' ', ' ', ' ', '4' ), &table, - &extension_id_4 + &extension_ids[ 4 ] ); T_step_rsc_success( 2, sc ); + table.fatal = FatalExtension5; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '5' ), + &table, + &extension_ids[ 5 ] + ); + T_step_rsc_success( 3, sc ); + + table.fatal = FatalExtension6; + sc = rtems_extension_create( + rtems_build_name( ' ', ' ', ' ', '6' ), + &table, + &extension_ids[ 6 ] + ); + T_step_rsc_success( 4, sc ); + test_case_active = true; if ( setjmp( before_terminate ) == 0 ) { @@ -274,33 +316,43 @@ static void ScoreInterrValTerminate_Action_0( void ) test_case_active = false; - sc = rtems_extension_delete( id_2 ); - T_step_rsc_success( 3, sc ); + sc = rtems_extension_delete( extension_ids[ 2 ] ); + T_step_rsc_success( 5, sc ); - sc = rtems_extension_delete( id_3 ); - T_step_rsc_success( 4, sc ); + sc = rtems_extension_delete( extension_ids[ 6 ] ); + T_step_rsc_success( 6, sc ); /* * Check that the fatal extensions were invoked with the expected source. */ T_step_eq_int( - 5, + 7, info[ 0 ].source, RTEMS_FATAL_SOURCE_APPLICATION ); T_step_eq_int( - 6, + 8, info[ 1 ].source, RTEMS_FATAL_SOURCE_APPLICATION ); T_step_eq_int( - 7, + 9, info[ 2 ].source, RTEMS_FATAL_SOURCE_APPLICATION ); T_step_eq_int( - 8, - info[ 3 ].source, + 10, + info[ 4 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 11, + info[ 5 ].source, + RTEMS_FATAL_SOURCE_APPLICATION + ); + T_step_eq_int( + 12, + info[ 6 ].source, RTEMS_FATAL_SOURCE_APPLICATION ); @@ -308,40 +360,46 @@ static void ScoreInterrValTerminate_Action_0( void ) * Check that the fatal extensions were invoked with the expected always set * to false argument. */ - T_step_false( 9, info[ 0 ].always_set_to_false ); - T_step_false( 10, info[ 1 ].always_set_to_false ); - T_step_false( 11, info[ 2 ].always_set_to_false ); - T_step_false( 12, info[ 3 ].always_set_to_false ); + T_step_false( 13, info[ 0 ].always_set_to_false ); + T_step_false( 14, info[ 1 ].always_set_to_false ); + T_step_false( 15, info[ 2 ].always_set_to_false ); + T_step_false( 16, info[ 4 ].always_set_to_false ); + T_step_false( 17, info[ 5 ].always_set_to_false ); + T_step_false( 18, info[ 6 ].always_set_to_false ); /* * Check that the fatal extensions were invoked with the expected code. */ - T_step_eq_ulong( 13, info[ 0 ].code, 123456 ); - T_step_eq_ulong( 14, info[ 1 ].code, 123456 ); - T_step_eq_ulong( 15, info[ 2 ].code, 123456 ); - T_step_eq_ulong( 16, info[ 3 ].code, 123456 ); + T_step_eq_ulong( 19, info[ 0 ].code, 123456 ); + T_step_eq_ulong( 20, info[ 1 ].code, 123456 ); + T_step_eq_ulong( 21, info[ 2 ].code, 123456 ); + T_step_eq_ulong( 22, info[ 4 ].code, 123456 ); + T_step_eq_ulong( 23, info[ 5 ].code, 123456 ); + T_step_eq_ulong( 24, info[ 6 ].code, 123456 ); /* * Check that the fatal extensions were invoked in forward order. */ - T_step_eq_uint( 17, info[ 0 ].counter, 1 ); - T_step_eq_uint( 18, info[ 1 ].counter, 2 ); - T_step_eq_uint( 19, info[ 2 ].counter, 3 ); - T_step_eq_uint( 20, info[ 3 ].counter, 4 ); + T_step_eq_uint( 25, info[ 0 ].counter, 1 ); + T_step_eq_uint( 26, info[ 1 ].counter, 2 ); + T_step_eq_uint( 27, info[ 2 ].counter, 3 ); + T_step_eq_uint( 28, info[ 4 ].counter, 4 ); + T_step_eq_uint( 29, info[ 5 ].counter, 5 ); + T_step_eq_uint( 30, info[ 6 ].counter, 6 ); /* * Check that the fatal extension in the deleted extension set was not * invoked. */ - T_step_eq_int( 21, info[ 4 ].source, 0 ); - T_step_false( 22, info[ 4 ].always_set_to_false ); - T_step_eq_ulong( 23, info[ 4 ].code, 0 ); - T_step_eq_uint( 24, info[ 4 ].counter, 0 ); + T_step_eq_int( 31, info[ 3 ].source, 0 ); + T_step_false( 32, info[ 3 ].always_set_to_false ); + T_step_eq_ulong( 33, info[ 3 ].code, 0 ); + T_step_eq_uint( 34, info[ 3 ].counter, 0 ); /* * Check that the system state is terminated. */ - T_step_eq_int( 25, _System_state_Get(), SYSTEM_STATE_TERMINATED ); + T_step_eq_int( 35, _System_state_Get(), SYSTEM_STATE_TERMINATED ); /* * Where the system was built with SMP support enabled, check that a shutdown @@ -352,22 +410,22 @@ static void ScoreInterrValTerminate_Action_0( void ) _Per_CPU_Get_state( _Per_CPU_Get() ) == PER_CPU_STATE_SHUTDOWN ); _ISR_Set_level( 0 ); #endif - T_step_true( 26, shutdown_ok ); + T_step_true( 36, shutdown_ok ); /* * Check that the system was halted with the expected fatal source. */ - T_step_eq_int( 27, halt_source, RTEMS_FATAL_SOURCE_APPLICATION ); + T_step_eq_int( 37, halt_source, RTEMS_FATAL_SOURCE_APPLICATION ); /* * Check that the system was halted with the expected fatal code. */ - T_step_eq_ulong( 28, halt_code, 123456 ); + T_step_eq_ulong( 38, halt_code, 123456 ); /* * Check that the system was finally halted. */ - T_step_eq_uint( 29, counter, 5 ); + T_step_eq_uint( 39, counter, 7 ); } /** @@ -375,7 +433,7 @@ static void ScoreInterrValTerminate_Action_0( void ) */ T_TEST_CASE( ScoreInterrValTerminate ) { - T_plan( 30 ); + T_plan( 40 ); ScoreInterrValTerminate_Action_0(); } diff --git a/testsuites/validation/tc-terminate.h b/testsuites/validation/tc-terminate.h deleted file mode 100644 index e46c8b0b16..0000000000 --- a/testsuites/validation/tc-terminate.h +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup RTEMSTestCaseScoreInterrValTerminate - * - * @brief This header file provides functions used by corresponding test suite. - */ - -/* - * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _TC_TERMINATE_H -#define _TC_TERMINATE_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void FatalExtension0( - rtems_fatal_source source, - bool always_set_to_false, - rtems_fatal_code code -); - -void FatalExtension1( - rtems_fatal_source source, - bool always_set_to_false, - rtems_fatal_code code -); - -#ifdef __cplusplus -} -#endif - -#endif /* _TC_TERMINATE_H */ diff --git a/testsuites/validation/tc-userext.c b/testsuites/validation/tc-userext.c new file mode 100644 index 0000000000..2d4420cab5 --- /dev/null +++ b/testsuites/validation/tc-userext.c @@ -0,0 +1,849 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseRtemsUserextValUserext + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "tc-userext.h" +#include "tx-support.h" + +#include + +/** + * @defgroup RTEMSTestCaseRtemsUserextValUserext \ + * spec:/rtems/userext/val/userext + * + * @ingroup RTEMSTestSuiteTestsuitesUserext + * + * @brief Tests the thread user extensions. + * + * This test case performs the following actions: + * + * - Create five dynamic extensions. Switch to a started thread. Delete three + * dynamic extension during the thread begin invocation. Clean up the used + * resources. + * + * - Check that the thread switch extensions were invoked in the right order + * before the thread begin extensions. + * + * - Check that the thread begin extensions were invoked in the right order. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread begin extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Create a thread. Delete three dynamic + * extension during the thread create invocation. Clean up the used + * resources. + * + * - Check that the thread create extensions were invoked in the right order. + * + * - Check that the thread create extensions were invoked under protection of + * the allocator mutex. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread create extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Delete a thread. Delete three dynamic + * extension during the thread delete invocation. Clean up the used + * resources. + * + * - Check that the thread delete extensions were invoked in the right order. + * + * - Check that the thread delete extensions were invoked under protection of + * the allocator mutex. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread delete extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Return from a thread entry. Delete three + * dynamic extension during the thread exitted invocation. Clean up the used + * resources. + * + * - Check that the thread exitted extensions were invoked in the right + * order. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread exitted extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Restart a thread. Delete three dynamic + * extension during the thread restart invocation. Clean up the used + * resources. + * + * - Check that the thread restart extensions were invoked in the right + * order. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread restart extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Start a thread. Delete three dynamic + * extension during the thread start invocation. Clean up the used + * resources. + * + * - Check that the thread start extensions were invoked in the right order. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread start extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * - Create five dynamic extensions. Terminate a thread. Delete three dynamic + * extension during the thread terminate invocation. Clean up the used + * resources. + * + * - Check that the thread terminate extensions were invoked in the right + * order. + * + * - Check that the other extensions were not invoked. + * + * - Check that the thread terminate extension of the extension set deleted + * before its turn in the invocation was not invoked. + * + * @{ + */ + +static void RtemsUserextValUserext_Setup( void *ctx ) +{ + SetSelfPriority( PRIO_NORMAL ); +} + +static void RtemsUserextValUserext_Teardown( void *ctx ) +{ + RestoreRunnerPriority(); +} + +static T_fixture RtemsUserextValUserext_Fixture = { + .setup = RtemsUserextValUserext_Setup, + .stop = NULL, + .teardown = RtemsUserextValUserext_Teardown, + .scope = NULL, + .initial_context = NULL +}; + +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(); +} + +/** + * @brief Create five dynamic extensions. Switch to a started thread. Delete + * three dynamic extension during the thread begin invocation. Clean up the + * used resources. + */ +static void RtemsUserextValUserext_Action_0( void ) +{ + 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(); + + /* + * Check that the thread switch extensions were invoked in the right order + * before the thread begin extensions. + */ + CheckForward( THREAD_SWITCH, 1, 1, executing, thread ); + + /* + * Check that the thread begin extensions were invoked in the right order. + */ + CheckForward( THREAD_BEGIN, 8, 1, thread, NULL ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread begin extension of the extension set deleted before + * its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_BEGIN ); +} + +/** + * @brief Create five dynamic extensions. Create a thread. Delete three + * dynamic extension during the thread create invocation. Clean up the used + * resources. + */ +static void RtemsUserextValUserext_Action_1( void ) +{ + 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(); + + /* + * Check that the thread create extensions were invoked in the right order. + */ + CheckForward( THREAD_CREATE, 1, 1, executing, thread ); + + /* + * Check that the thread create extensions were invoked under protection of + * the allocator mutex. + */ + T_eq_u32( thread_create_allocator_owner_count, 6 ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread create extension of the extension set deleted before + * its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_CREATE ); +} + +/** + * @brief Create five dynamic extensions. Delete a thread. Delete three + * dynamic extension during the thread delete invocation. Clean up the used + * resources. + */ +static void RtemsUserextValUserext_Action_2( void ) +{ + 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(); + + /* + * Check that the thread delete extensions were invoked in the right order. + */ + CheckReverse( THREAD_DELETE, 1, 1, executing, thread ); + + /* + * Check that the thread delete extensions were invoked under protection of + * the allocator mutex. + */ + T_eq_u32( thread_delete_allocator_owner_count, 6 ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread delete extension of the extension set deleted before + * its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_DELETE ); +} + +/** + * @brief Create five dynamic extensions. Return from a thread entry. Delete + * three dynamic extension during the thread exitted invocation. Clean up + * the used resources. + */ +static void RtemsUserextValUserext_Action_3( void ) +{ + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, ExittedWorker, NULL ); + KillZombies(); + + /* + * Check that the thread exitted extensions were invoked in the right order. + */ + CheckForward( THREAD_EXITTED, 1, 1, thread, NULL ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread exitted extension of the extension set deleted + * before its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_EXITTED ); +} + +/** + * @brief Create five dynamic extensions. Restart a thread. Delete three + * dynamic extension during the thread restart invocation. Clean up the used + * resources. + */ +static void RtemsUserextValUserext_Action_4( void ) +{ + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, RestartWorker, NULL ); + KillZombies(); + + /* + * Check that the thread restart extensions were invoked in the right order. + */ + CheckForward( THREAD_RESTART, 1, 1, thread, thread ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread restart extension of the extension set deleted + * before its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_RESTART ); +} + +/** + * @brief Create five dynamic extensions. Start a thread. Delete three + * dynamic extension during the thread start invocation. Clean up the used + * resources. + */ +static void RtemsUserextValUserext_Action_5( void ) +{ + 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(); + + /* + * Check that the thread start extensions were invoked in the right order. + */ + CheckForward( THREAD_START, 1, 1, executing, thread ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread start extension of the extension set deleted before + * its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_START ); +} + +/** + * @brief Create five dynamic extensions. Terminate a thread. Delete three + * dynamic extension during the thread terminate invocation. Clean up the + * used resources. + */ +static void RtemsUserextValUserext_Action_6( void ) +{ + rtems_tcb *thread; + rtems_id id; + + id = CreateTask( "WORK", PRIO_HIGH ); + thread = GetThread( id ); + StartTask( id, TerminateWorker, NULL ); + KillZombies(); + + /* + * Check that the thread terminate extensions were invoked in the right + * order. + */ + CheckReverse( THREAD_TERMINATE, 1, 1, thread, NULL ); + + /* + * Check that the other extensions were not invoked. + */ + 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 ); + + /* + * Check that the thread terminate extension of the extension set deleted + * before its turn in the invocation was not invoked. + */ + CheckDeletedNotInvoked( THREAD_TERMINATE ); +} + +/** + * @fn void T_case_body_RtemsUserextValUserext( void ) + */ +T_TEST_CASE_FIXTURE( RtemsUserextValUserext, &RtemsUserextValUserext_Fixture ) +{ + RtemsUserextValUserext_Action_0(); + RtemsUserextValUserext_Action_1(); + RtemsUserextValUserext_Action_2(); + RtemsUserextValUserext_Action_3(); + RtemsUserextValUserext_Action_4(); + RtemsUserextValUserext_Action_5(); + RtemsUserextValUserext_Action_6(); +} + +/** @} */ diff --git a/testsuites/validation/tc-userext.h b/testsuites/validation/tc-userext.h new file mode 100644 index 0000000000..dbe9e30b67 --- /dev/null +++ b/testsuites/validation/tc-userext.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestCaseScoreInterrValTerminate + * + * @brief This header file provides functions used by corresponding test suite. + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _TC_USEREXT_H +#define _TC_USEREXT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ThreadBeginExtension0( rtems_tcb *executing ); + +bool ThreadCreateExtension0( rtems_tcb *executing, rtems_tcb *created ); + +void ThreadDeleteExtension0( rtems_tcb *executing, rtems_tcb *deleted ); + +void ThreadExittedExtension0( rtems_tcb *executing ); + +void ThreadRestartExtension0( rtems_tcb *executing, rtems_tcb *restarted ); + +void ThreadStartExtension0( rtems_tcb *executing, rtems_tcb *started ); + +void ThreadSwitchExtension0( rtems_tcb *executing, rtems_tcb *heir ); + +void ThreadTerminateExtension0( rtems_tcb *executing ); + +void FatalExtension0( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +); + +void ThreadBeginExtension1( rtems_tcb *executing ); + +bool ThreadCreateExtension1( rtems_tcb *executing, rtems_tcb *created ); + +void ThreadDeleteExtension1( rtems_tcb *executing, rtems_tcb *deleted ); + +void ThreadExittedExtension1( rtems_tcb *executing ); + +void ThreadRestartExtension1( rtems_tcb *executing, rtems_tcb *restarted ); + +void ThreadStartExtension1( rtems_tcb *executing, rtems_tcb *started ); + +void ThreadSwitchExtension1( rtems_tcb *executing, rtems_tcb *heir ); + +void ThreadTerminateExtension1( rtems_tcb *executing ); + +void FatalExtension1( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code code +); + +#ifdef __cplusplus +} +#endif + +#endif /* _TC_USEREXT_H */ diff --git a/testsuites/validation/ts-default.h b/testsuites/validation/ts-default.h index bb0ce8dd91..216e8b1bfa 100644 --- a/testsuites/validation/ts-default.h +++ b/testsuites/validation/ts-default.h @@ -157,7 +157,7 @@ static void task_stack_deallocate( void *stack ) #define CONFIGURE_MAXIMUM_TIMERS 3 -#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 3 +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5 #define CONFIGURE_MICROSECONDS_PER_TICK TEST_MICROSECONDS_PER_TICK diff --git a/testsuites/validation/ts-terminate.c b/testsuites/validation/ts-terminate.c index 491444a029..52676db6d9 100644 --- a/testsuites/validation/ts-terminate.c +++ b/testsuites/validation/ts-terminate.c @@ -52,7 +52,7 @@ #include "config.h" #endif -#include "tc-terminate.h" +#include "tc-userext.h" #include @@ -67,7 +67,7 @@ * @{ */ -const char rtems_test_name[] = "Fatal"; +const char rtems_test_name[] = "Terminate"; #define CONFIGURE_MAXIMUM_PROCESSORS 2 diff --git a/testsuites/validation/ts-userext.c b/testsuites/validation/ts-userext.c new file mode 100644 index 0000000000..5d41f52093 --- /dev/null +++ b/testsuites/validation/ts-userext.c @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSTestSuiteTestsuitesUserext + */ + +/* + * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file is part of the RTEMS quality process and was automatically + * generated. If you find something that needs to be fixed or + * worded better please post a report or patch to an RTEMS mailing list + * or raise a bug report: + * + * https://www.rtems.org/bugs.html + * + * For information on updating and regenerating please refer to the How-To + * section in the Software Requirements Engineering chapter of the + * RTEMS Software Engineering manual. The manual is provided as a part of + * a release. For development sources please refer to the online + * documentation at: + * + * https://docs.rtems.org + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "tc-userext.h" + +#include + +/** + * @defgroup RTEMSTestSuiteTestsuitesUserext spec:/testsuites/userext + * + * @ingroup RTEMSTestSuites + * + * @brief This validation test suite contains a test cases related to the + * invocation of user extensions. + * + * @{ + */ + +const char rtems_test_name[] = "Userext"; + +#define CONFIGURE_MAXIMUM_PROCESSORS 2 + +#define CONFIGURE_INITIAL_EXTENSIONS \ + { \ + .thread_begin = ThreadBeginExtension0, \ + .thread_create = ThreadCreateExtension0, \ + .thread_delete = ThreadDeleteExtension0, \ + .thread_exitted = ThreadExittedExtension0, \ + .thread_restart = ThreadRestartExtension0, \ + .thread_start = ThreadStartExtension0, \ + .thread_switch = ThreadSwitchExtension0, \ + .thread_terminate = ThreadTerminateExtension0 \ + }, { \ + .thread_begin = ThreadBeginExtension1, \ + .thread_create = ThreadCreateExtension1, \ + .thread_delete = ThreadDeleteExtension1, \ + .thread_exitted = ThreadExittedExtension1, \ + .thread_restart = ThreadRestartExtension1, \ + .thread_start = ThreadStartExtension1, \ + .thread_switch = ThreadSwitchExtension1, \ + .thread_terminate = ThreadTerminateExtension1 \ + } + +#include "ts-default.h" + +/** @} */ -- cgit v1.2.3