mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-22 23:41:54 +08:00
score: Use thread action for thread restart
The thread restart is now supported on SMP. New test smptests/smpthreadlife01.
This commit is contained in:
@@ -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 );
|
||||
|
||||
@@ -879,23 +879,6 @@ RTEMS_INLINE_ROUTINE void _Objects_Put_without_thread_dispatch(
|
||||
_Thread_Unnest_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().
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ) ) {
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -20,7 +20,39 @@
|
||||
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/userextimpl.h>
|
||||
#include <rtems/config.h>
|
||||
|
||||
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
|
||||
)
|
||||
{
|
||||
_Thread_Set_transient( the_thread );
|
||||
|
||||
_Thread_Reset( the_thread, pointer_argument, numeric_argument );
|
||||
|
||||
_Thread_Add_post_switch_action( the_thread, &the_thread->Life.Action );
|
||||
|
||||
_Thread_Ready( the_thread );
|
||||
|
||||
_Thread_Request_dispatch_if_executing( the_thread );
|
||||
}
|
||||
|
||||
bool _Thread_Restart(
|
||||
Thread_Control *the_thread,
|
||||
@@ -28,24 +60,12 @@ bool _Thread_Restart(
|
||||
Thread_Entry_numeric_type numeric_argument
|
||||
)
|
||||
{
|
||||
#if defined( RTEMS_SMP )
|
||||
if (
|
||||
rtems_configuration_is_smp_enabled()
|
||||
&& !_Thread_Is_executing( the_thread )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !_States_Is_dormant( the_thread->current_state ) ) {
|
||||
|
||||
_Thread_Set_transient( the_thread );
|
||||
|
||||
_Thread_Reset( the_thread, pointer_argument, numeric_argument );
|
||||
|
||||
_Thread_Load_environment( the_thread );
|
||||
|
||||
_Thread_Ready( the_thread );
|
||||
_Thread_Request_life_change(
|
||||
the_thread,
|
||||
pointer_argument,
|
||||
numeric_argument
|
||||
);
|
||||
|
||||
_User_extensions_Thread_restart( the_thread );
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ SUBDIRS += smpmigration01
|
||||
SUBDIRS += smpschedule01
|
||||
SUBDIRS += smpsignal01
|
||||
SUBDIRS += smpswitchextension01
|
||||
SUBDIRS += smpthreadlife01
|
||||
SUBDIRS += smpunsupported01
|
||||
if HAS_POSIX
|
||||
SUBDIRS += smppsxaffinity01
|
||||
|
||||
@@ -78,6 +78,7 @@ smppsxsignal01/Makefile
|
||||
smpschedule01/Makefile
|
||||
smpsignal01/Makefile
|
||||
smpswitchextension01/Makefile
|
||||
smpthreadlife01/Makefile
|
||||
smpunsupported01/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -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@.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
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2014 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.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>
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
*** BEGIN OF TEST SMPTHREADLIFE 1 ***
|
||||
*** END OF TEST SMPTHREADLIFE 1 ***
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user