[PATCH 2/2] stackchk: Add SMP support

Sebastian Huber sebastian.huber at embedded-brains.de
Wed Jun 20 10:06:41 UTC 2018


Check the interrupt stacks of all processors.  Set up the interrupt
stack of the current processor for high water testing in the thread
begin extension.  This must be done after multi-threading started, since
the initialization stacks may reuse the interrupt stacks.  Disable
thread dispatching in SMP configurations to prevent thread migration.
Writing to the interrupt stack is only safe if done from the
corresponding processor in thread context.

Update #3459.
---
 cpukit/include/rtems/stackchk.h |   4 +-
 cpukit/libmisc/stackchk/check.c | 101 +++++++++++++++++++++++++---------------
 2 files changed, 67 insertions(+), 38 deletions(-)

diff --git a/cpukit/include/rtems/stackchk.h b/cpukit/include/rtems/stackchk.h
index eb81bb827e..b7d906ec22 100644
--- a/cpukit/include/rtems/stackchk.h
+++ b/cpukit/include/rtems/stackchk.h
@@ -96,6 +96,8 @@ bool rtems_stack_checker_create_extension(
   Thread_Control *the_thread
 );
 
+void rtems_stack_checker_begin_extension( Thread_Control *executing );
+
 /**
  * @brief Stack Checker Task Context Switch Extension
  *
@@ -125,7 +127,7 @@ void rtems_stack_checker_switch_extension(
   0,                                           /* rtems_task_restart */ \
   0,                                           /* rtems_task_delete  */ \
   rtems_stack_checker_switch_extension,        /* task_switch  */ \
-  0,                                           /* task_begin   */ \
+  rtems_stack_checker_begin_extension,         /* task_begin   */ \
   0,                                           /* task_exitted */ \
   0,                                           /* fatal        */ \
   0                                            /* terminate    */ \
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c
index 974d0eb5e5..abbd0e0845 100644
--- a/cpukit/libmisc/stackchk/check.c
+++ b/cpukit/libmisc/stackchk/check.c
@@ -60,7 +60,7 @@
 /*
  *  Variable to indicate when the stack checker has been initialized.
  */
