[rtems commit] score: Fix CPU context usage on SMP

Sebastian Huber sebh at rtems.org
Thu May 8 10:56:21 UTC 2014


Module:    rtems
Branch:    master
Commit:    11b05f11d4d6d61717e345d20f492977b95ab131
Changeset: http://git.rtems.org/rtems/commit/?id=11b05f11d4d6d61717e345d20f492977b95ab131

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu May  8 10:11:13 2014 +0200

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 8b15284..bf2dca9 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 32c0489..c12a04e 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 4e74996..6bde8bd 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 91109e4..089826e 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 f2c4afe..0df5ebb 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 dc57a78..d53be60 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 cc08312..9b39567 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 ba731b0..2d1472d 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 739a6a8..9570fb6 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 18a6770..3cad329 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 d05c511..ee0d622 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 7bcdbd9..b931d2f 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 1a03b0d..2beaed4 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 f26bc55..e1af302 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();




More information about the vc mailing list