Index: cpukit/libmisc/stackchk/check.c
===================================================================
--- cpukit/libmisc/stackchk/check.c	(revision 17f744b8c81be98f68d53a82583c9a0b1c690579)
+++ cpukit/libmisc/stackchk/check.c	(revision ac7d5ef06a6d6e8d84abbd1f0b82162725f98326)
@@ -1,596 +1,439 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-
-/**
- * @file
- *
- * @ingroup libmisc_stackchk Stack Checker Mechanism
- *
- * @brief Stack Overflow Check User Extension Set
- *
- * NOTE:  This extension set automatically determines at
+/*
+ *  Stack Overflow Check User Extension Set
+ *
+ *  NOTE:  This extension set automatically determines at
  *         initialization time whether the stack for this
  *         CPU grows up or down and installs the correct
  *         extension routines for that direction.
- */
-
-/*
- *  COPYRIGHT (c) 1989-2010.
+ *
+ *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
  *  On-Line Applications Research Corporation (OAR).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+ *  All rights assigned to U.S. Government, 1994.
+ *
+ *  This material may be reproduced by or for the U.S. Government pursuant
+ *  to the copyright license under the clause at DFARS 252.227-7013.  This
+ *  notice must appear in all copies of this file and its derivatives.
+ *
+ *  $Id$
+ *
+ */
+
+#include <rtems/system.h>
+#include <rtems/extension.h>
+#include <rtems/fatal.h>
+#include <rtems/heap.h>
+#include <rtems/stack.h>
+#include <rtems/thread.h>
+#ifdef XXX_RTEMS_H_FIXED
+#include <bsp.h>
+#else
+#include <rtems/config.h>
+extern rtems_configuration_table BSP_Configuration;
 #endif
 
-#include <rtems.h>
-#include <inttypes.h>
-
+#include <assert.h>
+#include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 
-#include <rtems/bspIo.h>
-#include <rtems/printer.h>
-#include <rtems/stackchk.h>
-#include <rtems/sysinit.h>
-#include <rtems/score/address.h>
-#include <rtems/score/percpu.h>
-#include <rtems/score/smp.h>
-#include <rtems/score/threadimpl.h>
-
-/*
- *  This structure is used to fill in and compare the "end of stack"
- *  marker pattern.
- *  pattern area must be a multiple of 4 words.
- */
-
-#if !defined(CPU_STACK_CHECK_PATTERN_INITIALIZER)
-#define CPU_STACK_CHECK_PATTERN_INITIALIZER \
-  { \
-    0xFEEDF00D, 0x0BAD0D06, /* FEED FOOD to  BAD DOG */ \
-    0xDEADF00D, 0x600D0D06  /* DEAD FOOD but GOOD DOG */ \
-  }
-#endif
-
-/*
- *  The pattern used to fill the entire stack.
- */
-
-#define BYTE_PATTERN 0xA5
-#define U32_PATTERN 0xA5A5A5A5
-
-/*
- *  Variable to indicate when the stack checker has been initialized.
- */
-static bool Stack_check_Initialized;
+#include "stackchk.h"
+#include "internal.h"
+
+/*
+ *  This variable contains the name of the task which "blew" the stack.
+ *  It is NULL if the system is all right.
+ */
+
+Thread_Control *Stack_check_Blown_task;
+
+/*
+ *  The extension table for the stack checker.
+ */
+
+rtems_extensions_table Stack_check_Extension_table = {
+  Stack_check_Create_extension,     /* rtems_task_create  */
+  0,                                /* rtems_task_start   */
+  0,                                /* rtems_task_restart */
+  0,                                /* rtems_task_delete  */
+  Stack_check_Switch_extension,     /* task_switch  */
+  Stack_check_Begin_extension,      /* task_begin   */
+  0,                                /* task_exitted */
+  Stack_check_Fatal_extension,      /* fatal        */
+};
 
 /*
  *  The "magic pattern" used to mark the end of the stack.
  */