-static int   Stack_check_Initialized = 0;
+static bool Stack_check_Initialized;
 
 /*
  *  The "magic pattern" used to mark the end of the stack.
@@ -137,7 +137,11 @@ static inline bool Stack_check_Frame_pointer_in_range(
 #define Stack_check_usable_stack_size(_the_stack) \
     ((_the_stack)->size - PATTERN_SIZE_BYTES)
 
-static Stack_Control Stack_check_Interrupt_stack;
+#if defined(RTEMS_SMP)
+static Stack_Control Stack_check_Interrupt_stack[ CPU_MAXIMUM_PROCESSORS ];
+#else
+static Stack_Control Stack_check_Interrupt_stack[ 1 ];
+#endif
 
 /*
  *  Fill an entire stack area with BYTE_PATTERN.  This will be used
@@ -146,30 +150,6 @@ static Stack_Control Stack_check_Interrupt_stack;
 #define Stack_check_Dope_stack(_stack) \
   memset((_stack)->area, BYTE_PATTERN, (_stack)->size)
 
-/*
- *  Stack_check_Initialize
- */
-static void Stack_check_Initialize( void )
-{
-  if ( Stack_check_Initialized )
-    return;
-
-  /*
-   * If appropriate, setup the interrupt stack for high water testing
-   * also.
-   */
-  #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
-    if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high) {
-      Stack_check_Interrupt_stack.area = _CPU_Interrupt_stack_low;
-      Stack_check_Interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
-                                  (char *) _CPU_Interrupt_stack_low;
-      Stack_check_Dope_stack(&Stack_check_Interrupt_stack);
-   }
-  #endif
-
-  Stack_check_Initialized = 1;
-}
-
 static bool Stack_check_Is_pattern_valid(const Thread_Control *the_thread)
 {
   return memcmp(
@@ -187,9 +167,9 @@ bool rtems_stack_checker_create_extension(
   Thread_Control *the_thread
 )
 {
-  Stack_check_Initialize();
-  Stack_check_Dope_stack(&the_thread->Start.Initial_stack);
+  Stack_check_Initialized = true;
 
+  Stack_check_Dope_stack(&the_thread->Start.Initial_stack);
   memcpy(
     Stack_check_Get_pattern(&the_thread->Start.Initial_stack),
     Stack_check_Pattern,
@@ -199,6 +179,44 @@ bool rtems_stack_checker_create_extension(
   return true;
 }
 
+void rtems_stack_checker_begin_extension( Thread_Control *executing )
+{
+#if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
+  Per_CPU_Control *cpu_self;
+  uint32_t         cpu_self_index;
+  Stack_Control   *stack;
+
+  /*
+   * If appropriate, set up the interrupt stack of the current processor for
+   * high water testing also.  This must be done after multi-threading started,
+   * since the initialization stacks may reuse the interrupt stacks.  Disable
+   * thread dispatching in SMP configurations to prevent thread migration.
+   * Writing to the interrupt stack is only safe if done from the corresponding
+   * processor in thread context.
+   */
+
+#if defined(RTEMS_SMP)
+  cpu_self = _Thread_Dispatch_disable();
+#else
+  cpu_self = _Per_CPU_Get();
+#endif
+
+  cpu_self_index = _Per_CPU_Get_index( cpu_self );
+  stack = &Stack_check_Interrupt_stack[ cpu_self_index ];
+
+  if ( stack->area == NULL ) {
+    stack->area = cpu_self->interrupt_stack_low;
+    stack->size = (size_t) ( (char *) cpu_self->interrupt_stack_high -
+      (char *) cpu_self->interrupt_stack_low );
+    Stack_check_Dope_stack( stack );
+  }
+
+#if defined(RTEMS_SMP)
+  _Thread_Dispatch_enable( cpu_self );
+#endif
+#endif
+}
+
 /*
  *  Stack_check_report_blown_task
  *
@@ -365,10 +383,10 @@ static bool Stack_check_Dump_stack_usage(
     size
   );
 
-  if (Stack_check_Initialized == 0) {
-    rtems_printf( printer, "N/A\n" );
-  } else {
+  if (Stack_check_Initialized) {
     rtems_printf( printer, "%6" PRId32 "\n", used );
+  } else {
+    rtems_printf( printer, "N/A\n" );
   }
 
   return false;
@@ -396,14 +414,15 @@ static bool Stack_check_Dump_threads_usage(
 
 static void Stack_check_Dump_interrupt_stack_usage(
   const Stack_Control *stack,
+  uint32_t             id,
   const rtems_printer *printer
 )
 {
   Stack_check_Dump_stack_usage(
     stack,
     NULL,
-    "INTR",
-    0xffffffff,
+    "Interrupt Stack",
+    id,
     printer
   );
 }
@@ -416,6 +435,9 @@ void rtems_stack_checker_report_usage_with_plugin(
   const rtems_printer* printer
 )
 {
+  uint32_t cpu_max;
+  uint32_t cpu_index;
+
   rtems_printf(
      printer,
      "                             STACK USAGE BY THREAD\n"
@@ -428,10 +450,15 @@ void rtems_stack_checker_report_usage_with_plugin(
     RTEMS_DECONST( rtems_printer *, printer )
   );
 
-  Stack_check_Dump_interrupt_stack_usage(
-    &Stack_check_Interrupt_stack,
-    printer
-  );
+  cpu_max = rtems_get_processor_count();
+
+  for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) {
+    Stack_check_Dump_interrupt_stack_usage(
+      &Stack_check_Interrupt_stack[ cpu_index ],
+      cpu_index,
+      printer
+    );
+  }
 }
 
 void rtems_stack_checker_report_usage( void )
-- 
2.13.7



More information about the devel mailing list