[rtems commit] score: Use thread action for thread restart
Sebastian Huber
sebh at rtems.org
Mon Mar 31 08:09:16 UTC 2014
Module: rtems
Branch: master
Commit: 5c731a83485ce3e7a6b6556e7a38b92d10a98cd6
Changeset: http://git.rtems.org/rtems/commit/?id=5c731a83485ce3e7a6b6556e7a38b92d10a98cd6
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Mon Mar 17 10:12:14 2014 +0100
score: Use thread action for thread restart
The thread restart is now supported on SMP. New test
smptests/smpthreadlife01.
---
cpukit/rtems/src/taskrestart.c | 10 +--
cpukit/score/include/rtems/score/objectimpl.h | 17 ---
cpukit/score/include/rtems/score/thread.h | 5 +
cpukit/score/include/rtems/score/threadimpl.h | 37 ++++++-
cpukit/score/src/threadinitialize.c | 5 +
cpukit/score/src/threadrestart.c | 50 ++++++---
testsuites/smptests/Makefile.am | 1 +
testsuites/smptests/configure.ac | 1 +
testsuites/smptests/smpthreadlife01/Makefile.am | 19 +++
testsuites/smptests/smpthreadlife01/init.c | 122 ++++++++++++++++++++
.../smptests/smpthreadlife01/smpthreadlife01.doc | 11 ++
.../smptests/smpthreadlife01/smpthreadlife01.scn | 2 +
testsuites/smptests/smpunsupported01/init.c | 25 +----
13 files changed, 236 insertions(+), 69 deletions(-)
diff --git a/cpukit/rtems/src/taskrestart.c b/cpukit/rtems/src/taskrestart.c
index daac0da..ad44642 100644
--- a/cpukit/rtems/src/taskrestart.c
+++ b/cpukit/rtems/src/taskrestart.c
@@ -34,15 +34,7 @@ rtems_status_code rtems_task_restart(
case OBJECTS_LOCAL:
if ( _Thread_Restart( the_thread, NULL, argument ) ) {
- if ( _Thread_Is_executing( the_thread ) ) {
- _Objects_Put_and_keep_thread_dispatch_disabled(
- &the_thread->Object
- );
- _Thread_Restart_self();
- } else {
- _Objects_Put( &the_thread->Object );
- }
-
+ _Objects_Put( &the_thread->Object );
return RTEMS_SUCCESSFUL;
}
_Objects_Put( &the_thread->Object );
diff --git a/cpukit/score/include/rtems/score/objectimpl.h b/cpukit/score/include/rtems/score/objectimpl.h
index 3764c66..119f11d 100644
--- a/cpukit/score/include/rtems/score/objectimpl.h
+++ b/cpukit/score/include/rtems/score/objectimpl.h
@@ -880,23 +880,6 @@ RTEMS_INLINE_ROUTINE void _Objects_Put_without_thread_dispatch(
}
/**
- * @brief Puts back an object obtained with _Objects_Get().
- *
- * The thread dispatch disable level will remain unchanged.
- *
- * On SMP configurations the Giant lock will be released.
- */
-RTEMS_INLINE_ROUTINE void _Objects_Put_and_keep_thread_dispatch_disabled(
- Objects_Control *the_object
-)
-{
- (void) the_object;
-#if defined(RTEMS_SMP)
- _Giant_Release();
-#endif
-}
-
-/**
* @brief Puts back an object obtained with _Objects_Get_isr_disable().
*/
RTEMS_INLINE_ROUTINE void _Objects_Put_for_get_isr_disable(
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index e5a1a55..d853aa0 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -396,6 +396,10 @@ typedef struct {
Chain_Control Chain;
} Thread_Action_control;
+typedef struct {
+ Thread_Action Action;
+} Thread_Life_control;
+
/**
* This structure defines the Thread Control Block (TCB).
*/
@@ -543,6 +547,7 @@ struct Thread_Control_struct {
*/
Chain_Control Key_Chain;
+ Thread_Life_control Life;
};
#if (CPU_PROVIDES_IDLE_THREAD_BODY == FALSE)
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index bbaa10a..b864727 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -219,6 +219,13 @@ void _Thread_Reset(
Thread_Entry_numeric_type numeric_argument
);
+void _Thread_Life_action_handler(
+ Thread_Control *executing,
+ Thread_Action *action,
+ Per_CPU_Control *cpu,
+ ISR_Level level
+);
+
/**
* @brief Frees all memory associated with the specified thread.
*
@@ -501,21 +508,23 @@ RTEMS_INLINE_ROUTINE void _Thread_Unblock (
* to that of its initial state.
*/
-RTEMS_INLINE_ROUTINE void _Thread_Restart_self( void )
+RTEMS_INLINE_ROUTINE void _Thread_Restart_self( Thread_Control *executing )
{
#if defined(RTEMS_SMP)
ISR_Level level;
+ _Giant_Release();
+
_Per_CPU_ISR_disable_and_acquire( _Per_CPU_Get(), level );
( void ) level;
#endif
#if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
- if ( _Thread_Executing->fp_context != NULL )
- _Context_Restore_fp( &_Thread_Executing->fp_context );
+ if ( executing->fp_context != NULL )
+ _Context_Restore_fp( &executing->fp_context );
#endif
- _CPU_Context_Restart_self( &_Thread_Executing->Registers );
+ _CPU_Context_Restart_self( &executing->Registers );
}
/**
@@ -603,6 +612,26 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Thread_Internal_allocate( void )
return (Thread_Control *) _Objects_Allocate( &_Thread_Internal_information );
}
+RTEMS_INLINE_ROUTINE void _Thread_Request_dispatch_if_executing(
+ Thread_Control *thread
+)
+{
+#if defined(RTEMS_SMP)
+ if ( thread->is_executing ) {
+ const Per_CPU_Control *cpu_of_executing = _Per_CPU_Get();
+ Per_CPU_Control *cpu_of_thread = _Thread_Get_CPU( thread );
+
+ cpu_of_thread->dispatch_necessary = true;
+
+ if ( cpu_of_executing != cpu_of_thread ) {
+ _Per_CPU_Send_interrupt( cpu_of_thread );
+ }
+ }
+#else
+ (void) thread;
+#endif
+}
+
RTEMS_INLINE_ROUTINE void _Thread_Signal_notification( Thread_Control *thread )
{
if ( _ISR_Is_in_progress() && _Thread_Is_executing( thread ) ) {
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index 315156e..c851320 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -240,6 +240,11 @@ bool _Thread_Initialize(
_Thread_Action_control_initialize( &the_thread->Post_switch_actions );
+ _Thread_Action_initialize(
+ &the_thread->Life.Action,
+ _Thread_Life_action_handler
+ );
+
/*
* Open the object
*/
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index b9a7dd5..d982f72 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -20,32 +20,52 @@
#include <rtems/score/threadimpl.h>
#include <rtems/score/userextimpl.h>
-#include <rtems/config.h>
-bool _Thread_Restart(
+void _Thread_Life_action_handler(
+ Thread_Control *executing,
+ Thread_Action *action,
+ Per_CPU_Control *cpu,
+ ISR_Level level
+)
+{
+ (void) action;
+ _Thread_Action_release_and_ISR_enable( cpu, level );
+
+ _Thread_Disable_dispatch();
+
+ _Thread_Load_environment( executing );
+ _Thread_Restart_self( executing );
+}
+
+static void _Thread_Request_life_change(
Thread_Control *the_thread,
void *pointer_argument,
Thread_Entry_numeric_type numeric_argument
)
{
-#if defined( RTEMS_SMP )
- if (
- rtems_configuration_is_smp_enabled()
- && !_Thread_Is_executing( the_thread )
- ) {
- return false;
- }
-#endif
+ _Thread_Set_transient( the_thread );
- if ( !_States_Is_dormant( the_thread->current_state ) ) {
+ _Thread_Reset( the_thread, pointer_argument, numeric_argument );
- _Thread_Set_transient( the_thread );
+ _Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action );
- _Thread_Reset( the_thread, pointer_argument, numeric_argument );
+ _Thread_Ready( the_thread );
- _Thread_Load_environment( the_thread );
+ _Thread_Request_dispatch_if_executing( the_thread );
+}
- _Thread_Ready( the_thread );
+bool _Thread_Restart(
+ Thread_Control *the_thread,
+ void *pointer_argument,
+ Thread_Entry_numeric_type numeric_argument
+)
+{
+ if ( !_States_Is_dormant( the_thread->current_state ) ) {
+ _Thread_Request_life_change(
+ the_thread,
+ pointer_argument,
+ numeric_argument
+ );
_User_extensions_Thread_restart( the_thread );
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index c7fa028..dddd7ab 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -21,6 +21,7 @@ SUBDIRS += smpmigration01
SUBDIRS += smpschedule01
SUBDIRS += smpsignal01
SUBDIRS += smpswitchextension01
+SUBDIRS += smpthreadlife01
SUBDIRS += smpunsupported01
if HAS_POSIX
SUBDIRS += smppsxaffinity01
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 0d08f0d..b7bd8d2 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -78,6 +78,7 @@ smppsxsignal01/Makefile
smpschedule01/Makefile
smpsignal01/Makefile
smpswitchextension01/Makefile
+smpthreadlife01/Makefile
smpunsupported01/Makefile
])
AC_OUTPUT
diff --git a/testsuites/smptests/smpthreadlife01/Makefile.am b/testsuites/smptests/smpthreadlife01/Makefile.am
new file mode 100644
index 0000000..02b5bd5
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = smpthreadlife01
+smpthreadlife01_SOURCES = init.c
+
+dist_rtems_tests_DATA = smpthreadlife01.scn smpthreadlife01.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 = $(smpthreadlife01_OBJECTS)
+LINK_LIBS = $(smpthreadlife01_LDLIBS)
+
+smpthreadlife01$(EXEEXT): $(smpthreadlife01_OBJECTS) $(smpthreadlife01_DEPENDENCIES)
+ @rm -f smpthreadlife01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpthreadlife01/init.c b/testsuites/smptests/smpthreadlife01/init.c
new file mode 100644
index 0000000..ee36068
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/init.c
@@ -0,0 +1,122 @@
+/*
+ * 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"
+
+#include <rtems.h>
+#include <rtems/score/smpbarrier.h>
+
+const char rtems_test_name[] = "SMPTHREADLIFE 1";
+
+#define CPU_COUNT 2
+
+typedef struct {
+ volatile rtems_task_argument main_arg;
+ volatile rtems_task_argument worker_arg;
+ SMP_barrier_Control barrier;
+ SMP_barrier_State worker_barrier_state;
+} test_context;
+
+static test_context test_instance = {
+ .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
+ .worker_barrier_state = SMP_BARRIER_STATE_INITIALIZER
+};
+
+static void worker_task(rtems_task_argument arg)
+{
+ test_context *ctx = &test_instance;
+
+ rtems_test_assert(arg == ctx->main_arg);
+
+ ctx->worker_arg = arg;
+
+ _SMP_barrier_Wait(&ctx->barrier, &ctx->worker_barrier_state, CPU_COUNT);
+
+ while (true) {
+ /* Do nothing */
+ }
+}
+
+static void test(void)
+{
+ test_context *ctx = &test_instance;
+ SMP_barrier_State barrier_state = SMP_BARRIER_STATE_INITIALIZER;
+ rtems_status_code sc;
+ rtems_id id;
+ rtems_task_argument arg;
+
+ sc = rtems_task_create(
+ rtems_build_name('W', 'O', 'R', 'K'),
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &id
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(id, worker_task, 0);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ _SMP_barrier_Wait(
+ &ctx->barrier,
+ &barrier_state,
+ CPU_COUNT
+ );
+
+ for (arg = 1; arg < 23; ++arg) {
+ ctx->main_arg = arg;
+ ctx->worker_arg = 0;
+
+ sc = rtems_task_restart(id, arg);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ _SMP_barrier_Wait(&ctx->barrier, &barrier_state, CPU_COUNT);
+
+ rtems_test_assert(ctx->worker_arg == arg);
+ }
+}
+
+static void Init(rtems_task_argument arg)
+{
+ TEST_BEGIN();
+
+ if (rtems_smp_get_processor_count() >= CPU_COUNT) {
+ test();
+ }
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
+
+#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc b/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc
new file mode 100644
index 0000000..f620567
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/smpthreadlife01.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smprestart01
+
+directives:
+
+ - rtems_task_restart()
+
+concepts:
+
+ - Ensure that a restart of a task executing on another processor works.
diff --git a/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn b/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn
new file mode 100644
index 0000000..7b4de1b
--- /dev/null
+++ b/testsuites/smptests/smpthreadlife01/smpthreadlife01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPTHREADLIFE 1 ***
+*** END OF TEST SMPTHREADLIFE 1 ***
diff --git a/testsuites/smptests/smpunsupported01/init.c b/testsuites/smptests/smpunsupported01/init.c
index a2ffbed..ffa4013 100644
--- a/testsuites/smptests/smpunsupported01/init.c
+++ b/testsuites/smptests/smpunsupported01/init.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -20,13 +20,6 @@
const char rtems_test_name[] = "SMPUNSUPPORTED 1";
-static void some_task(rtems_task_argument arg)
-{
- (void) arg;
-
- while (1);
-}
-
static void test(void)
{
rtems_status_code sc;
@@ -59,22 +52,6 @@ static void test(void)
&id
);
rtems_test_assert(sc == RTEMS_UNSATISFIED);
-
- sc = rtems_task_create(
- rtems_build_name('T', 'A', 'S', 'K'),
- RTEMS_MAXIMUM_PRIORITY,
- RTEMS_MINIMUM_STACK_SIZE,
- RTEMS_DEFAULT_MODES,
- RTEMS_DEFAULT_ATTRIBUTES,
- &id
- );
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- sc = rtems_task_start(id, some_task, 0);
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- sc = rtems_task_restart(id, 0);
- rtems_test_assert(sc == RTEMS_INCORRECT_STATE);
}
static void Init(rtems_task_argument arg)
More information about the vc
mailing list