diff options
-rw-r--r-- | cpukit/include/rtems/score/percpu.h | 7 | ||||
-rw-r--r-- | cpukit/include/rtems/score/userextimpl.h | 11 | ||||
-rw-r--r-- | cpukit/libmisc/stackchk/check.c | 26 | ||||
-rw-r--r-- | cpukit/score/src/threadcreateidle.c | 3 | ||||
-rw-r--r-- | cpukit/score/src/threaddispatch.c | 5 | ||||
-rw-r--r-- | cpukit/score/src/threadhandler.c | 4 | ||||
-rw-r--r-- | cpukit/score/src/userextaddset.c | 21 | ||||
-rw-r--r-- | testsuites/sptests/spextensions01/init.c | 4 |
8 files changed, 78 insertions, 3 deletions
diff --git a/cpukit/include/rtems/score/percpu.h b/cpukit/include/rtems/score/percpu.h index 7c95a9649a..31bc2b0bff 100644 --- a/cpukit/include/rtems/score/percpu.h +++ b/cpukit/include/rtems/score/percpu.h @@ -529,6 +529,13 @@ typedef struct Per_CPU_Control { } Scheduler; /** + * @brief The ancestor of the executing thread. + * + * This member is used by _User_extensions_Thread_switch(). + */ + struct _Thread_Control *ancestor; + + /** * @brief Begin of the per-CPU data area. * * Contains items defined via PER_CPU_DATA_ITEM(). diff --git a/cpukit/include/rtems/score/userextimpl.h b/cpukit/include/rtems/score/userextimpl.h index 8b456c072d..23ee957724 100644 --- a/cpukit/include/rtems/score/userextimpl.h +++ b/cpukit/include/rtems/score/userextimpl.h @@ -386,7 +386,16 @@ static inline void _User_extensions_Thread_switch( _ISR_lock_ISR_disable( &lock_context ); _Per_CPU_Acquire( cpu_self, &lock_context ); + executing = cpu_self->ancestor; + cpu_self->ancestor = heir; node = _Chain_Immutable_first( chain ); + + /* + * An executing thread equal to the heir thread may happen in two + * situations. Firstly, in case context switch extensions are created after + * system initialization. Secondly, during a thread self restart. + */ + if ( executing != heir ) { #endif while ( node != tail ) { @@ -398,6 +407,8 @@ static inline void _User_extensions_Thread_switch( } #if defined(RTEMS_SMP) + } + _Per_CPU_Release( cpu_self, &lock_context ); _ISR_lock_ISR_enable( &lock_context ); #endif diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c index eec3a911aa..0c859f6375 100644 --- a/cpukit/libmisc/stackchk/check.c +++ b/cpukit/libmisc/stackchk/check.c @@ -295,8 +295,8 @@ static void Stack_check_report_blown_task( * rtems_stack_checker_switch_extension */ void rtems_stack_checker_switch_extension( - Thread_Control *running RTEMS_UNUSED, - Thread_Control *heir RTEMS_UNUSED + Thread_Control *running, + Thread_Control *heir ) { bool sp_ok; @@ -306,6 +306,22 @@ void rtems_stack_checker_switch_extension( /* * Check for an out of bounds stack pointer or an overwrite */ +#if defined(RTEMS_SMP) + sp_ok = Stack_check_Frame_pointer_in_range( heir ); + + if ( !sp_ok ) { + pattern_ok = Stack_check_Is_sanity_pattern_valid( + &heir->Start.Initial_stack + ); + Stack_check_report_blown_task( heir, pattern_ok ); + } + + pattern_ok = Stack_check_Is_sanity_pattern_valid( &running->Start.Initial_stack ); + + if ( !pattern_ok ) { + Stack_check_report_blown_task( running, pattern_ok ); + } +#else sp_ok = Stack_check_Frame_pointer_in_range( running ); pattern_ok = Stack_check_Is_sanity_pattern_valid( &running->Start.Initial_stack ); @@ -313,6 +329,7 @@ void rtems_stack_checker_switch_extension( if ( !sp_ok || !pattern_ok ) { Stack_check_report_blown_task( running, pattern_ok ); } +#endif stack = &Stack_check_Interrupt_stack[ _SMP_Get_current_processor() ]; @@ -329,7 +346,10 @@ void rtems_stack_checker_switch_extension( */ bool rtems_stack_checker_is_blown( void ) { - rtems_stack_checker_switch_extension( _Thread_Get_executing(), NULL ); + Thread_Control *executing; + + executing = _Thread_Get_executing(); + rtems_stack_checker_switch_extension( executing, executing ); /* * The Stack Pointer and the Pattern Area are OK so return false. diff --git a/cpukit/score/src/threadcreateidle.c b/cpukit/score/src/threadcreateidle.c index 52c3ad4534..d71315005b 100644 --- a/cpukit/score/src/threadcreateidle.c +++ b/cpukit/score/src/threadcreateidle.c @@ -75,6 +75,9 @@ static void _Thread_Create_idle_for_CPU( Per_CPU_Control *cpu ) */ cpu->heir = cpu->executing = idle; +#if defined(RTEMS_SMP) + cpu->ancestor = idle; +#endif idle->is_idle = true; idle->Start.Entry.adaptor = _Thread_Entry_adaptor_idle; diff --git a/cpukit/score/src/threaddispatch.c b/cpukit/score/src/threaddispatch.c index cd32f5a1d2..3b611f7a7a 100644 --- a/cpukit/score/src/threaddispatch.c +++ b/cpukit/score/src/threaddispatch.c @@ -297,10 +297,15 @@ void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level ) _ISR_Local_enable( level ); +#if !defined(RTEMS_SMP) _User_extensions_Thread_switch( executing, heir ); +#endif _Thread_Save_fp( executing ); _Context_Switch( &executing->Registers, &heir->Registers ); _Thread_Restore_fp( executing ); +#if defined(RTEMS_SMP) + _User_extensions_Thread_switch( NULL, executing ); +#endif /* * We have to obtain this value again after the context switch since the diff --git a/cpukit/score/src/threadhandler.c b/cpukit/score/src/threadhandler.c index 6ddb303299..4b8e386a67 100644 --- a/cpukit/score/src/threadhandler.c +++ b/cpukit/score/src/threadhandler.c @@ -97,6 +97,10 @@ void _Thread_Handler( void ) */ _Thread_Restore_fp( executing ); +#if defined(RTEMS_SMP) + _User_extensions_Thread_switch( NULL, executing ); +#endif + /* * Do not use the level of the thread control block, since it has a * different format. diff --git a/cpukit/score/src/userextaddset.c b/cpukit/score/src/userextaddset.c index 2b13dfad62..70e9fb008f 100644 --- a/cpukit/score/src/userextaddset.c +++ b/cpukit/score/src/userextaddset.c @@ -20,8 +20,28 @@ #endif #include <rtems/score/userextimpl.h> +#include <rtems/score/smp.h> #include <rtems/score/percpu.h> +static void _User_extensions_Set_ancestors( void ) +{ +#if defined(RTEMS_SMP) + if ( _Chain_Is_empty( &_User_extensions_Switches_list ) ) { + uint32_t cpu_max; + uint32_t cpu_index; + + cpu_max = _SMP_Get_processor_maximum(); + + for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) { + Per_CPU_Control *cpu; + + cpu = _Per_CPU_Get_by_index( cpu_index ); + cpu->ancestor = cpu->executing; + } + } +#endif +} + void _User_extensions_Add_set( User_extensions_Control *the_extension ) @@ -45,6 +65,7 @@ void _User_extensions_Add_set( the_extension->Callouts.thread_switch; _Per_CPU_Acquire_all( &lock_context ); + _User_extensions_Set_ancestors(); _Chain_Initialize_node( &the_extension->Switch.Node ); _Chain_Append_unprotected( &_User_extensions_Switches_list, diff --git a/testsuites/sptests/spextensions01/init.c b/testsuites/sptests/spextensions01/init.c index f9e3c11140..7ce1da5320 100644 --- a/testsuites/sptests/spextensions01/init.c +++ b/testsuites/sptests/spextensions01/init.c @@ -453,8 +453,12 @@ static void test(void) #endif active_extensions = 4; +#ifdef RTEMS_SMP + assert(counter == 12); +#else assert(counter == 10); counter = 12; +#endif sc = rtems_task_create( rtems_build_name('W', 'O', 'R', 'K'), |