From 709f38a97287ff1aa8e8c0668c2d066e711db87c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 13 Apr 2016 06:48:58 +0200 Subject: score: Use chain iterator for user extensions Add a lock and use a chain iterator for safe iteration during concurrent user extension addition and removal. Ensure that dynamically added thread delete and fatal extensions are called in reverse order. Update #2555. Update #2692. --- testsuites/sptests/Makefile.am | 1 + testsuites/sptests/configure.ac | 1 + testsuites/sptests/spextensions01/Makefile.am | 19 + testsuites/sptests/spextensions01/init.c | 447 +++++++++++++++++++++ .../sptests/spextensions01/spextensions01.doc | 12 + .../sptests/spextensions01/spextensions01.scn | 2 + 6 files changed, 482 insertions(+) create mode 100644 testsuites/sptests/spextensions01/Makefile.am create mode 100644 testsuites/sptests/spextensions01/init.c create mode 100644 testsuites/sptests/spextensions01/spextensions01.doc create mode 100644 testsuites/sptests/spextensions01/spextensions01.scn (limited to 'testsuites/sptests') diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am index f88e74af2d..ed8e759e87 100644 --- a/testsuites/sptests/Makefile.am +++ b/testsuites/sptests/Makefile.am @@ -33,6 +33,7 @@ _SUBDIRS = \ spsignal_err01 spport_err01 spmsgq_err01 spmsgq_err02 spsem_err01 \ spsem_err02 sptask_err01 spevent_err03 sptask_err03 sptask_err02 \ sptask_err04 spclock_err01 +_SUBDIRS += spextensions01 _SUBDIRS += spsysinit01 if HAS_SMP else diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac index 208940651c..f5481ae3bf 100644 --- a/testsuites/sptests/configure.ac +++ b/testsuites/sptests/configure.ac @@ -46,6 +46,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +spextensions01/Makefile sptimerserver01/Makefile spsysinit01/Makefile splinkersets01/Makefile diff --git a/testsuites/sptests/spextensions01/Makefile.am b/testsuites/sptests/spextensions01/Makefile.am new file mode 100644 index 0000000000..610c2b5deb --- /dev/null +++ b/testsuites/sptests/spextensions01/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = spextensions01 +spextensions01_SOURCES = init.c + +dist_rtems_tests_DATA = spextensions01.scn spextensions01.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(spextensions01_OBJECTS) +LINK_LIBS = $(spextensions01_LDLIBS) + +spextensions01$(EXEEXT): $(spextensions01_OBJECTS) $(spextensions01_DEPENDENCIES) + @rm -f spextensions01$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/sptests/spextensions01/init.c b/testsuites/sptests/spextensions01/init.c new file mode 100644 index 0000000000..d8593b9980 --- /dev/null +++ b/testsuites/sptests/spextensions01/init.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include +#include +#include + +#include + +#include + +const char rtems_test_name[] = "SPEXTENSIONS 1"; + +static int counter; + +static int active_extensions = 2; + +static rtems_id master_task; + +static void assert_static_order(int index) +{ + assert((counter % active_extensions) == index); + ++counter; +} + +static void assert_forward_order(int index) +{ + assert((counter % active_extensions) == index); + ++counter; +} + +static void assert_reverse_order(int index) +{ + assert((counter % active_extensions) == (5 - index)); + ++counter; +} + +static bool zero_thread_create(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(0); + return true; +} + +static void zero_thread_start(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(0); +} + +static void zero_thread_restart(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(0); +} + +static void zero_thread_delete(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(0); +} + +static void zero_thread_switch(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(0); +} + +static void zero_thread_begin(rtems_tcb *a) +{ + assert_static_order(0); +} + +static void zero_thread_exitted(rtems_tcb *a) +{ + assert_static_order(0); +} + +static void zero_fatal( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if (source == RTEMS_FATAL_SOURCE_EXIT) { + assert_static_order(0); + } +} + +static void zero_thread_terminate(rtems_tcb *a) +{ + assert_static_order(0); +} + +static bool one_thread_create(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(1); + return true; +} + +static void one_thread_start(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(1); +} + +static void one_thread_restart(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(1); +} + +static void one_thread_delete(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(1); +} + +static void one_thread_switch(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(1); +} + +static void one_thread_begin(rtems_tcb *a) +{ + assert_static_order(1); +} + +static void one_thread_exitted(rtems_tcb *a) +{ + assert_static_order(1); +} + +static void one_fatal( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if (source == RTEMS_FATAL_SOURCE_EXIT) { + assert_static_order(1); + } +} + +static void one_thread_terminate(rtems_tcb *a) +{ + assert_static_order(1); +} + +static bool two_thread_create(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(2); + return true; +} + +static void two_thread_start(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(2); +} + +static void two_thread_restart(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(2); +} + +static void two_thread_delete(rtems_tcb *a, rtems_tcb *b) +{ + assert_reverse_order(2); +} + +static void two_thread_switch(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(2); +} + +static void two_thread_begin(rtems_tcb *a) +{ + assert_forward_order(2); +} + +static void two_thread_exitted(rtems_tcb *a) +{ + assert_forward_order(2); +} + +static void two_fatal( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if (source == RTEMS_FATAL_SOURCE_EXIT) { + assert_reverse_order(2); + assert(counter == 72); + rtems_test_endk(); + } +} + +static void two_thread_terminate(rtems_tcb *a) +{ + assert_forward_order(2); +} + +static bool three_thread_create(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(3); + return true; +} + +static void three_thread_start(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(3); +} + +static void three_thread_restart(rtems_tcb *a, rtems_tcb *b) +{ + assert_static_order(3); +} + +static void three_thread_delete(rtems_tcb *a, rtems_tcb *b) +{ + assert_reverse_order(3); +} + +static void three_thread_switch(rtems_tcb *a, rtems_tcb *b) +{ + assert_forward_order(3); +} + +static void three_thread_begin(rtems_tcb *a) +{ + assert_forward_order(3); +} + +static void three_thread_exitted(rtems_tcb *a) +{ + assert_forward_order(3); +} + +static void three_fatal( + rtems_fatal_source source, + bool is_internal, + rtems_fatal_code code +) +{ + if (source == RTEMS_FATAL_SOURCE_EXIT) { + assert_reverse_order(3); + } +} + +static void three_thread_terminate(rtems_tcb *a) +{ + assert_forward_order(3); +} + +#define ZERO \ + { \ + .thread_create = zero_thread_create, \ + .thread_start = zero_thread_start, \ + .thread_restart = zero_thread_restart, \ + .thread_delete = zero_thread_delete, \ + .thread_switch = zero_thread_switch, \ + .thread_begin = zero_thread_begin, \ + .thread_exitted = zero_thread_exitted, \ + .fatal = zero_fatal, \ + .thread_terminate = zero_thread_terminate \ + } + +#define ONE \ + { \ + .thread_create = one_thread_create, \ + .thread_start = one_thread_start, \ + .thread_restart = one_thread_restart, \ + .thread_delete = one_thread_delete, \ + .thread_switch = one_thread_switch, \ + .thread_begin = one_thread_begin, \ + .thread_exitted = one_thread_exitted, \ + .fatal = one_fatal, \ + .thread_terminate = one_thread_terminate \ + } + +static const rtems_extensions_table two = { + .thread_create = two_thread_create, + .thread_start = two_thread_start, + .thread_restart = two_thread_restart, + .thread_delete = two_thread_delete, + .thread_switch = two_thread_switch, + .thread_begin = two_thread_begin, + .thread_exitted = two_thread_exitted, + .fatal = two_fatal, + .thread_terminate = two_thread_terminate +}; + +static const rtems_extensions_table three = { + .thread_create = three_thread_create, + .thread_start = three_thread_start, + .thread_restart = three_thread_restart, + .thread_delete = three_thread_delete, + .thread_switch = three_thread_switch, + .thread_begin = three_thread_begin, + .thread_exitted = three_thread_exitted, + .fatal = three_fatal, + .thread_terminate = three_thread_terminate +}; + +static const rtems_extensions_table initial_test = + RTEMS_TEST_INITIAL_EXTENSION; + +#ifdef BSP_INITIAL_EXTENSION +static const rtems_extensions_table initial_bsp = + BSP_INITIAL_EXTENSION; +#endif + +static void wake_up_master(void) +{ + rtems_status_code sc; + + sc = rtems_event_transient_send(master_task); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void wait_for_worker(void) +{ + rtems_status_code sc; + + sc = rtems_event_transient_receive( + RTEMS_WAIT, + RTEMS_NO_TIMEOUT + ); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void worker(rtems_task_argument arg) +{ + wake_up_master(); + + (void) rtems_task_suspend(RTEMS_SELF); + assert(false); +} + +static void test(void) +{ + rtems_status_code sc; + rtems_id id; + + master_task = rtems_task_self(); + +#ifdef BSP_INITIAL_EXTENSION + sc = rtems_extension_create( + rtems_build_name(' ', 'B', 'S', 'P'), + &initial_bsp, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); +#undef BSP_INITIAL_EXTENSION +#endif + + sc = rtems_extension_create( + rtems_build_name('T', 'E', 'S', 'T'), + &initial_test, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_extension_create( + rtems_build_name('2', ' ', ' ', ' '), + &two, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_extension_create( + rtems_build_name('3', ' ', ' ', ' '), + &three, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + active_extensions = 4; + assert(counter == 14); + counter = 16; + + sc = rtems_task_create( + rtems_build_name('W', 'O', 'R', 'K'), + 2, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, worker, 0); + assert(sc == RTEMS_SUCCESSFUL); + + wait_for_worker(); + + sc = rtems_task_restart(id, 0); + assert(sc == RTEMS_SUCCESSFUL); + + wait_for_worker(); + + sc = rtems_task_delete(id); + assert(sc == RTEMS_SUCCESSFUL); + + /* Process zombies to trigger delete extensions */ + sc = rtems_task_create( + rtems_build_name('N', 'U', 'L', 'L'), + 2, + SIZE_MAX, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + assert(sc == RTEMS_UNSATISFIED); +} + +static void Init(rtems_task_argument arg) +{ + rtems_test_begink(); + + test(); + + exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER + +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 4 + +#define CONFIGURE_MAXIMUM_TASKS 2 + +#define CONFIGURE_INITIAL_EXTENSIONS ZERO, ONE + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT + +#include diff --git a/testsuites/sptests/spextensions01/spextensions01.doc b/testsuites/sptests/spextensions01/spextensions01.doc new file mode 100644 index 0000000000..5e91e8400a --- /dev/null +++ b/testsuites/sptests/spextensions01/spextensions01.doc @@ -0,0 +1,12 @@ +This file describes the directives and concepts tested by this test set. + +test set name: spextensions01 + +directives: + + - rtems_extension_create() + - _User_extensions_Iterate() + +concepts: + + - Ensure that the user extensions are called in the right order. diff --git a/testsuites/sptests/spextensions01/spextensions01.scn b/testsuites/sptests/spextensions01/spextensions01.scn new file mode 100644 index 0000000000..7a51b9441c --- /dev/null +++ b/testsuites/sptests/spextensions01/spextensions01.scn @@ -0,0 +1,2 @@ +*** BEGIN OF TEST SPEXTENSIONS 1 *** +*** END OF TEST SPEXTENSIONS 1 *** -- cgit v1.2.3