new files.

This commit is contained in:
Joel Sherrill
1997-04-09 20:18:54 +00:00
parent 9d5152f121
commit fc7bc517db
21 changed files with 1649 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH=@srcdir@
LIB=${ARCH}/libcpuuse-tmp.a
# C source names, if any, go here -- minus the .c
C_PIECES=cpuuse
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=
INSTALLED_H_FILES=$(srcdir)/cpuuse.h
SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/lib.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS += -I.
CFLAGS +=
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
${LIB}: ${SRCS} ${OBJS}
$(make-library)
all: ${ARCH} $(SRCS) $(LIB)
$(INSTALL) -m 444 ${INSTALLED_H_FILES} ${PROJECT_RELEASE}/include
# $(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems

View File

@@ -0,0 +1,41 @@
#
# README,v 1.3 1995/12/19 20:13:47 joel Exp
#
This directory contains a stack bounds checker. It provides two
primary features:
+ check for stack overflow at each context switch
+ provides an educated guess at each task's stack usage
The stack overflow check at context switch works by looking for
a 16 byte pattern at the logical end of the stack to be corrupted.
The "guesser" assumes that the entire stack was prefilled with a known
pattern and assumes that the pattern is still in place if the memory
has not been used as a stack.
Both of these can be fooled by pushing large holes onto the stack
and not writing to them... or (much more unlikely) writing the
magic patterns into memory.
This code has not been extensively tested. It is provided as a tool
for RTEMS users to catch the most common mistake in multitasking
systems ... too little stack space. Suggestions and comments are appreciated.
NOTES:
1. Stack usage information is questionable on CPUs which push
large holes on stack.
2. The stack checker has a tendency to generate a fault when
trying to print the helpful diagnostic message. If it comes
out, congratulations. If not, then the variable Stack_check_Blown_task
contains a pointer to the TCB of the offending task. This
is usually enough to go on.
FUTURE:
1. Determine how/if gcc will generate stack probe calls and support that.
2. Get accurate stack usage numbers on i960.. it pushes very large
holes on the stack.

View File

@@ -0,0 +1,142 @@
/*
* CPU Usage Reporter
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* check.c,v 1.13 1996/04/22 16:51:52 joel Exp
*
*/
#include <rtems.h>
extern rtems_configuration_table BSP_Configuration;
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cpuuse.h"
unsigned32 CPU_usage_Ticks_at_last_reset;
/*PAGE
*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
unsigned32 u32_name;
char name[5];
unsigned32 total_units = 0;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( the_thread )
total_units += the_thread->ticks_executed;
}
}
}
printf("CPU Usage by thread\n");
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( " ID NAME TICKS PERCENT\n" );
#else
printf( " ID NAME TICKS\n" );
#endif
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
u32_name = *(unsigned32 *)the_thread->Object.name;
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( "0x%08x %4s %8d %5.3f\n",
the_thread->Object.id,
name,
the_thread->ticks_executed,
(total_units) ?
(double)the_thread->ticks_executed / (double)total_units :
(double)total_units
);
#else
printf( "0x%08x %4s %8d\n",
the_thread->Object.id,
name,
the_thread->ticks_executed
);
#endif
}
}
}
printf(
"\nTicks since last reset = %d\n",
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
);
printf( "\nTotal Units = %d\n", total_units );
}
/*PAGE
*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
the_thread->ticks_executed = 0;
}
}
}
}

View File

@@ -0,0 +1,41 @@
/* cpuuse.h
*
* This include file contains information necessary to utilize
* and install the cpu usage reporting mechanism.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* stackchk.h,v 1.3 1995/12/19 20:13:52 joel Exp
*/
#ifndef __CPU_USE_h
#define __CPU_USE_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void );
/*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,96 @@
/* internal.h
*
* This include file contains internal information
* for the RTEMS stack checker.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* internal.h,v 1.5 1995/12/19 20:13:50 joel Exp
*/
#ifndef __INTERNAL_STACK_CHECK_h
#define __INTERNAL_STACK_CHECK_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* This structure is used to fill in and compare the "end of stack"
* marker pattern.
* pattern area must be a multiple of 4 words.
*/
#ifdef CPU_STACK_CHECK_SIZE
#define PATTERN_SIZE_WORDS (((CPU_STACK_CHECK_SIZE / 4) + 3) & ~0x3)
#else
#define PATTERN_SIZE_WORDS 4
#endif
#define PATTERN_SIZE_BYTES (PATTERN_SIZE_WORDS * 4)
typedef struct {
unsigned32 pattern[ PATTERN_SIZE_WORDS ];
} Stack_check_Control;
/*
* The pattern used to fill the entire stack.
*/
#define BYTE_PATTERN 0xA5
#define U32_PATTERN 0xA5A5A5A5
/*
* Stack_check_Create_extension
*/
boolean Stack_check_Create_extension(
Thread_Control *running,
Thread_Control *the_thread
);
/*
* Stack_check_Begin_extension
*/
void Stack_check_Begin_extension(
Thread_Control *the_thread
);
/*
* Stack_check_Switch_extension
*/
void Stack_check_Switch_extension(
Thread_Control *running,
Thread_Control *heir
);
/*
* Stack_check_Fatal_extension
*/
void Stack_check_Fatal_extension(
Internal_errors_Source source,
boolean is_internal,
unsigned32 status
);
/*
* Stack_check_Dump_usage
*/
void Stack_check_Dump_usage( void );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,53 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH=@srcdir@
LIB=${ARCH}/librtmonuse-tmp.a
# C source names, if any, go here -- minus the .c
C_PIECES=rtmonuse
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=
INSTALLED_H_FILES=$(srcdir)/rtmonuse.h
SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/lib.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS += -I.
CFLAGS +=
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
${LIB}: ${SRCS} ${OBJS}
$(make-library)
all: ${ARCH} $(SRCS) $(LIB)
$(INSTALL) -m 444 ${INSTALLED_H_FILES} ${PROJECT_RELEASE}/include
# $(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems

