[rtems commit] score: Rework global construction

Sebastian Huber sebh at rtems.org
Mon Oct 13 13:09:20 UTC 2014


Module:    rtems
Branch:    master
Commit:    a38ced268314dfe3f61cbba5b982eeb77c2b8de4
Changeset: http://git.rtems.org/rtems/commit/?id=a38ced268314dfe3f61cbba5b982eeb77c2b8de4

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Oct 10 09:09:19 2014 +0200

score: Rework global construction

Ensure that the global construction is performed in the context of the
first initialization thread.  On SMP this was not guaranteed in the
previous implementation.

---

 cpukit/posix/src/pthreadinitthreads.c              |   17 +++-
 cpukit/rtems/src/taskinitusers.c                   |   13 +++-
 cpukit/score/Makefile.am                           |    1 +
 cpukit/score/include/rtems/score/threadimpl.h      |   10 ++
 cpukit/score/src/threadglobalconstruction.c        |   94 ++++++++++++++++++++
 cpukit/score/src/threadhandler.c                   |   84 +-----------------
 testsuites/psxtests/Makefile.am                    |    4 +
 testsuites/psxtests/configure.ac                   |    9 ++-
 testsuites/psxtests/psxglobalcon01/Makefile.am     |   19 ++++
 testsuites/psxtests/psxglobalcon01/init.cc         |   58 ++++++++++++
 .../psxtests/psxglobalcon01/psxglobalcon01.doc     |   12 +++
 .../psxtests/psxglobalcon01/psxglobalcon01.scn     |    2 +
 testsuites/psxtests/psxglobalcon02/Makefile.am     |   19 ++++
 testsuites/psxtests/psxglobalcon02/init.cc         |   73 +++++++++++++++
 .../psxtests/psxglobalcon02/psxglobalcon02.doc     |   12 +++
 .../psxtests/psxglobalcon02/psxglobalcon02.scn     |    2 +
 testsuites/sptests/Makefile.am                     |    1 +
 testsuites/sptests/configure.ac                    |    1 +
 testsuites/sptests/spglobalcon01/Makefile.am       |   19 ++++
 testsuites/sptests/spglobalcon01/init.cc           |   61 +++++++++++++
 testsuites/sptests/spglobalcon01/spglobalcon01.doc |   12 +++
 testsuites/sptests/spglobalcon01/spglobalcon01.scn |    2 +
 testsuites/sptests/spthreadlife01/init.c           |    6 +-
 23 files changed, 444 insertions(+), 87 deletions(-)

diff --git a/cpukit/posix/src/pthreadinitthreads.c b/cpukit/posix/src/pthreadinitthreads.c
index ad8906b..3738dc4 100644
--- a/cpukit/posix/src/pthreadinitthreads.c
+++ b/cpukit/posix/src/pthreadinitthreads.c
@@ -34,6 +34,7 @@
 #include <rtems/posix/priorityimpl.h>
 #include <rtems/posix/config.h>
 #include <rtems/posix/time.h>
