Changeset 4da36c1a in rtems


Ignore:
Timestamp:
May 11, 2007, 8:01:37 PM (13 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
70669f28
Parents:
e974f9d7
Message:

2007-05-11 Joel Sherrill <joel.sherrill@…>

  • libmisc/cpuuse/cpuuse.c, libmisc/stackchk/check.c, libmisc/stackchk/stackchk.h: Clean up as side-effect of making them suitable for inclusion in the Users Guide.
Location:
cpukit
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    re974f9d7 r4da36c1a  
     12007-05-11      Joel Sherrill <joel.sherrill@OARcorp.com>
     2
     3        * libmisc/cpuuse/cpuuse.c, libmisc/stackchk/check.c,
     4        libmisc/stackchk/stackchk.h: Clean up as side-effect of making them
     5        suitable for inclusion in the Users Guide.
     6
    172007-05-11      Joel Sherrill <joel.sherrill@oarcorp.com>
    28
  • cpukit/libmisc/cpuuse/cpuuse.c

    re974f9d7 r4da36c1a  
    22 *  CPU Usage Reporter
    33 *
    4  *  COPYRIGHT (c) 1989-2006
     4 *  COPYRIGHT (c) 1989-2007
    55 *  On-Line Applications Research Corporation (OAR).
    66 *
  • cpukit/libmisc/stackchk/check.c

    re974f9d7 r4da36c1a  
    2626
    2727/*
    28  * HACK
    29  * the stack dump information should be printed by a "fatal" extension.
     28 * The stack dump information may be printed by a "fatal" extension.
    3029 * Fatal extensions only get called via rtems_fatal_error_occurred()
    3130 * and not when rtems_shutdown_executive() is called.
    32  * I hope/think this is changing so that fatal extensions are renamed
    33  * to "shutdown" extensions.
    3431 * When that happens, this #define should be deleted and all the code
    3532 * it marks.
     
    4643
    4744/*
    48  *  The extension table for the stack checker.
    49  */
    50 
    51 rtems_extensions_table rtems_stack_checker_extension_table = {
    52   rtems_stack_checker_create_extension,     /* rtems_task_create  */
    53   0,                                        /* rtems_task_start   */
    54   0,                                        /* rtems_task_restart */
    55   0,                                        /* rtems_task_delete  */
    56   rtems_stack_checker_switch_extension,     /* task_switch  */
    57   rtems_stack_checker_begin_extension,      /* task_begin   */ 0,                                /* task_exitted */
    58 #ifdef DONT_USE_FATAL_EXTENSION
    59   0,                                        /* fatal        */
    60 #else
    61   rtems_stack_checker_fatal_extension,      /* fatal        */
    62 #endif
    63 };
     45 *  Variable to indicate when the stack checker has been initialized.
     46 */
     47static int   Stack_check_Initialized = 0;
    6448
    6549/*
    6650 *  The "magic pattern" used to mark the end of the stack.
    6751 */
    68 
    6952Stack_check_Control Stack_check_Pattern;
    7053
     
    7457 * NOTE: This uses a GCC specific method.
    7558 */
    76 
    7759static inline boolean Stack_check_Frame_pointer_in_range(
    7860  Stack_Control *the_stack
     
    9072      return FALSE;
    9173    }
     74  #else
     75    #error "How do I check stack bounds on a non-GNU compiler?"
    9276  #endif
    9377  return TRUE;
     
    9781 *  Where the pattern goes in the stack area is dependent upon
    9882 *  whether the stack grow to the high or low area of the memory.
    99  *
    100  */
    101 #if ( CPU_STACK_GROWS_UP == TRUE )
    102 
    103 #define Stack_check_Get_pattern_area( _the_stack ) \
    104   ((Stack_check_Control *) ((char *)(_the_stack)->area + \
    105        (_the_stack)->size - sizeof( Stack_check_Control ) ))
    106 
    107 #define Stack_check_Calculate_used( _low, _size, _high_water ) \
    108     ((char *)(_high_water) - (char *)(_low))
    109 
    110 #define Stack_check_usable_stack_start(_the_stack) \
     83 */
     84#if (CPU_STACK_GROWS_UP == TRUE)
     85  #define Stack_check_Get_pattern_area( _the_stack ) \
     86    ((Stack_check_Control *) ((char *)(_the_stack)->area + \
     87         (_the_stack)->size - sizeof( Stack_check_Control ) ))
     88
     89  #define Stack_check_Calculate_used( _low, _size, _high_water ) \
     90      ((char *)(_high_water) - (char *)(_low))
     91
     92  #define Stack_check_usable_stack_start(_the_stack) \
    11193    ((_the_stack)->area)
    11294
    11395#else
    114 
    115 
    116 #define Stack_check_Get_pattern_area( _the_stack ) \
    117   ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
    118 
    119 #define Stack_check_Calculate_used( _low, _size, _high_water) \
    120     ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
    121 
    122 #define Stack_check_usable_stack_start(_the_stack) \
    123     ((char *)(_the_stack)->area + sizeof(Stack_check_Control))
     96  #define Stack_check_Get_pattern_area( _the_stack ) \
     97    ((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
     98
     99  #define Stack_check_Calculate_used( _low, _size, _high_water) \
     100      ( ((char *)(_low) + (_size)) - (char *)(_high_water) )
     101
     102  #define Stack_check_usable_stack_start(_the_stack) \
     103      ((char *)(_the_stack)->area + sizeof(Stack_check_Control))
    124104
    125105#endif
    126106
     107/*
     108 *  The assumption is that if the pattern gets overwritten, the task
     109 *  is too close.  This defines the usable stack memory.
     110 */
    127111#define Stack_check_usable_stack_size(_the_stack) \
    128112    ((_the_stack)->size - sizeof(Stack_check_Control))
    129 
    130113
    131114/*
     
    134117 *     stored in a "stack" structure!
    135118 */
    136 
    137 
    138 Stack_Control stack_check_interrupt_stack;
    139 
    140 /*
    141  * Fill an entire stack area with BYTE_PATTERN.
    142  * This will be used by a Fatal extension to check for
    143  * amount of actual stack used
    144  */
    145 
    146 void
    147 stack_check_dope_stack(Stack_Control *stack)
    148 {
    149     memset(stack->area, BYTE_PATTERN, stack->size);
    150 }
    151 
    152 
    153 /*PAGE
    154  *
    155  *  rtems_stack_checker_initialize
    156  */
    157 
    158 static int   stack_check_initialized = 0;
    159 
    160 void rtems_stack_checker_initialize( void )
    161 {
    162   uint32_t            *p;
    163 
    164   if (stack_check_initialized)
     119Stack_Control Stack_check_Interrupt_stack;
     120
     121/*
     122 *  Fill an entire stack area with BYTE_PATTERN.  This will be used
     123 *  to check for amount of actual stack used.
     124 */
     125#define Stack_check_Dope_stack(_stack) \
     126  memset((_stack)->area, BYTE_PATTERN, (_stack)->size)
     127
     128/*
     129 *  Stack_check_Initialize
     130 */
     131void Stack_check_Initialize( void )
     132{
     133  uint32_t *p;
     134
     135  if (Stack_check_Initialized)
    165136    return;
    166137
     
    172143        p < &Stack_check_Pattern.pattern[PATTERN_SIZE_WORDS];
    173144        p += 4
    174       )
    175   {
     145      ) {
    176146      p[0] = 0xFEEDF00D;          /* FEED FOOD to BAD DOG */
    177147      p[1] = 0x0BAD0D06;
    178148      p[2] = 0xDEADF00D;          /* DEAD FOOD GOOD DOG */
    179149      p[3] = 0x600D0D06;
    180   };
    181 
    182   /*
    183    * If installed by a task, that task will not get setup properly
    184    * since it missed out on the create hook.  This will cause a
    185    * failure on first switch out of that task.
    186    * So pretend here that we actually ran create and begin extensions.
    187    */
    188 
     150  }
     151 
    189152  /*
    190153   * If appropriate, setup the interrupt stack for high water testing
    191154   * also.
    192155   */
    193 #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
    194   if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high)
    195   {
    196       stack_check_interrupt_stack.area = _CPU_Interrupt_stack_low;
    197       stack_check_interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
    198                                               (char *) _CPU_Interrupt_stack_low;
    199 
    200       stack_check_dope_stack(&stack_check_interrupt_stack);
    201   }
    202 #endif
    203 
    204 #ifdef DONT_USE_FATAL_EXTENSION
    205 #ifdef RTEMS_DEBUG
    206     /*
    207      * this would normally be called by a fatal extension
    208      * handler, but we don't run fatal extensions unless
    209      * we fatal error.
    210      */
    211   atexit(rtems_stack_checker_report_usage);
    212 #endif
    213 #endif
    214 
    215   stack_check_initialized = 1;
    216 }
    217 
    218 /*PAGE
    219  *
     156  #if (CPU_ALLOCATE_INTERRUPT_STACK == TRUE)
     157    if (_CPU_Interrupt_stack_low && _CPU_Interrupt_stack_high) {
     158      Stack_check_Interrupt_stack.area = _CPU_Interrupt_stack_low;
     159      Stack_check_Interrupt_stack.size = (char *) _CPU_Interrupt_stack_high -
     160                                  (char *) _CPU_Interrupt_stack_low;
     161      Stack_check_Dope_stack(&Stack_check_Interrupt_stack);
     162  }
     163  #endif
     164
     165  Stack_check_Initialized = 1;
     166}
     167
     168/*
    220169 *  rtems_stack_checker_create_extension
    221170 */
    222 
    223171boolean rtems_stack_checker_create_extension(
    224172  Thread_Control *running,
     
    226174)
    227175{
    228     if (!stack_check_initialized)
    229       rtems_stack_checker_initialize();
    230 
    231     if (the_thread /* XXX && (the_thread != _Thread_Executing) */ )
    232         stack_check_dope_stack(&the_thread->Start.Initial_stack);
    233 
    234     return TRUE;
    235 }
    236 
    237 /*PAGE
    238  *
     176  Stack_check_Initialize();
     177
     178  if (the_thread)
     179    Stack_check_Dope_stack(&the_thread->Start.Initial_stack);
     180
     181  return TRUE;
     182}
     183
     184/*
    239185 *  rtems_stack_checker_Begin_extension
    240186 */
    241 
    242187void rtems_stack_checker_begin_extension(
    243188  Thread_Control *the_thread
     
    246191  Stack_check_Control  *the_pattern;
    247192
    248   if (!stack_check_initialized)
    249     rtems_stack_checker_initialize();
    250 
    251193  if ( the_thread->Object.id == 0 )        /* skip system tasks */
    252194    return;
     
    257199}
    258200
    259 /*PAGE
    260  *
     201/*
    261202 *  Stack_check_report_blown_task
     203 *
    262204 *  Report a blown stack.  Needs to be a separate routine
    263205 *  so that interrupt handlers can use this too.
     
    266208 *        the following message out.
    267209 */
    268 
    269210void Stack_check_report_blown_task(
    270211  Thread_Control *running,
     
    272213)
    273214{
    274     Stack_Control *stack = &running->Start.Initial_stack;
    275 
     215  Stack_Control *stack = &running->Start.Initial_stack;
     216
     217  printk(
     218    "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32 "; name=0x%08" PRIx32,
     219    running,
     220    running->Object.id,
     221    (uint32_t) running->Object.name
     222  );
     223
     224  #if defined(RTEMS_MULTIPROCESSING)
     225    if (rtems_configuration_get_user_multiprocessing_table()) {
     226      printk(
     227        "; node=%d\n",
     228        rtems_configuration_get_user_multiprocessing_table()->node
     229      );
     230    }
     231  #else
     232      printk( "\n" );
     233  #endif
     234
     235  printk(
     236    "  stack covers range %p - %p (%d bytes)\n",
     237    stack->area,
     238    stack->area + stack->size - 1,
     239    stack->size
     240  );
     241
     242  if ( !pattern_ok ) {
    276243    printk(
    277         "BLOWN STACK!!! Offending task(%p): id=0x%08" PRIx32
    278              "; name=0x%08" PRIx32,
    279         running,
    280         running->Object.id,
    281         (uint32_t) running->Object.name
    282     );
    283 
    284     if (rtems_configuration_get_user_multiprocessing_table())
    285         printk(
    286           "; node=%d\n",
    287           rtems_configuration_get_user_multiprocessing_table()->node
    288        );
    289     else
    290         printk( "\n");
    291 
    292     printk(
    293         "  stack covers range %p - %p (%d bytes)\n",
    294         stack->area,
    295         stack->area + stack->size - 1,
    296         stack->size);
    297 
    298     if ( !pattern_ok ) {
    299       printk(
    300           "  Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
    301           (unsigned long) Stack_check_Get_pattern_area(stack),
    302           (long) PATTERN_SIZE_BYTES);
    303     }
    304 
    305     rtems_fatal_error_occurred( (uint32_t) "STACK BLOWN" );
    306 }
    307 
    308 /*PAGE
    309  *
     244      "  Damaged pattern begins at 0x%08lx and is %ld bytes long\n",
     245      (unsigned long) Stack_check_Get_pattern_area(stack),
     246      (long) PATTERN_SIZE_BYTES);
     247  }
     248
     249  rtems_fatal_error_occurred( 0x81 );
     250}
     251
     252/*
    310253 *  rtems_stack_checker_switch_extension
    311254 */
    312 
    313255void rtems_stack_checker_switch_extension(
    314256  Thread_Control *running,
     
    323265  pattern = (void *) Stack_check_Get_pattern_area(the_stack)->pattern;
    324266
    325 
    326267  /*
    327268   *  Check for an out of bounds stack pointer and then an overwrite
     
    337278}
    338279
     280/*
     281 *  Check if blown
     282 */
     283boolean rtems_stack_checker_is_blown( void )
     284{
     285  Stack_Control *the_stack = &_Thread_Executing->Start.Initial_stack;
     286  void          *pattern;
     287  boolean        sp_ok;
     288  boolean        pattern_ok = TRUE;
     289
     290  pattern = (void *) Stack_check_Get_pattern_area(the_stack)->pattern;
     291
     292  /*
     293   *  Check for an out of bounds stack pointer and then an overwrite
     294   */
     295
     296  sp_ok = Stack_check_Frame_pointer_in_range( the_stack );
     297  pattern_ok = (!memcmp( pattern,
     298            (void *) Stack_check_Pattern.pattern, PATTERN_SIZE_BYTES));
     299
     300  if ( !sp_ok || !pattern_ok ) {
     301    return TRUE;
     302  }
     303  return FALSE;
     304}
     305
     306/*
     307 * Stack_check_find_high_water_mark
     308 */
    339309void *Stack_check_find_high_water_mark(
    340310  const void *s,
    341   size_t n
     311  size_t      n
    342312)
    343313{
     
    348318  length = n/4;
    349319
    350 #if ( CPU_STACK_GROWS_UP == TRUE )
    351   /*
    352    * start at higher memory and find first word that does not
    353    * match pattern
    354    */
    355 
    356   base += length - 1;
    357   for (ebase = s; base > ebase; base--)
    358       if (*base != U32_PATTERN)
    359           return (void *) base;
    360 #else
    361   /*
    362    * start at lower memory and find first word that does not
    363    * match pattern
    364    */
    365 
    366   base += PATTERN_SIZE_WORDS;
    367   for (ebase = base + length; base < ebase; base++)
    368       if (*base != U32_PATTERN)
    369           return (void *) base;
    370 #endif
     320  #if ( CPU_STACK_GROWS_UP == TRUE )
     321    /*
     322     * start at higher memory and find first word that does not
     323     * match pattern
     324     */
     325
     326    base += length - 1;
     327    for (ebase = s; base > ebase; base--)
     328        if (*base != U32_PATTERN)
     329            return (void *) base;
     330  #else
     331    /*
     332     * start at lower memory and find first word that does not
     333     * match pattern
     334     */
     335
     336    base += PATTERN_SIZE_WORDS;
     337    for (ebase = base + length; base < ebase; base++)
     338        if (*base != U32_PATTERN)
     339            return (void *) base;
     340  #endif
    371341
    372342  return (void *)0;
    373343}
    374344
    375 /*PAGE
    376  *
     345/*
     346 *  Report Name
     347 */
     348
     349char *Stack_check_Get_object_name(
     350  Objects_Control  *the_object,
     351  char            **name
     352)
     353{
     354  Objects_Information *info;
     355
     356  info = _Objects_Get_information(the_object->id);
     357  if ( info->is_string ) {
     358    *name = (char *) the_object->name;
     359  } else {
     360    uint32_t  u32_name = (uint32_t) the_object->name;
     361    (*name)[ 0 ] = (u32_name >> 24) & 0xff;
     362    (*name)[ 1 ] = (u32_name >> 16) & 0xff;
     363    (*name)[ 2 ] = (u32_name >>  8) & 0xff;
     364    (*name)[ 3 ] = (u32_name >>  0) & 0xff;
     365    (*name)[ 4 ] = '\0';
     366  }
     367  return *name;
     368}
     369
     370/*
    377371 *  Stack_check_Dump_threads_usage(
     372 *
    378373 *  Try to print out how much stack was actually used by the task.
    379  *
    380  */
    381 
     374 */
    382375void Stack_check_Dump_threads_usage(
    383376  Thread_Control *the_thread
     
    390383  uint32_t        u32_name;
    391384  char            name_str[5];
    392   char            *name;
    393   Objects_Information *info;
     385  char           *name;
    394386
    395387  if ( !the_thread )
     
    400392   */
    401393
    402   if (the_thread == (Thread_Control *) -1)
    403   {
    404       if (stack_check_interrupt_stack.area)
    405       {
    406           stack = &stack_check_interrupt_stack;
    407           the_thread = 0;
    408       }
    409       else
    410           return;
    411   }
    412   else
    413       stack = &the_thread->Start.Initial_stack;
     394  if (the_thread == (Thread_Control *) -1) {
     395    if (Stack_check_Interrupt_stack.area) {
     396      stack = &Stack_check_Interrupt_stack;
     397      the_thread = 0;
     398    }
     399    else
     400      return;
     401  } else
     402    stack = &the_thread->Start.Initial_stack;
    414403
    415404  low  = Stack_check_usable_stack_start(stack);
     
    425414  name = name_str;
    426415  if ( the_thread ) {
    427     info = _Objects_Get_information(the_thread->Object.id);
    428     if ( info->is_string ) {
    429       name = (char *) the_thread->Object.name;
    430     } else {
    431       u32_name = (uint32_t) the_thread->Object.name;
    432       name[ 0 ] = (u32_name >> 24) & 0xff;
    433       name[ 1 ] = (u32_name >> 16) & 0xff;
    434       name[ 2 ] = (u32_name >>  8) & 0xff;
    435       name[ 3 ] = (u32_name >>  0) & 0xff;
    436       name[ 4 ] = '\0';
    437     }
     416    name = Stack_check_Get_object_name( &the_thread->Object, &name );
    438417  } else {
    439418    u32_name = rtems_build_name('I', 'N', 'T', 'R');
     
    446425
    447426  printk("0x%08" PRIx32 "  %4s  %p - %p   %8" PRId32 "   %8" PRId32 "\n",
    448           the_thread ? the_thread->Object.id : ~0,
    449           name,
    450           stack->area,
    451           stack->area + stack->size - 1,
    452           size,
    453           used
     427    the_thread ? the_thread->Object.id : ~0,
     428    name,
     429    stack->area,
     430    stack->area + stack->size - 1,
     431    size,
     432    used
    454433  );
    455434}
    456435
    457 /*PAGE
    458  *
     436/*
    459437 *  rtems_stack_checker_fatal_extension
    460438 */
    461 
    462 void rtems_stack_checker_fatal_extension(
     439#ifndef DONT_USE_FATAL_EXTENSION
     440  void rtems_stack_checker_fatal_extension(
    463441    Internal_errors_Source  source,
    464442    boolean                 is_internal,
    465443    uint32_t                status
    466 )
    467 {
    468 #ifndef DONT_USE_FATAL_EXTENSION
     444  )
     445  {
    469446    if (status == 0)
    470         rtems_stack_checker_report_usage();
     447      rtems_stack_checker_report_usage();
     448  }
    471449#endif
    472 }
    473 
    474450
    475451/*PAGE
     
    480456void rtems_stack_checker_report_usage( void )
    481457{
    482   if (stack_check_initialized == 0)
     458  if (Stack_check_Initialized == 0)
    483459      return;
    484460
  • cpukit/libmisc/stackchk/stackchk.h

    re974f9d7 r4da36c1a  
    1 /*  stackchk.h
     1/** @file rtems/stackchk.h
    22 *
    33 *  This include file contains information necessary to utilize
    44 *  and install the stack checker mechanism.
    5  *
    6  *  COPYRIGHT (c) 1989-2006.
     5 */
     6
     7/*
     8 *  COPYRIGHT (c) 1989-2007.
    79 *  On-Line Applications Research Corporation (OAR).
    810 *
     
    2123#endif
    2224
    23 /*
    24  *  rtems_stack_checker_initialize
     25/** @brief Has Current Task Blown Its Stack
     26 *
     27 *  This method is used to determine if the current stack pointer
     28 *  of the currently executing task is within bounds.
     29 *
     30 *  @return This method returns true if the currently executing task
     31 *  has blown its stack.
     32 *
    2533 */
     34boolean rtems_stack_checker_is_blown( void );
    2635
    27 void rtems_stack_checker_initialize( void );
    28 
    29 /*
    30  *  rtems_stack_checker_Dump_usage
     36/** @brief Print Stack Usage Report
     37 *
     38 *  This method prints a stack usage report for the curently executing
     39 *  task.
     40 *
     41 *  @note It uses printk to print the report.
    3142 */
    32 
    3343void rtems_stack_checker_report_usage( void );
    3444
    35 /*
    36  *  rtems_stack_checker_create_extension
     45/*************************************************************
     46 *************************************************************
     47 **  Prototyped only so the user extension can be installed **
     48 *************************************************************
     49 *************************************************************/
     50
     51/** @brief Stack Checker Task Create Extension
     52 *
     53 * This method is the task create extension for the stack checker.
     54 *
     55 * @param[in] running points to the currently executing task
     56 * @param[in] the_thread points to the newly created task
     57 *
     58 * @note If this this the first task created, the stack checker
     59 *       will automatically intialize itself.
    3760 */
    38 
    3961boolean rtems_stack_checker_create_extension(
    4062  Thread_Control *running,
     
    4264);
    4365
    44 /*
    45  *  rtems_stack_checker_begin_extension
     66/** @brief Stack Checker Task Begin Extension
     67 *
     68 * This method is the task begin extension for the stack checker.
     69 *
     70 * @param[in] the_thread points to task starting to execute
     71 *
     72 * @note This is called from the internal method _Thread_Handler.
    4673 */
    47 
    4874void rtems_stack_checker_begin_extension(
    4975  Thread_Control *the_thread
    5076);
    5177
    52 /*
    53  *  rtems_stack_checker_switch_extension
     78/** @brief Stack Checker Task Context Switch Extension
     79 *
     80 * This method is the task context switch extension for the stack checker.
     81 *
     82 * @param[in] running points to the currently executing task which
     83 *            is being context switched out
     84 * @param[in] running points to the heir task which we are switching to
     85 *
     86 * @note This is called from the internal method _Thread_Dispatch.
    5487 */
    55 
    5688void rtems_stack_checker_switch_extension(
    5789  Thread_Control *running,
     
    5991);
    6092
    61 /*
    62  *  Extension set definition
     93/** @brief Stack Checker Extension Set Definition
     94 *
     95 *  This macro defines the user extension handler set for the stack
     96 *  checker.  This macro is normally only used by confdefs.h.
    6397 */
    64 
    6598#define RTEMS_STACK_CHECKER_EXTENSION \
    6699{ \
Note: See TracChangeset for help on using the changeset viewer.