View File

@@ -0,0 +1,173 @@
/*
* $Id$
*/
#include <rtems.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "rtmonuse.h"
typedef struct {
rtems_id id;
unsigned32 count;
unsigned32 missed_count;
unsigned32 min_cpu_time;
unsigned32 max_cpu_time;
unsigned32 total_cpu_time;
unsigned32 min_wall_time;
unsigned32 max_wall_time;
unsigned32 total_wall_time;
} Period_usage_t;
Period_usage_t *Period_usage_Information;
/*PAGE
*
* Period_usage_Initialize
*/
void Period_usage_Initialize( void )
{
int maximum;
maximum = _Configuration_Table->RTEMS_api_configuration->maximum_periods;
Period_usage_Information = malloc( sizeof(Period_usage_t) * (maximum+1) );
Period_usage_Reset();
}
/*PAGE
*
* Period_usage_Reset
*/
void Period_usage_Reset( void )
{
unsigned32 i;
Period_usage_t *the_usage;
for ( i=0 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
the_usage->count = 0;
the_usage->missed_count = 0;
the_usage->min_cpu_time = 0xFFFFFFFF;
the_usage->max_cpu_time = 0;
the_usage->total_cpu_time = 0;
the_usage->min_wall_time = 0xFFFFFFFF;
the_usage->max_wall_time = 0;
the_usage->total_wall_time = 0;
}
}
/*PAGE
*
* Period_usage_Update
*/
void Period_usage_Update(
rtems_id id
)
{
rtems_rate_monotonic_period_status rm_status;
rtems_status_code status;
Period_usage_t *the_usage;
assert( Period_usage_Information );
status = rtems_rate_monotonic_get_status( id, &rm_status );
assert( status == RTEMS_SUCCESSFUL );
the_usage = &Period_usage_Information[ rtems_get_index( id ) ];
the_usage->id = id;
the_usage->count++;
if ( rm_status.state == RATE_MONOTONIC_EXPIRED )
the_usage->missed_count++;
the_usage->total_cpu_time += rm_status.ticks_executed_since_last_period;
the_usage->total_wall_time += rm_status.ticks_since_last_period;
/*
* Update CPU time
*/
if ( rm_status.ticks_executed_since_last_period < the_usage->min_cpu_time )
the_usage->min_cpu_time = rm_status.ticks_executed_since_last_period;
if ( rm_status.ticks_executed_since_last_period > the_usage->max_cpu_time )
the_usage->max_cpu_time = rm_status.ticks_executed_since_last_period;
/*
* Update Wall time
*/
if ( rm_status.ticks_since_last_period < the_usage->min_wall_time )
the_usage->min_wall_time = rm_status.ticks_since_last_period;
if ( rm_status.ticks_since_last_period > the_usage->max_wall_time )
the_usage->max_wall_time = rm_status.ticks_since_last_period;
}
/*PAGE
*
* Period_usage_Dump
*/
void Period_usage_Dump( void )
{
unsigned32 i;
Period_usage_t *the_usage;
Rate_monotonic_Control *the_period;
unsigned32 u32_name;
char name[5];
printf( "Period information by period\n" );
printf( " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" );
/*
* RTEMS does not use an index of zero for object ids.
*/
for ( i=1 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
if ( the_usage->count == 0 )
continue;
the_period =
(Rate_monotonic_Control *)_Rate_monotonic_Information.local_table[ i ];
if ( the_period->owner )
u32_name = *(unsigned32 *)the_period->owner->Object.name;
else
u32_name = rtems_build_name(' ', ' ', ' ', ' ');
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
printf(
"0x%08x %4s %6d %3d %d/%d/%5.2f %d/%d/%3.2f\n",
the_usage->id,
name,
the_usage->count,
the_usage->missed_count,
the_usage->min_cpu_time,
the_usage->max_cpu_time,
(double) the_usage->total_cpu_time / (double) the_usage->count,
the_usage->min_wall_time,
the_usage->max_wall_time,
(double) the_usage->total_wall_time / (double) the_usage->count
);
}
}

