[rtems commit] score: Simplify global construction

Sebastian Huber sebh at rtems.org
Wed Nov 22 12:01:49 UTC 2017


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

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Nov 17 06:36:54 2017 +0100

score: Simplify global construction

Update #3243.

---

 cpukit/posix/src/pthreadinitthreads.c         | 26 ++------
 cpukit/rtems/src/taskinitusers.c              | 24 ++------
 cpukit/score/Makefile.am                      |  1 -
 cpukit/score/include/rtems/score/threadimpl.h | 23 ++++----
 cpukit/score/src/threadglobalconstruction.c   | 63 --------------------
 cpukit/score/src/threadhandler.c              | 46 +++++++++++++++
 testsuites/sptests/Makefile.am                |  1 +
 testsuites/sptests/configure.ac               |  1 +
 testsuites/sptests/spextensions01/init.c      |  6 +-
 testsuites/sptests/sptls04/Makefile.am        | 19 ++++++
 testsuites/sptests/sptls04/init.c             | 85 +++++++++++++++++++++++++++
 testsuites/sptests/sptls04/sptls04.doc        | 12 ++++
 testsuites/sptests/sptls04/sptls04.scn        |  7 +++
 13 files changed, 192 insertions(+), 122 deletions(-)

diff --git a/cpukit/posix/src/pthreadinitthreads.c b/cpukit/posix/src/pthreadinitthreads.c
index 7695879..1777ec9 100644
--- a/cpukit/posix/src/pthreadinitthreads.c
+++ b/cpukit/posix/src/pthreadinitthreads.c
@@ -31,19 +31,6 @@
 #include <rtems/posix/pthreadimpl.h>
 #include <rtems/posix/priorityimpl.h>
 #include <rtems/posix/config.h>
-#include <rtems/rtems/config.h>
-
-static void *_POSIX_Global_construction( void *arg )
-{
-  Thread_Control           *executing = _Thread_Get_executing();
-  Thread_Entry_information  entry = executing->Start.Entry;
-
-  entry.Kinds.Pointer.entry = Configuration_POSIX_API
-    .User_initialization_threads_table[ 0 ].thread_entry;
-
-  (void) arg;
-  _Thread_Global_construction( executing, &entry );
-}
 
 void _POSIX_Threads_Initialize_user_threads_body(void)
 {
@@ -53,7 +40,6 @@ 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;
@@ -62,9 +48,6 @@ void _POSIX_Threads_Initialize_user_threads_body(void)
   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.
    *
@@ -88,11 +71,6 @@ void _POSIX_Threads_Initialize_user_threads_body(void)
       _Internal_error( INTERNAL_ERROR_POSIX_INIT_THREAD_ENTRY_IS_NULL );
     }
 
-    if ( register_global_construction ) {
-      register_global_construction = false;
-      thread_entry = _POSIX_Global_construction;
-    }
-
     eno = pthread_create(
       &thread_id,
       &attr,
@@ -102,5 +80,9 @@ void _POSIX_Threads_Initialize_user_threads_body(void)
     if ( eno != 0 ) {
       _Internal_error( INTERNAL_ERROR_POSIX_INIT_THREAD_CREATE_FAILED );
     }
+
+    if ( _Thread_Global_constructor == 0 ) {
+      _Thread_Global_constructor = thread_id;
+    }
   }
 }
diff --git a/cpukit/rtems/src/taskinitusers.c b/cpukit/rtems/src/taskinitusers.c
index 41b7edc..c14d95d 100644
--- a/cpukit/rtems/src/taskinitusers.c
+++ b/cpukit/rtems/src/taskinitusers.c
@@ -29,18 +29,6 @@
 #include <rtems/score/thread.h>
 #include <rtems/score/wkspace.h>
 
-static void _RTEMS_Global_construction( rtems_task_argument arg )
-{
-  Thread_Control           *executing = _Thread_Get_executing();
-  Thread_Entry_information  entry = executing->Start.Entry;
-
-  entry.Kinds.Numeric.entry =
-    Configuration_RTEMS_API.User_initialization_tasks_table[ 0 ].entry_point;
-
-  (void) arg;
-  _Thread_Global_construction( executing, &entry );
-}
-
 /*
  *  _RTEMS_tasks_Initialize_user_tasks_body
  *
@@ -59,7 +47,6 @@ 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;
 
   /*
@@ -74,8 +61,6 @@ 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.
    */