-static const uint32_t Stack_check_Sanity_pattern[] =
-  CPU_STACK_CHECK_PATTERN_INITIALIZER;
-
-#define SANITY_PATTERN_SIZE_BYTES sizeof(Stack_check_Sanity_pattern)
-
-#define SANITY_PATTERN_SIZE_WORDS RTEMS_ARRAY_SIZE(Stack_check_Sanity_pattern)
-
-/*
- * Helper function to report if the actual stack pointer is in range.
- *
- * NOTE: This uses a GCC specific method.
- */
-static inline bool Stack_check_Frame_pointer_in_range(
-  const Thread_Control *the_thread
-)
-{
-  #if defined(__GNUC__)
-    void *sp = __builtin_frame_address(0);
-    const Stack_Control *the_stack = &the_thread->Start.Initial_stack;
-
-    if ( sp < the_stack->area ) {
-      return false;
-    }
-    if ( sp > (the_stack->area + the_stack->size) ) {
-      return false;
-    }
-  #else
-    #error "How do I check stack bounds on a non-GNU compiler?"
-  #endif
-  return true;
-}
+
+Stack_check_Control Stack_check_Pattern;
 
 /*
  *  Where the pattern goes in the stack area is dependent upon
  *  whether the stack grow to the high or low area of the memory.
- */
-#if (CPU_STACK_GROWS_UP == TRUE)
-  #define Stack_check_Get_pattern( _the_stack ) \
-    ((char *)(_the_stack)->area + \
-         (_the_stack)->size - SANITY_PATTERN_SIZE_BYTES )
-
-  #define Stack_check_Calculate_used( _low, _size, _high_water ) \
-      ((char *)(_high_water) - (char *)(_low))
-
-  #define Stack_check_Usable_stack_start(_the_stack) \
+ *
+ */
+
+#if ( CPU_STACK_GROWS_UP == TRUE )
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+  ((Stack_check_Control *) \
+    ((_the_stack)->area + (_the_stack)->size - sizeof( Stack_check_Control ) ))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water ) \
+    ((_high_water) - (_low))
+
+#define Stack_check_usable_stack_start(_the_stack) \
     ((_the_stack)->area)
 
 #else
-  #define Stack_check_Get_pattern( _the_stack ) \
-    ((char *)(_the_stack)->area)
-
-  #define Stack_check_Calculate_used( _low, _size, _high_water) \
-      ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
-
-  #define Stack_check_Usable_stack_start(_the_stack) \
-      ((char *)(_the_stack)->area + SANITY_PATTERN_SIZE_BYTES)
+
+#define Stack_check_Get_pattern_area( _the_stack ) \
+  ((Stack_check_Control *) ((_the_stack)->area + HEAP_OVERHEAD))
+
+#define Stack_check_Calculate_used( _low, _size, _high_water) \
+    ( ((_low) + (_size)) - (_high_water) )
+
+#define Stack_check_usable_stack_start(_the_stack) \
+    ((_the_stack)->area + sizeof(Stack_check_Control))
 
 #endif
 
