mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-25 12:24:54 +08:00
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -69,6 +69,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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -64,6 +64,7 @@ _SUBDIRS += spfatal28
|
||||
_SUBDIRS += spthreadlife01
|
||||
_SUBDIRS += spcache01
|
||||
_SUBDIRS += sptls03
|
||||
_SUBDIRS += sptls04
|
||||
_SUBDIRS += spcpucounter01
|
||||
if HAS_CPLUSPLUS
|
||||
_SUBDIRS += spglobalcon01
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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@.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
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2017 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@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__ */
|
||||
@@ -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.
|
||||
@@ -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 ***
|
||||
Reference in New Issue
Block a user