View File

@@ -0,0 +1,18 @@
/*
* $Id$
*/
#ifndef __RATE_MONOTONIC_USAGE_h
#define __RATE_MONOTONIC_USAGE_h
void Period_usage_Initialize( void );
void Period_usage_Reset( void );
void Period_usage_Update(
rtems_id id
);
void Period_usage_Dump( void );
#endif

View File

@@ -0,0 +1,53 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH=@srcdir@
LIB=${ARCH}/libcpuuse-tmp.a
# C source names, if any, go here -- minus the .c
C_PIECES=cpuuse
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=
INSTALLED_H_FILES=$(srcdir)/cpuuse.h
SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/lib.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS += -I.
CFLAGS +=
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
${LIB}: ${SRCS} ${OBJS}
$(make-library)
all: ${ARCH} $(SRCS) $(LIB)
$(INSTALL) -m 444 ${INSTALLED_H_FILES} ${PROJECT_RELEASE}/include
# $(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems

View File

@@ -0,0 +1,41 @@
#
# README,v 1.3 1995/12/19 20:13:47 joel Exp
#
This directory contains a stack bounds checker. It provides two
primary features:
+ check for stack overflow at each context switch
+ provides an educated guess at each task's stack usage
The stack overflow check at context switch works by looking for
a 16 byte pattern at the logical end of the stack to be corrupted.
The "guesser" assumes that the entire stack was prefilled with a known
pattern and assumes that the pattern is still in place if the memory
has not been used as a stack.
Both of these can be fooled by pushing large holes onto the stack
and not writing to them... or (much more unlikely) writing the
magic patterns into memory.
This code has not been extensively tested. It is provided as a tool
for RTEMS users to catch the most common mistake in multitasking
systems ... too little stack space. Suggestions and comments are appreciated.
NOTES:
1. Stack usage information is questionable on CPUs which push
large holes on stack.
2. The stack checker has a tendency to generate a fault when
trying to print the helpful diagnostic message. If it comes
out, congratulations. If not, then the variable Stack_check_Blown_task
contains a pointer to the TCB of the offending task. This
is usually enough to go on.
FUTURE:
1. Determine how/if gcc will generate stack probe calls and support that.
2. Get accurate stack usage numbers on i960.. it pushes very large
holes on the stack.

View File