-/*
- *  The assumption is that if the pattern gets overwritten, the task
- *  is too close.  This defines the usable stack memory.
- */
-#define Stack_check_Usable_stack_size(_the_stack) \
-    ((_the_stack)->size - SANITY_PATTERN_SIZE_BYTES)
-
-#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
- *  to check for amount of actual stack used.
- */
-static void Stack_check_Dope_stack( Stack_Control *stack )
-{
-  memset(
-    Stack_check_Usable_stack_start( stack ),
-    BYTE_PATTERN,
-    Stack_check_Usable_stack_size( stack )
+#define Stack_check_usable_stack_size(_the_stack) \
+    ((_the_stack)->size - sizeof(Stack_check_Control))
+
+
+/*
+ * Do we have an interrupt stack?
+ * XXX it would sure be nice if the interrupt stack were also
+ *     stored in a "stack" structure!
+ */
+
+
+Stack_Control stack_check_interrupt_stack;
+
+/*
+ * Fill an entire stack area with BYTE_PATTERN.
+ * This will be used by a Fatal extension to check for
+ * amount of actual stack used
+ */
+
+void
+stack_check_dope_stack(Stack_Control *stack)
+{
+    memset(stack->area, BYTE_PATTERN, stack->size);
+}
+
+
+/*PAGE
+ *
+ *  Stack_check_Initialize
+ */
+
+unsigned32 stack_check_initialized = 0;
+
+void Stack_check_Initialize( void )
+{
+  rtems_status_code status;
+  Objects_Id   id_ignored;
+  unsigned32  *p;
+
+  if (stack_check_initialized)
+      return;
+
+  /*
+   * Dope the pattern and fill areas
+   */
+
+  for ( p = Stack_check_Pattern.pattern;
+        p < &Stack_check_Pattern.pattern[PATTERN_SIZE_WORDS];
+        p += 4
+      )
+  {
+      p[0] = 0xFEEDF00D;          /* FEED FOOD to BAD DOG */
+      p[1] = 0x0BAD0D06;
+      p[2] = 0xDEADF00D;          /* DEAD FOOD GOOD DOG */
+      p[3] = 0x600D0D06;
+  };
+
+  status = rtems_extension_create(
+    rtems_build_name( 'S', 'T', 'C', 'K' ),
+    &Stack_check_Extension_table,
+    &id_ignored
   );
-}
-
-static void Stack_check_Add_sanity_pattern( Stack_Control *stack )
-{
-  memcpy(
-    Stack_check_Get_pattern( stack ),
-    Stack_check_Sanity_pattern,
-    SANITY_PATTERN_SIZE_BYTES
-  );
-}
-
-static bool Stack_check_Is_sanity_pattern_valid( const Stack_Control *stack )
-{
-  return memcmp(
-    Stack_check_Get_pattern( stack ),
-    Stack_check_Sanity_pattern,
-    SANITY_PATTERN_SIZE_BYTES
-  ) == 0;
-}
-
-/*
- *  rtems_stack_checker_create_extension
- */
-bool rtems_stack_checker_create_extension(
-  Thread_Control *running RTEMS_UNUSED,
+  assert ( status == RTEMS_SUCCESSFUL );
+
+  Stack_check_Blown_task = 0;
+
+  /*
+   * If installed by a task, that task will not get setup properly
+   * since it missed out on the create hook.  This will cause a
+   * failure on first switch out of that task.
+   * So pretend here that we actually ran create and begin extensions.
+   */
+
+  if (_Thread_Executing)
+  {
+      Stack_check_Create_extension(_Thread_Executing, _Thread_Executing);
+  }
+
+  /*
+   * If appropriate, setup the interrupt stack for high water testing
+   * also.
+   */
+  if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high)
+  {
+      stack_check_interrupt_stack.area = _CPU_Interrupt_stack_low;
+      stack_check_interrupt_stack.size = _CPU_Interrupt_stack_high -
+                                               _CPU_Interrupt_stack_low;
+
+      stack_check_dope_stack(&stack_check_interrupt_stack);
+  }
+
+  stack_check_initialized = 1;
+}
+
+/*PAGE
+ *
+ *  Stack_check_Create_extension
+ */
+
+void Stack_check_Create_extension(
+  Thread_Control *running,
   Thread_Control *the_thread
 )
 {
-  Stack_check_Initialized = true;
-
-  Stack_check_Dope_stack( &the_thread->Start.Initial_stack );
-  Stack_check_Add_sanity_pattern( &the_thread->Start.Initial_stack );
-
-  return true;
-}
-
-void rtems_stack_checker_begin_extension( Thread_Control *executing )
-{
-  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 );
-
-    /*
-     * Sanity pattern has been added by Stack_check_Prepare_interrupt_stack()
-     */
-    if ( !Stack_check_Is_sanity_pattern_valid( stack ) ) {
-      rtems_fatal(
-        RTEMS_FATAL_SOURCE_STACK_CHECKER,
-        rtems_build_name( 'I', 'N', 'T', 'R' )
-      );
-    }
-
-    Stack_check_Dope_stack( stack );
-  }
-
-#if defined(RTEMS_SMP)
-  _Thread_Dispatch_enable( cpu_self );
-#endif
-}
-
-/*
+    if (the_thread && (the_thread != _Thread_Executing))
+        stack_check_dope_stack(&the_thread->Start.Initial_stack);
+}
+
+/*PAGE
+ *
+ *  Stack_check_Begin_extension
+ */
+
+void Stack_check_Begin_extension(
+  Thread_Control *the_thread
+)
+{
+  Stack_check_Control  *the_pattern;
+
+  if ( the_thread->Object.id == 0 )        /* skip system tasks */
+    return;
+
+  the_pattern = Stack_check_Get_pattern_area(&the_thread->Start.Initial_stack);
+
+  *the_pattern = Stack_check_Pattern;
+}
+
+/*PAGE
+ *
  *  Stack_check_report_blown_task
- *
  *  Report a blown stack.  Needs to be a separate routine
  *  so that interrupt handlers can use this too.
  *
+ *  Caller must have set the Stack_check_Blown_task.
+ *
  *  NOTE: The system is in a questionable state... we may not get
  *        the following message out.
  */