@@ -97,11 +82,6 @@ void _RTEMS_tasks_Initialize_user_tasks_body( void )
       _Internal_error( INTERNAL_ERROR_RTEMS_INIT_TASK_ENTRY_IS_NULL );
     }
 
-    if ( register_global_construction ) {
-      register_global_construction = false;
-      entry_point = _RTEMS_Global_construction;
-    }
-
     return_value = rtems_task_start(
       id,
       entry_point,
@@ -109,5 +89,9 @@ void _RTEMS_tasks_Initialize_user_tasks_body( void )
     );
     _Assert( rtems_is_status_successful( return_value ) );
     (void) return_value;
+
+    if ( _Thread_Global_constructor == 0 ) {
+      _Thread_Global_constructor = id;
+    }
   }
 }
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 11bf59c..1c815b1 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -292,7 +292,6 @@ libscore_a_SOURCES += src/threadentryadaptoridle.c
 libscore_a_SOURCES += src/threadentryadaptornumeric.c
 libscore_a_SOURCES += src/threadentryadaptorpointer.c
 libscore_a_SOURCES += src/threadgetcputimeused.c
-libscore_a_SOURCES += src/threadglobalconstruction.c
 libscore_a_SOURCES += src/threaditerate.c
 libscore_a_SOURCES += src/threadname.c
 libscore_a_SOURCES += src/threadscheduler.c
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 5f6a5eb..b6722fa 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -70,6 +70,16 @@ typedef struct {
 extern Thread_Information _Thread_Internal_information;
 
 /**
+ * @brief Object identifier of the global constructor thread.
+ *
+ * This variable is set by _RTEMS_tasks_Initialize_user_tasks_body() or
+ * _POSIX_Threads_Initialize_user_threads_body().
+ *
+ * It is consumed by _Thread_Handler().
+ */
+extern Objects_Id _Thread_Global_constructor;
+
+/**
  *  The following points to the thread whose floating point
  *  context is currently loaded.
  */
@@ -345,19 +355,6 @@ void _Thread_Entry_adaptor_pointer( Thread_Control *executing );
  */
 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(
-  Thread_Control                 *executing,
-  const Thread_Entry_information *entry
-) RTEMS_NO_RETURN;
-
 RTEMS_INLINE_ROUTINE void _Thread_State_acquire_critical(
   Thread_Control   *the_thread,
   ISR_lock_Context *lock_context
diff --git a/cpukit/score/src/threadglobalconstruction.c b/cpukit/score/src/threadglobalconstruction.c
deleted file mode 100644
index 7ce1862..0000000
--- a/cpukit/score/src/threadglobalconstruction.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * @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>
-
-/*
- *  Conditional magic to determine what style of C++ constructor
- *  initialization this target and compiler version uses.
- */
-#if defined(__USE_INIT_FINI__)
-  #if 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(
-  Thread_Control                 *executing,
-  const Thread_Entry_information *entry
-)
-{
-  ISR_lock_Context lock_context;
-
-#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
-
-  _ISR_lock_ISR_disable( &lock_context );
-  _Thread_Restart_self( _Thread_Executing, entry, &lock_context );
-}
diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c
index 7267577..9201c55 100644
--- a/cpukit/score/src/threadhandler.c
+++ b/cpukit/score/src/threadhandler.c
@@ -24,6 +24,50 @@
 #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(__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
+
+Objects_Id _Thread_Global_constructor;
+
+static void _Thread_Global_construction( Thread_Control *executing )
+{
+#if defined(EXECUTE_GLOBAL_CONSTRUCTORS)
+  if ( executing->Object.id == _Thread_Global_constructor ) {
+    /*
+     * Prevent double construction in case the initialization thread is deleted
+     * and then recycled.  There is not need for extra synchronization since
+     * this variable is set during the sequential system boot procedure.
+     */
+    _Thread_Global_constructor = 0;
+
+    /*
+     *  _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
+}
+
 void _Thread_Handler( void )
 {
   Thread_Control  *executing;
@@ -80,6 +124,8 @@ void _Thread_Handler( void )
    */
   _User_extensions_Thread_begin( executing );
 
+  _Thread_Global_construction( executing );
+
   /*
    *  RTEMS supports multiple APIs and each API can define a different
    *  thread/task prototype. The following code supports invoking the
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index e52316a..00f7571 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -64,6 +64,7 @@ _SUBDIRS += spfatal28
 _SUBDIRS += spthreadlife01
 _SUBDIRS += spcache01
 _SUBDIRS += sptls03
+_SUBDIRS += sptls04
 _SUBDIRS += spcpucounter01
 if HAS_CPLUSPLUS
 _SUBDIRS += spglobalcon01
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index 0872f67..6a303b2 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -36,6 +36,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
 
 # Explicitly list all Makefiles here
 AC_CONFIG_FILES([Makefile
+sptls04/Makefile
 spconsole01/Makefile
 spintrcritical24/Makefile
 spfatal31/Makefile
diff --git a/testsuites/sptests/spextensions01/init.c b/testsuites/sptests/spextensions01/init.c
index 35fce48..f9e3c11 100644
--- a/testsuites/sptests/spextensions01/init.c
+++ b/testsuites/sptests/spextensions01/init.c
@@ -318,7 +318,7 @@ static void three_fatal(
 {
   if (source == RTEMS_FATAL_SOURCE_EXIT) {
     assert_forward_order(3);
-    assert(counter == 72);
+    assert(counter == 68);
     TEST_END();
   }
 }
@@ -453,8 +453,8 @@ static void test(void)
 #endif
 
   active_extensions = 4;
-  assert(counter == 14);
-  counter = 16;
+  assert(counter == 10);
+  counter = 12;
 
   sc = rtems_task_create(
     rtems_build_name('W', 'O', 'R', 'K'),
diff --git a/testsuites/sptests/sptls04/Makefile.am b/testsuites/sptests/sptls04/Makefile.am
new file mode 100644
index 0000000..9d4afd2
--- /dev/null
+++ b/testsuites/sptests/sptls04/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = sptls04
+sptls04_SOURCES = init.c
+
+dist_rtems_tests_DATA = sptls04.scn sptls04.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 = $(sptls04_OBJECTS)
+LINK_LIBS = $(sptls04_LDLIBS)
+
+sptls04$(EXEEXT): $(sptls04_OBJECTS) $(sptls04_DEPENDENCIES)
+	@rm -f sptls04$(EXEEXT)
+	$(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/sptls04/init.c b/testsuites/sptests/sptls04/init.c
new file mode 100644
index 0000000..d73b0f4
--- /dev/null
+++ b/testsuites/sptests/sptls04/init.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017 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.com/license/LICENSE.
+ */
+
+/*
+ * This test program runs also on GNU/Linux and FreeBSD.  Use
+ *
+ * cc init.c && ./a.out
+ *
+ * to run it.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef __rtems__
+
+#include <tmacros.h>
+
+#else /* __rtems__ */
+
+#include <assert.h>
+
+#define rtems_test_assert(x) assert(x)
+
+#endif /* __rtems__ */
+
+static __thread int i;
+
+static __thread int j;
+
+static __attribute__((__constructor__)) void con(void)
+{
+  i = 1;
+}
+
+static void test(void)
+{
+  rtems_test_assert(i == 1);
+  rtems_test_assert(j == 0);
+}
+
+#ifdef __rtems__
+
+const char rtems_test_name[] = "SPTLS 4";
+
+static void Init(rtems_task_argument arg)
+{
+  TEST_BEGIN();
+  test();
+  TEST_END();
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+
+#else /* __rtems__ */
+
+int main(void)
+{
+  test();
+  return 0;
+}
+
+#endif /* __rtems__ */
diff --git a/testsuites/sptests/sptls04/sptls04.doc b/testsuites/sptests/sptls04/sptls04.doc
new file mode 100644
index 0000000..4c77dac
--- /dev/null
+++ b/testsuites/sptests/sptls04/sptls04.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: sptls04
+
+directives:
+
+  - None
+
+concepts:
+
+  - Ensure that global construction affects the thread-local variables of the
+    first initialization thread to be in line with GNU/Linux and FreeBSD.
diff --git a/testsuites/sptests/sptls04/sptls04.scn b/testsuites/sptests/sptls04/sptls04.scn
new file mode 100644
index 0000000..f07cef1
--- /dev/null
+++ b/testsuites/sptests/sptls04/sptls04.scn
@@ -0,0 +1,7 @@
+*** BEGIN OF TEST SPTLS 4 ***
+*** TEST VERSION: 5.0.0.b926da560283088c42555a3f2e03a0ae9508087a
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: default
+*** TEST TOOLS: 7.2.0 20170814 (RTEMS 5, RSB d1e6dfcb1e14d2f9d42c79e1137ddca6d8fc67d5, Newlib 2.5.0.20170922)
+
+*** END OF TEST SPTLS 4 ***



More information about the vc mailing list