From 11b05f11d4d6d61717e345d20f492977b95ab131 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 8 May 2014 10:11:13 +0200 Subject: score: Fix CPU context usage on SMP We must not alter the is executing indicator in _CPU_Context_Initialize() since this would cause an invalid state during a self restart. The is executing indicator must be valid at creation time since otherwise _Thread_Kill_zombies() uses an undefined value for not started threads. This could result in a system life lock. --- c/src/lib/libbsp/sparc/shared/irq_asm.S | 6 ++--- c/src/lib/libcpu/powerpc/new-exceptions/cpu.c | 6 ----- c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S | 14 +++++------- cpukit/score/cpu/arm/cpu.c | 4 ---- cpukit/score/cpu/arm/cpu_asm.S | 20 ++++++++--------- cpukit/score/cpu/arm/rtems/score/cpu.h | 16 ++++++++++++-- cpukit/score/cpu/i386/cpu_asm.S | 8 +++---- cpukit/score/cpu/i386/rtems/score/cpu.h | 23 +++++++++++-------- cpukit/score/cpu/no_cpu/rtems/score/cpu.h | 26 +++++++++++++++++++--- cpukit/score/cpu/powerpc/rtems/score/cpu.h | 16 ++++++++++++-- cpukit/score/cpu/sparc/cpu.c | 4 ---- cpukit/score/cpu/sparc/rtems/score/cpu.h | 16 ++++++++++++-- cpukit/score/src/threadinitialize.c | 1 + testsuites/sptests/spcontext01/init.c | 27 +++++++++++++++++++++++ 14 files changed, 129 insertions(+), 58 deletions(-) diff --git a/c/src/lib/libbsp/sparc/shared/irq_asm.S b/c/src/lib/libbsp/sparc/shared/irq_asm.S index 8b152840ed..bf2dca9787 100644 --- a/c/src/lib/libbsp/sparc/shared/irq_asm.S +++ b/c/src/lib/libbsp/sparc/shared/irq_asm.S @@ -164,17 +164,17 @@ done_flushing: nop #if defined(RTEMS_SMP) - ! Indicate that this context is no longer executing + ! The executing context no longer executes on this processor stb %g0, [%o0 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET] - ! Wait for context to stop execution if necessary + ! Wait for heir context to stop execution 1: ldub [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET], %g1 cmp %g1, 0 bne 1b mov 1, %g1 - ! Indicate that this context is executing + ! The heir context executes now on this processor stb %g1, [%o1 + SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET] #endif diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/cpu.c b/c/src/lib/libcpu/powerpc/new-exceptions/cpu.c index 32c0489308..c12a04e6d1 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/cpu.c +++ b/c/src/lib/libcpu/powerpc/new-exceptions/cpu.c @@ -123,17 +123,11 @@ void _CPU_Context_Initialize( else msr_value &= ~PPC_MSR_FP; - memset( the_context, 0, sizeof( *the_context ) ); - the_ppc_context = ppc_get_context( the_context ); the_ppc_context->gpr1 = sp; the_ppc_context->msr = msr_value; the_ppc_context->lr = (uint32_t) entry_point; -#ifdef RTEMS_SMP - the_ppc_context->is_executing = false; -#endif - #ifdef __ALTIVEC__ _CPU_Context_initialize_altivec( the_ppc_context ); #endif diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S b/c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S index 4e74996d4c..6bde8bd11e 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S +++ b/c/src/lib/libcpu/powerpc/new-exceptions/cpu_asm.S @@ -327,28 +327,26 @@ PROC (_CPU_Context_switch): stw r2, PPC_CONTEXT_OFFSET_GPR2(r3) #ifdef RTEMS_SMP - /* Indicate that this context is no longer executing */ + /* The executing context no longer executes on this processor */ msync li r5, 0 stb r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r3) -#endif - - /* Restore context from r4 */ -restore_context: -#ifdef RTEMS_SMP - /* Wait for context to stop execution if necessary */ + /* Wait for heir context to stop execution */ 1: lbz r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r4) cmpwi r5, 0 bne 1b - /* Indicate that this context is executing */ + /* The heir context executes now on this processor */ li r5, 1 stb r5, PPC_CONTEXT_OFFSET_IS_EXECUTING(r4) isync #endif + /* Restore context from r4 */ +restore_context: + #ifdef __ALTIVEC__ mr r14, r4 .extern _CPU_Context_switch_altivec diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index 91109e4e1d..089826ee17 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -101,10 +101,6 @@ void _CPU_Context_Initialize( the_context->thread_id = (uint32_t) tls_area; #endif -#ifdef RTEMS_SMP - the_context->is_executing = false; -#endif - if ( tls_area != NULL ) { _TLS_TCB_at_area_begin_initialize( tls_area ); } diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S index f2c4afe39e..0df5ebbb87 100644 --- a/cpukit/score/cpu/arm/cpu_asm.S +++ b/cpukit/score/cpu/arm/cpu_asm.S @@ -68,31 +68,29 @@ DEFINE_FUNCTION_ARM(_CPU_Context_switch) #endif #ifdef RTEMS_SMP - /* Indicate that this context is no longer executing */ + /* The executing context no longer executes on this processor */ dmb mov r3, #0 strb r3, [r0, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET] -#endif - -/* Start restoring context */ -_restore: -#ifdef ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE - clrex -#endif -#ifdef RTEMS_SMP - /* Wait for context to stop execution if necessary */ + /* Wait for heir context to stop execution */ 1: ldrb r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET] cmp r3, #0 bne 1b - /* Indicate that this context is executing */ + /* The heir context executes now on this processor */ dmb mov r3, #1 strb r3, [r1, #ARM_CONTEXT_CONTROL_IS_EXECUTING_OFFSET] #endif +/* Start restoring context */ +_restore: +#ifdef ARM_MULTILIB_HAS_LOAD_STORE_EXCLUSIVE + clrex +#endif + #ifdef ARM_MULTILIB_HAS_THREAD_ID_REGISTER ldr r3, [r1, #ARM_CONTEXT_CONTROL_THREAD_ID_OFFSET] mcr p15, 0, r3, c13, c0, 3 diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index dc57a78a67..d53be6043f 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h @@ -422,8 +422,20 @@ void _CPU_Context_Initialize( (_context)->register_sp #ifdef RTEMS_SMP - #define _CPU_Context_Get_is_executing( _context ) \ - (_context)->is_executing + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return context->is_executing; + } + + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + context->is_executing = is_executing; + } #endif #define _CPU_Context_Restart_self( _the_context ) \ diff --git a/cpukit/score/cpu/i386/cpu_asm.S b/cpukit/score/cpu/i386/cpu_asm.S index cc08312f33..9b395678b8 100644 --- a/cpukit/score/cpu/i386/cpu_asm.S +++ b/cpukit/score/cpu/i386/cpu_asm.S @@ -58,24 +58,24 @@ SYM (_CPU_Context_switch): movl edi,REG_EDI(eax) /* save destination register */ #ifdef RTEMS_SMP - /* Indicate that this context is no longer executing */ + /* The executing context no longer executes on this processor */ movb $0, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax) #endif movl HEIRCONTEXT_ARG(esp),eax /* eax = heir threads context */ -restore: #ifdef RTEMS_SMP - /* Wait for context to stop execution if necessary */ + /* Wait for heir context to stop execution */ 1: movb I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax), bl testb bl, bl jne 1b - /* Indicate that this context is executing */ + /* The heir context executes now on this processor */ movb $1, I386_CONTEXT_CONTROL_IS_EXECUTING_OFFSET(eax) #endif +restore: pushl REG_EFLAGS(eax) /* push eflags */ popf /* restore eflags */ movl REG_ESP(eax),esp /* restore stack pointer */ diff --git a/cpukit/score/cpu/i386/rtems/score/cpu.h b/cpukit/score/cpu/i386/rtems/score/cpu.h index ba731b0666..2d1472d4df 100644 --- a/cpukit/score/cpu/i386/rtems/score/cpu.h +++ b/cpukit/score/cpu/i386/rtems/score/cpu.h @@ -167,8 +167,20 @@ typedef struct { (_context)->esp #ifdef RTEMS_SMP - #define _CPU_Context_Get_is_executing( _context ) \ - (_context)->is_executing + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return context->is_executing; + } + + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + context->is_executing = is_executing; + } #endif /* @@ -454,12 +466,6 @@ uint32_t _CPU_ISR_Get_level( void ); */ -#ifdef RTEMS_SMP - #define _I386_Context_Initialize_is_executing( _the_context ) \ - (_the_context)->is_executing = false -#else - #define _I386_Context_Initialize_is_executing( _the_context ) -#endif #define _CPU_Context_Initialize( _the_context, _stack_base, _size, \ _isr, _entry_point, _is_fp, _tls_area ) \ @@ -475,7 +481,6 @@ uint32_t _CPU_ISR_Get_level( void ); *((proc_ptr *)(_stack)) = (_entry_point); \ (_the_context)->ebp = (void *) 0; \ (_the_context)->esp = (void *) _stack; \ - _I386_Context_Initialize_is_executing( _the_context ); \ } while (0) #define _CPU_Context_Restart_self( _the_context ) \ diff --git a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h index 739a6a8a42..9570fb6c8d 100644 --- a/cpukit/score/cpu/no_cpu/rtems/score/cpu.h +++ b/cpukit/score/cpu/no_cpu/rtems/score/cpu.h @@ -1596,10 +1596,30 @@ register struct Per_CPU_Control *_CPU_Per_CPU_current asm( "rX" ); } /** - * @brief Macro to return the is executing field of the thread context. + * @brief Gets the is executing indicator of the thread context. + * + * @param[in] context The context. */ - #define _CPU_Context_Get_is_executing( _context ) \ - ( ( _context )->is_executing ) + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return context->is_executing; + } + + /** + * @brief Sets the is executing indicator of the thread context. + * + * @param[in] context The context. + * @param[in] is_executing The new value for the is executing indicator. + */ + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + context->is_executing = is_executing; + } #endif #ifdef __cplusplus diff --git a/cpukit/score/cpu/powerpc/rtems/score/cpu.h b/cpukit/score/cpu/powerpc/rtems/score/cpu.h index 18a6770788..3cad329157 100644 --- a/cpukit/score/cpu/powerpc/rtems/score/cpu.h +++ b/cpukit/score/cpu/powerpc/rtems/score/cpu.h @@ -343,8 +343,20 @@ static inline ppc_context *ppc_get_context( const Context_Control *context ) ppc_get_context(_context)->gpr1 #ifdef RTEMS_SMP - #define _CPU_Context_Get_is_executing( _context ) \ - ppc_get_context(_context)->is_executing + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return ppc_get_context(context)->is_executing; + } + + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + ppc_get_context(context)->is_executing = is_executing; + } #endif #endif /* ASM */ diff --git a/cpukit/score/cpu/sparc/cpu.c b/cpukit/score/cpu/sparc/cpu.c index d05c511162..ee0d622067 100644 --- a/cpukit/score/cpu/sparc/cpu.c +++ b/cpukit/score/cpu/sparc/cpu.c @@ -330,10 +330,6 @@ void _CPU_Context_Initialize( */ the_context->isr_dispatch_disable = 0; -#if defined(RTEMS_SMP) - the_context->is_executing = false; -#endif - if ( tls_area != NULL ) { void *tcb = _TLS_TCB_after_TLS_block_initialize( tls_area ); diff --git a/cpukit/score/cpu/sparc/rtems/score/cpu.h b/cpukit/score/cpu/sparc/rtems/score/cpu.h index 7bcdbd9b37..b931d2f103 100644 --- a/cpukit/score/cpu/sparc/rtems/score/cpu.h +++ b/cpukit/score/cpu/sparc/rtems/score/cpu.h @@ -488,8 +488,20 @@ typedef struct { (_context)->o6_sp #ifdef RTEMS_SMP - #define _CPU_Context_Get_is_executing( _context ) \ - (_context)->is_executing + static inline bool _CPU_Context_Get_is_executing( + const Context_Control *context + ) + { + return context->is_executing; + } + + static inline void _CPU_Context_Set_is_executing( + Context_Control *context, + bool is_executing + ) + { + context->is_executing = is_executing; + } #endif #endif /* ASM */ diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index 1a03b0d320..2beaed4563 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -184,6 +184,7 @@ bool _Thread_Initialize( the_thread->is_scheduled = false; the_thread->is_in_the_air = false; the_thread->scheduler = scheduler; + _CPU_Context_Set_is_executing( &the_thread->Registers, false ); #endif _Thread_Debug_set_real_processor( the_thread, cpu ); diff --git a/testsuites/sptests/spcontext01/init.c b/testsuites/sptests/spcontext01/init.c index f26bc55168..e1af302c7a 100644 --- a/testsuites/sptests/spcontext01/init.c +++ b/testsuites/sptests/spcontext01/init.c @@ -160,12 +160,39 @@ static void test(test_context *self) wait_for_finish(); } +static void test_context_is_executing(void) +{ +#if defined(RTEMS_SMP) + Context_Control context; + bool is_executing; + + memset(&context, 0, sizeof(context)); + + is_executing = _CPU_Context_Get_is_executing(&context); + rtems_test_assert(!is_executing); + + _CPU_Context_Set_is_executing(&context, true); + is_executing = _CPU_Context_Get_is_executing(&context); + rtems_test_assert(is_executing); + + _CPU_Context_Set_is_executing(&context, false); + is_executing = _CPU_Context_Get_is_executing(&context); + rtems_test_assert(!is_executing); + + _CPU_Context_Set_is_executing(&context, true); + _CPU_Context_Initialize(&context, NULL, 0, 0, NULL, false, NULL); + is_executing = _CPU_Context_Get_is_executing(&context); + rtems_test_assert(is_executing); +#endif +} + static void Init(rtems_task_argument arg) { test_context *self = &test_instance; TEST_BEGIN(); + test_context_is_executing(); test(self); TEST_END(); -- cgit v1.2.3