-static void Stack_check_report_blown_task(
-  const Thread_Control *running,
-  bool pattern_ok
-)
-{
-  const Stack_Control *stack = &running->Start.Initial_stack;
-  void                *pattern_area = Stack_check_Get_pattern(stack);
-  char                 name[2 * THREAD_DEFAULT_MAXIMUM_NAME_SIZE];
-
-  printk("BLOWN STACK!!!\n");
-  printk("task control block: 0x%08" PRIxPTR "\n", (intptr_t) running);
-  printk("task ID: 0x%08lx\n", (unsigned long) running->Object.id);
-  printk(
-    "task name: 0x%08" PRIx32 "\n",
-    running->Object.name.name_u32
-  );
-  _Thread_Get_name(running, name, sizeof(name));
-  printk("task name string: %s\n", name);
-  printk(
-    "task stack area (%lu Bytes): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",
-    (unsigned long) stack->size,
-    (intptr_t) stack->area,
-    (intptr_t) ((char *) stack->area + stack->size)
-  );
-  if (!pattern_ok) {
-    printk(
-      "damaged pattern area (%lu Bytes): 0x%08" PRIxPTR " .. 0x%08" PRIxPTR "\n",
-      (unsigned long) SANITY_PATTERN_SIZE_BYTES,
-      (intptr_t) pattern_area,
-      (intptr_t) (pattern_area + SANITY_PATTERN_SIZE_BYTES)
-    );
-  }
-
-  #if defined(RTEMS_MULTIPROCESSING)
-    if (rtems_configuration_get_user_multiprocessing_table()) {
-      printk(
-        "node: 0x%08" PRIxPTR "\n",
-          (intptr_t) rtems_configuration_get_user_multiprocessing_table()->node
-      );
-    }
-  #endif
-
-  rtems_fatal(
-    RTEMS_FATAL_SOURCE_STACK_CHECKER,
-    running->Object.name.name_u32
-  );
-}
-
-/*
- *  rtems_stack_checker_switch_extension
- */
-void rtems_stack_checker_switch_extension(
+
+void Stack_check_report_blown_task(void)
+{
+    Stack_Control *stack;
+    Thread_Control *running;
+
+    running = Stack_check_Blown_task;
+    stack = &running->Start.Initial_stack;
+
+    fprintf(
+        stderr,
+        "BLOWN STACK!!! Offending task(%p): id=0x%08x; name=0x%08x",
+        running,
+        running->Object.id,
+        running->name);
+    fflush(stderr);
+
+    if (BSP_Configuration.User_multiprocessing_table)
+        fprintf(
+          stderr,
+          "; node=%d\n",
+          BSP_Configuration.User_multiprocessing_table->node
+       );
+    else
+        fprintf(stderr, "\n");
+    fflush(stderr);
+
+    fprintf(
+        stderr,
+        "  stack covers range 0x%08x - 0x%08x (%d bytes)\n",
+        (unsigned32) stack->area,
+        (unsigned32) stack->area + stack->size - 1,
+        (unsigned32) stack->size);
+    fflush(stderr);
+
+    fprintf(
+        stderr,
+        "  Damaged pattern begins at 0x%08x and is %d bytes long\n",
+        (unsigned32) Stack_check_Get_pattern_area(stack), PATTERN_SIZE_BYTES);
+    fflush(stderr);
+
+    rtems_fatal_error_occurred( (unsigned32) "STACK BLOWN" );
+}
+
+/*PAGE
+ *
+ *  Stack_check_Switch_extension
+ */
+
+void Stack_check_Switch_extension(
   Thread_Control *running,
   Thread_Control *heir
 )
 {
-  bool sp_ok;
-  bool pattern_ok;
-  const Stack_Control *stack;
-
-  /*
-   *  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 );
+  if ( running->Object.id == 0 )        /* skip system tasks */
+    return;
+
+  if (0 != memcmp( (void *) Stack_check_Get_pattern_area( &running->Start.Initial_stack)->pattern,
+                  (void *) Stack_check_Pattern.pattern,
+                  PATTERN_SIZE_BYTES))
+  {
+      Stack_check_Blown_task = running;
+      Stack_check_report_blown_task();
   }
-
-  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 );
-
-  if ( !sp_ok || !pattern_ok ) {
-    Stack_check_report_blown_task( running, pattern_ok );
-  }
-#endif
-
-  stack = &Stack_check_Interrupt_stack[ _SMP_Get_current_processor() ];
-
-  if ( stack->area != NULL && !Stack_check_Is_sanity_pattern_valid( stack ) ) {
-    rtems_fatal(
-      RTEMS_FATAL_SOURCE_STACK_CHECKER,
-      rtems_build_name( 'I', 'N', 'T', 'R' )
-    );
-  }
-}
-
-/*
- *  Check if blown
- */
-bool rtems_stack_checker_is_blown( void )
-{
-  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.
-   */
-  return false;
-}
-
-/*
- * Stack_check_find_high_water_mark
- */
-static inline void *Stack_check_Find_high_water_mark(
+}
+
+void *Stack_check_find_high_water_mark(
   const void *s,
-  size_t      n
+  size_t n
 )
 {
-  const uint32_t   *base, *ebase;
-  uint32_t   length;
+  const unsigned32 *base, *ebase;
+  unsigned32 length;
 
   base = s;
   length = n/4;
 
-  #if ( CPU_STACK_GROWS_UP == TRUE )
-    /*
-     * start at higher memory and find first word that does not
-     * match pattern
-     */
-
-    base += length - 1;
-    for (ebase = s; base > ebase; base--)
+#if ( CPU_STACK_GROWS_UP == TRUE )
+  /*
+   * start at higher memory and find first word that does not
+   * match pattern
+   */
+
+  base += length - 1;
+  for (ebase = s; base > ebase; base--)
       if (*base != U32_PATTERN)
-        return (void *) base;
-  #else
-    /*
-     * start at lower memory and find first word that does not
-     * match pattern
-     */
-
-    base += SANITY_PATTERN_SIZE_WORDS;
-    for (ebase = base + length; base < ebase; base++)
+          return (void *) base;
+#else
+  /*
+   * start at lower memory and find first word that does not
+   * match pattern
+   */
+
+  for (ebase = base + length; base < ebase; base++)
       if (*base != U32_PATTERN)
-        return (void *) base;
-  #endif
-
-  return NULL;
-}
-
-static void Stack_check_Visit_stack(
-  const Stack_Control        *stack,
-  const void                 *current,
-  const char                 *name,
-  rtems_id                    id,
-  rtems_stack_checker_visitor visit,
-  void                        *arg
+          return (void *) base;
+#endif
+
+  return (void *)0;
+}
+
+/*PAGE
+ *
+ *  Stack_check_Dump_threads_usage
+ *  Try to print out how much stack was actually used by the task.
+ *
+ */
+
+void Stack_check_Dump_threads_usage(
+  Thread_Control *the_thread
 )
 {
-  rtems_stack_checker_info info;
-
-  /* This is likely to occur if the stack checker is not actually enabled */
-  if ( stack->area == NULL ) {
+  unsigned32      size, used;
+  void           *low;
+  void           *high_water_mark;
+  Stack_Control  *stack;
+
+  if ( !the_thread )
     return;
+
+  /*
+   * XXX HACK to get to interrupt stack
+   */
+
+  if (the_thread == (Thread_Control *) -1)
+  {
+      if (stack_check_interrupt_stack.area)
+      {
+          stack = &stack_check_interrupt_stack;
+          the_thread = 0;
+      }
+      else
+          return;
   }
-
-  info.id = id;
-  info.name = name;
-  info.current = current;
-  info.begin  = Stack_check_Usable_stack_start( stack );
-  info.size = Stack_check_Usable_stack_size( stack );
-
-  if ( Stack_check_Initialized ) {
-    void *high_water_mark;
-
-    high_water_mark =
-      Stack_check_Find_high_water_mark( info.begin, info.size );
-
-    if ( high_water_mark != NULL ) {
-      info.used =
-        Stack_check_Calculate_used( info.begin, info.size, high_water_mark );
-    } else {
-      info.used = 0;
-    }
-  } else {
-    info.used = UINTPTR_MAX;
+  else
+      stack = &the_thread->Start.Initial_stack;
+
+  low  = Stack_check_usable_stack_start(stack);
+  size = Stack_check_usable_stack_size(stack);
+
+  high_water_mark = Stack_check_find_high_water_mark(low, size);
+
+  if ( high_water_mark )
+    used = Stack_check_Calculate_used( low, size, high_water_mark );
+  else
+    used = 0;
+
+  printf( "0x%08x  0x%08x  0x%08x  0x%08x   %8d   %8d\n",
+          the_thread ? the_thread->Object.id : ~0,
+          the_thread ? the_thread->name :
+                       rtems_build_name('I', 'N', 'T', 'R'),
+          (unsigned32) stack->area,
+          (unsigned32) stack->area + (unsigned32) stack->size - 1,
+          size,
+          used
+  );
+}
+
+/*PAGE
+ *
+ *  Stack_check_Fatal_extension
+ */
+
+void Stack_check_Fatal_extension( unsigned32 status )
+{
+    if (status == 0)
+        Stack_check_Dump_usage();
+}
+
+
+/*PAGE
+ *
+ *  Stack_check_Dump_usage
+ */
+
+void Stack_check_Dump_usage( void )
+{
+  unsigned32      i;
+  Thread_Control *the_thread;
+  unsigned32      hit_running = 0;
+
+  if (stack_check_initialized == 0)
+      return;
+
+  printf(
+    "   ID          NAME         LOW        HIGH      AVAILABLE     USED\n"
+  );
+  for ( i=1 ; i<_Thread_Information.maximum ; i++ ) {
+    the_thread = (Thread_Control *)_Thread_Information.local_table[ i ];
+    Stack_check_Dump_threads_usage( the_thread );
+    if ( the_thread == _Thread_Executing )
+      hit_running = 1;
   }
 
-  ( *visit )( &info, arg );
-}
-
-typedef struct {
-  rtems_stack_checker_visitor visit;
-  void *arg;
-} Stack_check_Visitor;
-
-static bool Stack_check_Visit_thread(
-  Thread_Control *the_thread,
-  void           *arg
-)
-{
-  Stack_check_Visitor *visitor;
-  char                 name[ 22 ];
-  uintptr_t sp = _CPU_Context_Get_SP( &the_thread->Registers );
-
-  visitor = arg;
-  _Thread_Get_name( the_thread, name, sizeof( name ) );
-  Stack_check_Visit_stack(
-    &the_thread->Start.Initial_stack,
-    (void *) sp,
-    name,
-    the_thread->Object.id,
-    visitor->visit,
-    visitor->arg
-  );
-  return false;
-}
-
-static void Stack_check_Visit_interrupt_stack(
-  const Stack_Control        *stack,
-  uint32_t                    id,
-  rtems_stack_checker_visitor visit,
-  void                       *arg
-)
-{
-  Stack_check_Visit_stack(
-    stack,
-    NULL,
-    "Interrupt Stack",
-    id,
-    visit,
-    arg
-  );
-}
-
-static void Stack_check_Print_info(
-  const rtems_stack_checker_info *info,
-  void                           *arg
-)
-{
-  const rtems_printer *printer;
-
-  printer = arg;
-
-  rtems_printf(
-    printer,
-    "0x%08" PRIx32 " %-21s 0x%08" PRIxPTR " 0x%08" PRIxPTR " 0x%08" PRIxPTR " %6" PRIuPTR " ",
-    info->id,
-    info->name,
-    (uintptr_t) info->begin,
-    (uintptr_t) info->begin + info->size - 1,
-    (uintptr_t) info->current,
-    info->size
-  );
-
-  if ( info->used != UINTPTR_MAX ) {
-    rtems_printf( printer, "%6" PRIuPTR "\n", info->used );
-  } else {
-    rtems_printf( printer, "N/A\n" );
-  }
-}
-
-void rtems_stack_checker_report_usage_with_plugin(
-  const rtems_printer* printer
-)
-{
-  rtems_printf(
-     printer,
-     "                             STACK USAGE BY THREAD\n"
-     "ID         NAME                  LOW        HIGH       CURRENT     AVAIL   USED\n"
-  );
-
-  rtems_stack_checker_iterate(
-    Stack_check_Print_info,
-    RTEMS_DECONST( rtems_printer *, printer )
-  );
-}
-
-void rtems_stack_checker_report_usage( void )
-{
-  rtems_printer printer;
-  rtems_print_printer_printk(&printer);
-  rtems_stack_checker_report_usage_with_plugin( &printer );
-}
-
-void rtems_stack_checker_iterate( rtems_stack_checker_visitor visit, void *arg )
-{
-  Stack_check_Visitor visitor;
-  uint32_t            cpu_max;
-  uint32_t            cpu_index;
-
-  visitor.visit = visit;
-  visitor.arg = arg;
-  rtems_task_iterate( Stack_check_Visit_thread, &visitor );
-
-  cpu_max = rtems_scheduler_get_processor_maximum();
-
-  for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) {
-    Stack_check_Visit_interrupt_stack(
-      &Stack_check_Interrupt_stack[ cpu_index ],
-      cpu_index,
-      visit,
-      arg
-    );
-  }
-}
-
-static void Stack_check_Prepare_interrupt_stacks( void )
-{
-  Stack_Control stack;
-  uint32_t      cpu_index;
-  uint32_t      cpu_max;
-
-  stack.size = rtems_configuration_get_interrupt_stack_size();
-  stack.area = _ISR_Stack_area_begin;
-  cpu_max = rtems_configuration_get_maximum_processors();
-
-  for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) {
-    Stack_check_Add_sanity_pattern( &stack );
-    stack.area = _Addresses_Add_offset( stack.area, stack.size );
-  }
-}
-
-RTEMS_SYSINIT_ITEM(
-  Stack_check_Prepare_interrupt_stacks,
-  RTEMS_SYSINIT_ISR_STACK,
-  RTEMS_SYSINIT_ORDER_MIDDLE
-);
+  if ( !hit_running )
+    Stack_check_Dump_threads_usage( _Thread_Executing );
+
+  /* dump interrupt stack info if any */
+  Stack_check_Dump_threads_usage((Thread_Control *) -1);
+}
+
