summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2014-10-10 09:09:19 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2014-10-13 14:30:22 +0200
commita38ced268314dfe3f61cbba5b982eeb77c2b8de4 (patch)
tree2fa13257e71eb2d5e391d8bc2a95f74a2d6fce74 /cpukit
parentarm/nds: Warning clean up (diff)
downloadrtems-a38ced268314dfe3f61cbba5b982eeb77c2b8de4.tar.bz2
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.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/posix/src/pthreadinitthreads.c17
-rw-r--r--cpukit/rtems/src/taskinitusers.c13
-rw-r--r--cpukit/score/Makefile.am1
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h10
-rw-r--r--cpukit/score/src/threadglobalconstruction.c94
-rw-r--r--cpukit/score/src/threadhandler.c84
6 files changed, 134 insertions, 85 deletions
diff --git a/cpukit/posix/src/pthreadinitthreads.c b/cpukit/posix/src/pthreadinitthreads.c
index ad8906b39a..3738dc44e1 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 51fb474a3e..490ddc73eb 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 55e10e9c4c..3e646a1725 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 9321c017b8..61b498a9cf 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 0000000000..ff8af51242
--- /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 5f6623f11f..f8a9a62429 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