+#include <rtems/rtems/config.h>
 
 void _POSIX_Threads_Initialize_user_threads_body(void)
 {
@@ -43,13 +44,18 @@ void _POSIX_Threads_Initialize_user_threads_body(void)
   posix_initialization_threads_table *user_threads;
   pthread_t                           thread_id;
   pthread_attr_t                      attr;
+  bool                                register_global_construction;
+  void                             *(*thread_entry)(void *);
 
   user_threads = Configuration_POSIX_API.User_initialization_threads_table;
   maximum      = Configuration_POSIX_API.number_of_initialization_threads;
 
-  if ( !user_threads || maximum == 0 )
+  if ( !user_threads )
     return;
 
+  register_global_construction =
+    Configuration_RTEMS_API.number_of_initialization_tasks == 0;
+
   /*
    *  Be careful .. if the default attribute set changes, this may need to.
    *
@@ -68,10 +74,17 @@ void _POSIX_Threads_Initialize_user_threads_body(void)
     eno = pthread_attr_setstacksize(&attr, user_threads[ index ].stack_size);
     _Assert( eno == 0 );
 
+    thread_entry = user_threads[ index ].thread_entry;
+
+    if ( register_global_construction && thread_entry != NULL ) {
+      register_global_construction = false;
+      thread_entry = (void *(*)(void *)) _Thread_Global_construction;
+    }
+
     eno = pthread_create(
       &thread_id,
       &attr,
-      user_threads[ index ].thread_entry,
+      thread_entry,
       NULL
     );
     if ( eno )
diff --git a/cpukit/rtems/src/taskinitusers.c b/cpukit/rtems/src/taskinitusers.c
index 51fb474..490ddc7 100644
--- a/cpukit/rtems/src/taskinitusers.c
+++ b/cpukit/rtems/src/taskinitusers.c
@@ -48,6 +48,8 @@ void _RTEMS_tasks_Initialize_user_tasks_body( void )
   rtems_id                          id;
   rtems_status_code                 return_value;
   rtems_initialization_tasks_table *user_tasks;
+  bool                              register_global_construction;
+  rtems_task_entry                  entry_point;
 
   /*
    *  Move information into local variables
@@ -61,6 +63,8 @@ void _RTEMS_tasks_Initialize_user_tasks_body( void )
   if ( !user_tasks )
     return;
 
+  register_global_construction = true;
+
   /*
    *  Now iterate over the initialization tasks and create/start them.
    */
@@ -76,9 +80,16 @@ void _RTEMS_tasks_Initialize_user_tasks_body( void )
     if ( !rtems_is_status_successful( return_value ) )
       _Terminate( INTERNAL_ERROR_RTEMS_API, true, return_value );
 
+    entry_point = user_tasks[ index ].entry_point;
+
+    if ( register_global_construction && entry_point != NULL ) {
+      register_global_construction = false;
+      entry_point = (rtems_task_entry) _Thread_Global_construction;
+    }
+
     return_value = rtems_task_start(
       id,
-      user_tasks[ index ].entry_point,
+      entry_point,
       user_tasks[ index ].argument
     );
     if ( !rtems_is_status_successful( return_value ) )
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 55e10e9..3e646a1 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -289,6 +289,7 @@ libscore_a_SOURCES += src/thread.c src/threadchangepriority.c \
     src/threadstackallocate.c src/threadstackfree.c src/threadstart.c \
     src/threadstartmultitasking.c src/iterateoverthreads.c \
     src/threadblockingoperationcancel.c
+libscore_a_SOURCES += src/threadglobalconstruction.c
 libscore_a_SOURCES += src/threadyield.c
 
 if HAS_SMP
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 9321c01..61b498a 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -305,6 +305,16 @@ void _Thread_Load_environment(
 void _Thread_Handler( void );
 
 /**
+ * @brief Executes the global constructors and then restarts itself as the
+ * first initialization thread.
+ *
+ * The first initialization thread is the first RTEMS initialization task or
+ * the first POSIX initialization thread in case no RTEMS initialization tasks
+ * are present.
+ */
+void *_Thread_Global_construction( void );
+
+/**
  *  @brief Ended the delay of a thread.
  *
  *  This routine is invoked when a thread must be unblocked at the
diff --git a/cpukit/score/src/threadglobalconstruction.c b/cpukit/score/src/threadglobalconstruction.c
new file mode 100644
index 0000000..ff8af51
--- /dev/null
+++ b/cpukit/score/src/threadglobalconstruction.c
@@ -0,0 +1,94 @@
+/**
+ * @file
+ *
+ * @brief Thread Global Construction
+ *
+ * @ingroup ScoreThread
+ */
+
+/*
+ *  COPYRIGHT (c) 1989-2012.
+ *  On-Line Applications Research Corporation (OAR).
+ *
+ *  The license and distribution terms for this file may be
+ *  found in the file LICENSE in this distribution or at
+ *  http://www.rtems.org/license/LICENSE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/threadimpl.h>
+#include <rtems/score/assert.h>
+#include <rtems/rtems/config.h>
+#include <rtems/posix/config.h>
+
+/*
+ *  Conditional magic to determine what style of C++ constructor
+ *  initialization this target and compiler version uses.
+ */
+#if defined(__USE_INIT_FINI__)
+  #if defined(__M32R__)
+    #define INIT_NAME __init
+  #elif defined(__ARM_EABI__)
+    #define INIT_NAME __libc_init_array
+  #else
+    #define INIT_NAME _init
+  #endif
+
+  extern void INIT_NAME(void);
+  #define EXECUTE_GLOBAL_CONSTRUCTORS
+#endif
+
+#if defined(__USE__MAIN__)
+  extern void __main(void);
+  #define INIT_NAME __main
+  #define EXECUTE_GLOBAL_CONSTRUCTORS
+#endif
+
+void *_Thread_Global_construction( void )
+{
+  Thread_Control *executing;
+  Thread_Entry    entry_point;
+
+#if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
+  /*
+   *  _init could be a weak symbol and we SHOULD test it but it isn't
+   *  in any configuration I know of and it generates a warning on every
+   *  RTEMS target configuration.  --joel (12 May 2007)
+   */
+  INIT_NAME();
+#endif
+
+#if defined(RTEMS_POSIX_API)
+  if ( Configuration_RTEMS_API.number_of_initialization_tasks > 0 ) {
+#endif
+    entry_point = (Thread_Entry)
+      Configuration_RTEMS_API.User_initialization_tasks_table[ 0 ].entry_point;
+#if defined(RTEMS_POSIX_API)
+  } else {
+    entry_point = (Thread_Entry)
+      Configuration_POSIX_API
+        .User_initialization_threads_table[ 0 ].thread_entry;
+  }
+#endif
+
+  _Thread_Disable_dispatch();
+
+  executing = _Thread_Executing;
+  executing->Start.entry_point = entry_point;
+
+  _Thread_Restart(
+    executing,
+    executing,
+    executing->Start.pointer_argument,
+    executing->Start.numeric_argument
+  );
+
+  _Thread_Enable_dispatch();
+
+  _Assert_Not_reached();
+
+  return NULL;
+}
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
index 5f6623f..f8a9a62 100644
--- a/cpukit/score/src/threadhandler.c
+++ b/cpukit/score/src/threadhandler.c
@@ -24,76 +24,11 @@
 #include <rtems/score/isrlevel.h>
 #include <rtems/score/userextimpl.h>
 
-/*
- *  Conditional magic to determine what style of C++ constructor
- *  initialization this target and compiler version uses.
- */
-#if defined(__USE_INIT_FINI__)
-  #if defined(__M32R__)
-    #define INIT_NAME __init
-  #elif defined(__ARM_EABI__)
-    #define INIT_NAME __libc_init_array
-  #else
-    #define INIT_NAME _init
-  #endif
-
-  extern void INIT_NAME(void);
-  #define EXECUTE_GLOBAL_CONSTRUCTORS
-#endif
-
-#if defined(__USE__MAIN__)
-  extern void __main(void);
-  #define INIT_NAME __main
-  #define EXECUTE_GLOBAL_CONSTRUCTORS
-#endif
-
-#if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
-  static bool _Thread_Handler_is_constructor_execution_required(
-    Thread_Control *executing
-  )
-  {
-    static bool doneConstructors;
-    bool doCons = false;
-
-    #if defined(RTEMS_SMP)
-      static SMP_lock_Control constructor_lock =
-        SMP_LOCK_INITIALIZER("constructor");
-
-      SMP_lock_Context lock_context;
-
-      if ( !doneConstructors ) {
-        _SMP_lock_Acquire( &constructor_lock, &lock_context );
-    #endif
-
-    #if defined(RTEMS_MULTIPROCESSING)
-      doCons = !doneConstructors
-        && _Objects_Get_API( executing->Object.id ) != OBJECTS_INTERNAL_API;
-      if (doCons)
-        doneConstructors = true;
-    #else
-      (void) executing;
-      doCons = !doneConstructors;
-      doneConstructors = true;
-    #endif
-
-    #if defined(RTEMS_SMP)
-        _SMP_lock_Release( &constructor_lock, &lock_context );
-      }
-    #endif
-
-    return doCons;
-  }
-#endif
-
 void _Thread_Handler( void )
 {
-  ISR_Level  level;
-  Thread_Control *executing;
-  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
-    bool doCons;
-  #endif
+  Thread_Control *executing = _Thread_Executing;
+  ISR_Level       level;
 
-  executing = _Thread_Executing;
 
   /*
    * Some CPUs need to tinker with the call frame or registers when the
@@ -111,10 +46,6 @@ void _Thread_Handler( void )
     _ISR_Set_level( level );
   #endif
 
-  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
-    doCons = _Thread_Handler_is_constructor_execution_required( executing );
-  #endif
-
   /*
    * Initialize the floating point context because we do not come
    * through _Thread_Dispatch on our first invocation. So the normal
@@ -171,17 +102,6 @@ void _Thread_Handler( void )
     _Thread_Enable_dispatch();
   #endif
 
-  #if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
-    /*
-     *  _init could be a weak symbol and we SHOULD test it but it isn't
-     *  in any configuration I know of and it generates a warning on every
-     *  RTEMS target configuration.  --joel (12 May 2007)
-     */
-    if (doCons) /* && (volatile void *)_init) */ {
-      INIT_NAME ();
-    }
- #endif
-
   /*
    *  RTEMS supports multiple APIs and each API can define a different
    *  thread/task prototype. The following code supports invoking the
diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am
index d8eee14..e15d72f 100644
--- a/testsuites/psxtests/Makefile.am
+++ b/testsuites/psxtests/Makefile.am
@@ -15,6 +15,10 @@ _SUBDIRS += psxhdrs psx01 psx02 psx03 psx04 psx05 psx06 psx07 psx08 psx09 \
     psxtime psxtimer01 psxtimer02 psxualarm psxusleep psxfatal01 psxfatal02 \
     psxintrcritical01 psxstack01 psxstack02 \
     psxeintr_join psxgetattrnp01
+if HAS_CPLUSPLUS
+_SUBDIRS += psxglobalcon01
+_SUBDIRS += psxglobalcon02
+endif
 endif
 
 ## File IO tests
diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac
index 26e4b60..23c7211 100644
--- a/testsuites/psxtests/configure.ac
+++ b/testsuites/psxtests/configure.ac
@@ -11,17 +11,22 @@ RTEMS_CANONICAL_TARGET_CPU
 AM_INIT_AUTOMAKE([no-define foreign 1.12.2])
 AM_MAINTAINER_MODE
 
+RTEMS_ENABLE_CXX
+
 RTEMS_ENV_RTEMSBSP
 
 RTEMS_PROJECT_ROOT
 
 RTEMS_PROG_CC_FOR_TARGET
+RTEMS_PROG_CXX_FOR_TARGET
 
 RTEMS_CANONICALIZE_TOOLS
 
 RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
+RTEMS_CHECK_CXX(RTEMS_BSP)
 
-AM_CONDITIONAL([HAS_NETWORKING],[test "$HAS_NETWORKING" = "yes"])
+AM_CONDITIONAL([HAS_NETWORKING],[test x"$HAS_NETWORKING" = x"yes"])
+AM_CONDITIONAL([HAS_CPLUSPLUS],[test x"$HAS_CPLUSPLUS" = x"yes"])
 
 RTEMS_CHECK_CPUOPTS([RTEMS_POSIX_API])
 AM_CONDITIONAL(HAS_POSIX,test x"${rtems_cv_RTEMS_POSIX_API}" = x"yes")
@@ -145,6 +150,8 @@ psxfile02/Makefile
 psxfilelock01/Makefile
 psxgetattrnp01/Makefile
 psxgetrusage01/Makefile
+psxglobalcon01/Makefile
+psxglobalcon02/Makefile
 psxhdrs/Makefile
 psxid01/Makefile
 psximfs01/Makefile
diff --git a/testsuites/psxtests/psxglobalcon01/Makefile.am b/testsuites/psxtests/psxglobalcon01/Makefile.am
new file mode 100644
index 0000000..3b87ebe
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = psxglobalcon01
+psxglobalcon01_SOURCES = init.cc
+
+dist_rtems_tests_DATA = psxglobalcon01.scn psxglobalcon01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxglobalcon01_OBJECTS)
+LINK_LIBS = $(psxglobalcon01_LDLIBS)
+
+psxglobalcon01$(EXEEXT): $(psxglobalcon01_OBJECTS) $(psxglobalcon01_DEPENDENCIES)
+	@rm -f psxglobalcon01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxglobalcon01/init.cc b/testsuites/psxtests/psxglobalcon01/init.cc
new file mode 100644
index 0000000..f33efc3
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon01/init.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "PSXGLOBALCON 1";
+
+class A {
+  public:
+    A()
+    {
+      ++i;
+    }
+
+    static int i;
+};
+
+int A::i;
+
+static A a;
+
+static void *POSIX_Init(void *argument)
+{
+  TEST_BEGIN();
+
+  rtems_test_assert(a.i == 1);
+
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/psxtests/psxglobalcon01/psxglobalcon01.doc b/testsuites/psxtests/psxglobalcon01/psxglobalcon01.doc
new file mode 100644
index 0000000..7ed81da
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon01/psxglobalcon01.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxglobalcon01
+
+directives:
+
+  - _Thread_Global_construction()
+
+concepts:
+
+  - Ensure that the global construction is performed exactly once in case only
+    a POSIX initialization thread is present.
diff --git a/testsuites/psxtests/psxglobalcon01/psxglobalcon01.scn b/testsuites/psxtests/psxglobalcon01/psxglobalcon01.scn
new file mode 100644
index 0000000..13d7b65
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon01/psxglobalcon01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST PSXGLOBALCON 1 ***
+*** END OF TEST PSXGLOBALCON 1 ***
diff --git a/testsuites/psxtests/psxglobalcon02/Makefile.am b/testsuites/psxtests/psxglobalcon02/Makefile.am
new file mode 100644
index 0000000..0d29894
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon02/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = psxglobalcon02
+psxglobalcon02_SOURCES = init.cc
+
+dist_rtems_tests_DATA = psxglobalcon02.scn psxglobalcon02.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(psxglobalcon02_OBJECTS)
+LINK_LIBS = $(psxglobalcon02_LDLIBS)
+
+psxglobalcon02$(EXEEXT): $(psxglobalcon02_OBJECTS) $(psxglobalcon02_DEPENDENCIES)
+	@rm -f psxglobalcon02$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/psxtests/psxglobalcon02/init.cc b/testsuites/psxtests/psxglobalcon02/init.cc
new file mode 100644
index 0000000..6de4fbd
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon02/init.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "PSXGLOBALCON 2";
+
+class A {
+  public:
+    A()
+    {
+      ++i;
+    }
+
+    static int i;
+};
+
+int A::i;
+
+static A a;
+
+static bool rtems_init_done;
+
+extern "C" void Init(rtems_task_argument argument)
+{
+  TEST_BEGIN();
+
+  rtems_test_assert(a.i == 1);
+
+  rtems_init_done = true;
+
+  rtems_task_delete(RTEMS_SELF);
+  rtems_test_assert(0);
+}
+
+static void *POSIX_Init(void *argument)
+{
+  rtems_test_assert(rtems_init_done);
+  rtems_test_assert(a.i == 1);
+
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/psxtests/psxglobalcon02/psxglobalcon02.doc b/testsuites/psxtests/psxglobalcon02/psxglobalcon02.doc
new file mode 100644
index 0000000..4dc5bde
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon02/psxglobalcon02.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: psxglobalcon02
+
+directives:
+
+  - _Thread_Global_construction()
+
+concepts:
+
+  - Ensure that the global construction is performed exactly once in case a
+    RTEMS initialization task and a POSIX initialization thread are present.
diff --git a/testsuites/psxtests/psxglobalcon02/psxglobalcon02.scn b/testsuites/psxtests/psxglobalcon02/psxglobalcon02.scn
new file mode 100644
index 0000000..54ae33b
--- /dev/null
+++ b/testsuites/psxtests/psxglobalcon02/psxglobalcon02.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST PSXGLOBALCON 2 ***
+*** END OF TEST PSXGLOBALCON 2 ***
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index 7764a3e..a71c024 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -50,6 +50,7 @@ _SUBDIRS += spcache01
 _SUBDIRS += sptls03
 _SUBDIRS += spcpucounter01
 if HAS_CPLUSPLUS
+_SUBDIRS += spglobalcon01
 _SUBDIRS += sptls02
 endif
 _SUBDIRS += sptls01
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 282cbcf..5acf7c0 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -40,6 +40,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
+spglobalcon01/Makefile
 spintrcritical22/Makefile
 spsem03/Makefile
 spresource01/Makefile
diff --git a/testsuites/sptests/spglobalcon01/Makefile.am b/testsuites/sptests/spglobalcon01/Makefile.am
new file mode 100644
index 0000000..a7d94af
--- /dev/null
+++ b/testsuites/sptests/spglobalcon01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = spglobalcon01
+spglobalcon01_SOURCES = init.cc
+
+dist_rtems_tests_DATA = spglobalcon01.scn spglobalcon01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP at .cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(spglobalcon01_OBJECTS)
+LINK_LIBS = $(spglobalcon01_LDLIBS)
+
+spglobalcon01$(EXEEXT): $(spglobalcon01_OBJECTS) $(spglobalcon01_DEPENDENCIES)
+	@rm -f spglobalcon01$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spglobalcon01/init.cc b/testsuites/sptests/spglobalcon01/init.cc
new file mode 100644
index 0000000..92a8a2c
--- /dev/null
+++ b/testsuites/sptests/spglobalcon01/init.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Dornierstr. 4
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems at embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#define TESTS_USE_PRINTK
+#include "tmacros.h"
+
+const char rtems_test_name[] = "SPGLOBALCON 1";
+
+class A {
+  public:
+    A()
+    {
+      ++i;
+    }
+
+    static int i;
+};
+
+int A::i;
+
+static A a;
+
+static void *idle_body(uintptr_t ignored)
+{
+  TEST_BEGIN();
+
+  rtems_test_assert(a.i == 0);
+
+  TEST_END();
+  rtems_test_exit(0);
+
+  return NULL;
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_IDLE_TASK_INITIALIZES_APPLICATION
+
+#define CONFIGURE_IDLE_TASK_BODY idle_body
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spglobalcon01/spglobalcon01.doc b/testsuites/sptests/spglobalcon01/spglobalcon01.doc
new file mode 100644
index 0000000..48c64c6
--- /dev/null
+++ b/testsuites/sptests/spglobalcon01/spglobalcon01.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: spglobalcon01
+
+directives:
+
+  - _Thread_Global_construction()
+
+concepts:
+
+  - Ensure that the global construction is not performed in case the idle
+    thread initializes the application.
diff --git a/testsuites/sptests/spglobalcon01/spglobalcon01.scn b/testsuites/sptests/spglobalcon01/spglobalcon01.scn
new file mode 100644
index 0000000..b15a431
--- /dev/null
+++ b/testsuites/sptests/spglobalcon01/spglobalcon01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPGLOBALCON 1 ***
+*** END OF TEST SPGLOBALCON 1 ***
diff --git a/testsuites/sptests/spthreadlife01/init.c b/testsuites/sptests/spthreadlife01/init.c
index 4e6c984..f400516 100644
--- a/testsuites/sptests/spthreadlife01/init.c
+++ b/testsuites/sptests/spthreadlife01/init.c
@@ -136,17 +136,21 @@ static void restart_extension(
   rtems_status_code sc;
 
   rtems_test_assert(executing == restarted);
-  rtems_test_assert(ctx->worker_task_id == rtems_task_self());
 
   switch (ctx->current) {
     case RESTART_0:
+      rtems_test_assert(ctx->worker_task_id == rtems_task_self());
       ctx->current = RESTART_1;
       sc = rtems_task_restart(RTEMS_SELF, 0);
       rtems_test_assert(sc == RTEMS_SUCCESSFUL);
       break;
     case RESTART_1:
+      rtems_test_assert(ctx->worker_task_id == rtems_task_self());
       ctx->current = RESTART_2;
       break;
+    case INIT:
+      /* Restart via _Thread_Global_construction() */
+      break;
     default:
       rtems_test_assert(0);
       break;



More information about the vc mailing list