@@ -0,0 +1,142 @@
/*
* CPU Usage Reporter
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* check.c,v 1.13 1996/04/22 16:51:52 joel Exp
*
*/
#include <rtems.h>
extern rtems_configuration_table BSP_Configuration;
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cpuuse.h"
unsigned32 CPU_usage_Ticks_at_last_reset;
/*PAGE
*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
unsigned32 u32_name;
char name[5];
unsigned32 total_units = 0;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( the_thread )
total_units += the_thread->ticks_executed;
}
}
}
printf("CPU Usage by thread\n");
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( " ID NAME TICKS PERCENT\n" );
#else
printf( " ID NAME TICKS\n" );
#endif
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
u32_name = *(unsigned32 *)the_thread->Object.name;
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( "0x%08x %4s %8d %5.3f\n",
the_thread->Object.id,
name,
the_thread->ticks_executed,
(total_units) ?
(double)the_thread->ticks_executed / (double)total_units :
(double)total_units
);
#else
printf( "0x%08x %4s %8d\n",
the_thread->Object.id,
name,
the_thread->ticks_executed
);
#endif
}
}
}
printf(
"\nTicks since last reset = %d\n",
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
);
printf( "\nTotal Units = %d\n", total_units );
}
/*PAGE
*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
the_thread->ticks_executed = 0;
}
}
}
}

View File

@@ -0,0 +1,41 @@
/* cpuuse.h
*
* This include file contains information necessary to utilize
* and install the cpu usage reporting mechanism.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* stackchk.h,v 1.3 1995/12/19 20:13:52 joel Exp
*/
#ifndef __CPU_USE_h
#define __CPU_USE_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void );
/*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,96 @@
/* internal.h
*
* This include file contains internal information
* for the RTEMS stack checker.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* internal.h,v 1.5 1995/12/19 20:13:50 joel Exp
*/
#ifndef __INTERNAL_STACK_CHECK_h
#define __INTERNAL_STACK_CHECK_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* This structure is used to fill in and compare the "end of stack"
* marker pattern.
* pattern area must be a multiple of 4 words.
*/
#ifdef CPU_STACK_CHECK_SIZE
#define PATTERN_SIZE_WORDS (((CPU_STACK_CHECK_SIZE / 4) + 3) & ~0x3)
#else
#define PATTERN_SIZE_WORDS 4
#endif
#define PATTERN_SIZE_BYTES (PATTERN_SIZE_WORDS * 4)
typedef struct {
unsigned32 pattern[ PATTERN_SIZE_WORDS ];
} Stack_check_Control;
/*
* The pattern used to fill the entire stack.
*/
#define BYTE_PATTERN 0xA5
#define U32_PATTERN 0xA5A5A5A5
/*
* Stack_check_Create_extension
*/
boolean Stack_check_Create_extension(
Thread_Control *running,
Thread_Control *the_thread
);
/*
* Stack_check_Begin_extension
*/
void Stack_check_Begin_extension(
Thread_Control *the_thread
);
/*
* Stack_check_Switch_extension
*/
void Stack_check_Switch_extension(
Thread_Control *running,
Thread_Control *heir
);
/*
* Stack_check_Fatal_extension
*/
void Stack_check_Fatal_extension(
Internal_errors_Source source,
boolean is_internal,
unsigned32 status
);
/*
* Stack_check_Dump_usage
*/
void Stack_check_Dump_usage( void );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,53 @@
#
# $Id$
#
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH=@srcdir@
LIB=${ARCH}/librtmonuse-tmp.a
# C source names, if any, go here -- minus the .c
C_PIECES=rtmonuse
C_FILES=$(C_PIECES:%=%.c)
C_O_FILES=$(C_PIECES:%=${ARCH}/%.o)
H_FILES=
INSTALLED_H_FILES=$(srcdir)/rtmonuse.h
SRCS=$(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
OBJS=$(C_O_FILES)
include $(RTEMS_CUSTOM)
include $(PROJECT_ROOT)/make/lib.cfg
#
# (OPTIONAL) Add local stuff here using +=
#
DEFINES +=
CPPFLAGS += -I.
CFLAGS +=
LD_PATHS +=
LD_LIBS +=
LDFLAGS +=
#
# Add your list of files to delete here. The config files
# already know how to delete some stuff, so you may want
# to just run 'make clean' first to see what gets missed.
# 'make clobber' already includes 'make clean'
#
CLEAN_ADDITIONS +=
CLOBBER_ADDITIONS +=
${LIB}: ${SRCS} ${OBJS}
$(make-library)
all: ${ARCH} $(SRCS) $(LIB)
$(INSTALL) -m 444 ${INSTALLED_H_FILES} ${PROJECT_RELEASE}/include
# $(INSTALL) -m 444 ${H_FILES} ${PROJECT_RELEASE}/include/rtems

View File

@@ -0,0 +1,173 @@
/*
* $Id$
*/
#include <rtems.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "rtmonuse.h"
typedef struct {
rtems_id id;
unsigned32 count;
unsigned32 missed_count;
unsigned32 min_cpu_time;
unsigned32 max_cpu_time;
unsigned32 total_cpu_time;
unsigned32 min_wall_time;
unsigned32 max_wall_time;
unsigned32 total_wall_time;
} Period_usage_t;
Period_usage_t *Period_usage_Information;
/*PAGE
*
* Period_usage_Initialize
*/
void Period_usage_Initialize( void )
{
int maximum;
maximum = _Configuration_Table->RTEMS_api_configuration->maximum_periods;
Period_usage_Information = malloc( sizeof(Period_usage_t) * (maximum+1) );
Period_usage_Reset();
}
/*PAGE
*
* Period_usage_Reset
*/
void Period_usage_Reset( void )
{
unsigned32 i;
Period_usage_t *the_usage;
for ( i=0 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
the_usage->count = 0;
the_usage->missed_count = 0;
the_usage->min_cpu_time = 0xFFFFFFFF;
the_usage->max_cpu_time = 0;
the_usage->total_cpu_time = 0;
the_usage->min_wall_time = 0xFFFFFFFF;
the_usage->max_wall_time = 0;
the_usage->total_wall_time = 0;
}
}
/*PAGE
*
* Period_usage_Update
*/
void Period_usage_Update(
rtems_id id
)
{
rtems_rate_monotonic_period_status rm_status;
rtems_status_code status;
Period_usage_t *the_usage;
assert( Period_usage_Information );
status = rtems_rate_monotonic_get_status( id, &rm_status );
assert( status == RTEMS_SUCCESSFUL );
the_usage = &Period_usage_Information[ rtems_get_index( id ) ];
the_usage->id = id;
the_usage->count++;
if ( rm_status.state == RATE_MONOTONIC_EXPIRED )
the_usage->missed_count++;
the_usage->total_cpu_time += rm_status.ticks_executed_since_last_period;
the_usage->total_wall_time += rm_status.ticks_since_last_period;
/*
* Update CPU time
*/
if ( rm_status.ticks_executed_since_last_period < the_usage->min_cpu_time )
the_usage->min_cpu_time = rm_status.ticks_executed_since_last_period;
if ( rm_status.ticks_executed_since_last_period > the_usage->max_cpu_time )
the_usage->max_cpu_time = rm_status.ticks_executed_since_last_period;
/*
* Update Wall time
*/
if ( rm_status.ticks_since_last_period < the_usage->min_wall_time )
the_usage->min_wall_time = rm_status.ticks_since_last_period;
if ( rm_status.ticks_since_last_period > the_usage->max_wall_time )
the_usage->max_wall_time = rm_status.ticks_since_last_period;
}
/*PAGE
*
* Period_usage_Dump
*/
void Period_usage_Dump( void )
{
unsigned32 i;
Period_usage_t *the_usage;
Rate_monotonic_Control *the_period;
unsigned32 u32_name;
char name[5];
printf( "Period information by period\n" );
printf( " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" );
/*
* RTEMS does not use an index of zero for object ids.
*/
for ( i=1 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
if ( the_usage->count == 0 )
continue;
the_period =
(Rate_monotonic_Control *)_Rate_monotonic_Information.local_table[ i ];
if ( the_period->owner )
u32_name = *(unsigned32 *)the_period->owner->Object.name;
else
u32_name = rtems_build_name(' ', ' ', ' ', ' ');
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
printf(
"0x%08x %4s %6d %3d %d/%d/%5.2f %d/%d/%3.2f\n",
the_usage->id,
name,
the_usage->count,
the_usage->missed_count,
the_usage->min_cpu_time,
the_usage->max_cpu_time,
(double) the_usage->total_cpu_time / (double) the_usage->count,
the_usage->min_wall_time,
the_usage->max_wall_time,
(double) the_usage->total_wall_time / (double) the_usage->count
);
}
}

View File

@@ -0,0 +1,18 @@
/*
* $Id$
*/
#ifndef __RATE_MONOTONIC_USAGE_h
#define __RATE_MONOTONIC_USAGE_h
void Period_usage_Initialize( void );
void Period_usage_Reset( void );
void Period_usage_Update(
rtems_id id
);
void Period_usage_Dump( void );
#endif

View File

@@ -0,0 +1,41 @@
#
# README,v 1.3 1995/12/19 20:13:47 joel Exp
#
This directory contains a stack bounds checker. It provides two
primary features:
+ check for stack overflow at each context switch
+ provides an educated guess at each task's stack usage
The stack overflow check at context switch works by looking for
a 16 byte pattern at the logical end of the stack to be corrupted.
The "guesser" assumes that the entire stack was prefilled with a known
pattern and assumes that the pattern is still in place if the memory
has not been used as a stack.
Both of these can be fooled by pushing large holes onto the stack
and not writing to them... or (much more unlikely) writing the
magic patterns into memory.
This code has not been extensively tested. It is provided as a tool
for RTEMS users to catch the most common mistake in multitasking
systems ... too little stack space. Suggestions and comments are appreciated.
NOTES:
1. Stack usage information is questionable on CPUs which push
large holes on stack.
2. The stack checker has a tendency to generate a fault when
trying to print the helpful diagnostic message. If it comes
out, congratulations. If not, then the variable Stack_check_Blown_task
contains a pointer to the TCB of the offending task. This
is usually enough to go on.
FUTURE:
1. Determine how/if gcc will generate stack probe calls and support that.
2. Get accurate stack usage numbers on i960.. it pushes very large
holes on the stack.

View File

@@ -0,0 +1,142 @@
/*
* CPU Usage Reporter
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* check.c,v 1.13 1996/04/22 16:51:52 joel Exp
*
*/
#include <rtems.h>
extern rtems_configuration_table BSP_Configuration;
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "cpuuse.h"
unsigned32 CPU_usage_Ticks_at_last_reset;
/*PAGE
*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
unsigned32 u32_name;
char name[5];
unsigned32 total_units = 0;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( the_thread )
total_units += the_thread->ticks_executed;
}
}
}
printf("CPU Usage by thread\n");
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( " ID NAME TICKS PERCENT\n" );
#else
printf( " ID NAME TICKS\n" );
#endif
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
u32_name = *(unsigned32 *)the_thread->Object.name;
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
#if defined(unix) || ( CPU_HARDWARE_FP == TRUE )
printf( "0x%08x %4s %8d %5.3f\n",
the_thread->Object.id,
name,
the_thread->ticks_executed,
(total_units) ?
(double)the_thread->ticks_executed / (double)total_units :
(double)total_units
);
#else
printf( "0x%08x %4s %8d\n",
the_thread->Object.id,
name,
the_thread->ticks_executed
);
#endif
}
}
}
printf(
"\nTicks since last reset = %d\n",
_Watchdog_Ticks_since_boot - CPU_usage_Ticks_at_last_reset
);
printf( "\nTotal Units = %d\n", total_units );
}
/*PAGE
*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void )
{
unsigned32 i;
unsigned32 class_index;
Thread_Control *the_thread;
Objects_Information *information;
CPU_usage_Ticks_at_last_reset = _Watchdog_Ticks_since_boot;
for ( class_index = OBJECTS_CLASSES_FIRST ;
class_index <= OBJECTS_CLASSES_LAST ;
class_index++ ) {
information = _Objects_Information_table[ class_index ];
if ( information && information->is_thread ) {
for ( i=1 ; i <= information->maximum ; i++ ) {
the_thread = (Thread_Control *)information->local_table[ i ];
if ( !the_thread )
continue;
the_thread->ticks_executed = 0;
}
}
}
}

View File

@@ -0,0 +1,41 @@
/* cpuuse.h
*
* This include file contains information necessary to utilize
* and install the cpu usage reporting mechanism.
*
* COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994, 1996.
* On-Line Applications Research Corporation (OAR).
* 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.
*
* stackchk.h,v 1.3 1995/12/19 20:13:52 joel Exp
*/
#ifndef __CPU_USE_h
#define __CPU_USE_h
#ifdef __cplusplus
extern "C" {
#endif
/*
* CPU_usage_Dump
*/
void CPU_usage_Dump( void );
/*
* CPU_usage_Reset
*/
void CPU_usage_Reset( void );
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,173 @@
/*
* $Id$
*/
#include <rtems.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "rtmonuse.h"
typedef struct {
rtems_id id;
unsigned32 count;
unsigned32 missed_count;
unsigned32 min_cpu_time;
unsigned32 max_cpu_time;
unsigned32 total_cpu_time;
unsigned32 min_wall_time;
unsigned32 max_wall_time;
unsigned32 total_wall_time;
} Period_usage_t;
Period_usage_t *Period_usage_Information;
/*PAGE
*
* Period_usage_Initialize
*/
void Period_usage_Initialize( void )
{
int maximum;
maximum = _Configuration_Table->RTEMS_api_configuration->maximum_periods;
Period_usage_Information = malloc( sizeof(Period_usage_t) * (maximum+1) );
Period_usage_Reset();
}
/*PAGE
*
* Period_usage_Reset
*/
void Period_usage_Reset( void )
{
unsigned32 i;
Period_usage_t *the_usage;
for ( i=0 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
the_usage->count = 0;
the_usage->missed_count = 0;
the_usage->min_cpu_time = 0xFFFFFFFF;
the_usage->max_cpu_time = 0;
the_usage->total_cpu_time = 0;
the_usage->min_wall_time = 0xFFFFFFFF;
the_usage->max_wall_time = 0;
the_usage->total_wall_time = 0;
}
}
/*PAGE
*
* Period_usage_Update
*/
void Period_usage_Update(
rtems_id id
)
{
rtems_rate_monotonic_period_status rm_status;
rtems_status_code status;
Period_usage_t *the_usage;
assert( Period_usage_Information );
status = rtems_rate_monotonic_get_status( id, &rm_status );
assert( status == RTEMS_SUCCESSFUL );
the_usage = &Period_usage_Information[ rtems_get_index( id ) ];
the_usage->id = id;
the_usage->count++;
if ( rm_status.state == RATE_MONOTONIC_EXPIRED )
the_usage->missed_count++;
the_usage->total_cpu_time += rm_status.ticks_executed_since_last_period;
the_usage->total_wall_time += rm_status.ticks_since_last_period;
/*
* Update CPU time
*/
if ( rm_status.ticks_executed_since_last_period < the_usage->min_cpu_time )
the_usage->min_cpu_time = rm_status.ticks_executed_since_last_period;
if ( rm_status.ticks_executed_since_last_period > the_usage->max_cpu_time )
the_usage->max_cpu_time = rm_status.ticks_executed_since_last_period;
/*
* Update Wall time
*/
if ( rm_status.ticks_since_last_period < the_usage->min_wall_time )
the_usage->min_wall_time = rm_status.ticks_since_last_period;
if ( rm_status.ticks_since_last_period > the_usage->max_wall_time )
the_usage->max_wall_time = rm_status.ticks_since_last_period;
}
/*PAGE
*
* Period_usage_Dump
*/
void Period_usage_Dump( void )
{
unsigned32 i;
Period_usage_t *the_usage;
Rate_monotonic_Control *the_period;
unsigned32 u32_name;
char name[5];
printf( "Period information by period\n" );
printf( " ID OWNER PERIODS MISSED CPU TIME WALL TIME\n" );
/*
* RTEMS does not use an index of zero for object ids.
*/
for ( i=1 ;
i<_Configuration_Table->RTEMS_api_configuration->maximum_periods ;
i++ ) {
the_usage = &Period_usage_Information[ i ];
if ( the_usage->count == 0 )
continue;
the_period =
(Rate_monotonic_Control *)_Rate_monotonic_Information.local_table[ i ];
if ( the_period->owner )
u32_name = *(unsigned32 *)the_period->owner->Object.name;
else
u32_name = rtems_build_name(' ', ' ', ' ', ' ');
name[ 0 ] = (u32_name >> 24) & 0xff;
name[ 1 ] = (u32_name >> 16) & 0xff;
name[ 2 ] = (u32_name >> 8) & 0xff;
name[ 3 ] = (u32_name >> 0) & 0xff;
name[ 4 ] = '\0';
printf(
"0x%08x %4s %6d %3d %d/%d/%5.2f %d/%d/%3.2f\n",
the_usage->id,
name,
the_usage->count,
the_usage->missed_count,
the_usage->min_cpu_time,
the_usage->max_cpu_time,
(double) the_usage->total_cpu_time / (double) the_usage->count,
the_usage->min_wall_time,
the_usage->max_wall_time,
(double) the_usage->total_wall_time / (double) the_usage->count
);
}
}

View File

@@ -0,0 +1,18 @@
/*
* $Id$
*/
#ifndef __RATE_MONOTONIC_USAGE_h
#define __RATE_MONOTONIC_USAGE_h
void Period_usage_Initialize( void );
void Period_usage_Reset( void );
void Period_usage_Update(
rtems_id id
);
void Period_usage_Dump( void );
#endif