forked from Imagelibrary/rtems
cat /tmp/j | while read f
do rpm -qi $f 2>&1 | grep -v "is not ins" done
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
ACLOCAL_AMFLAGS = -I $(RTEMS_TOPdir)/aclocal
|
||||
|
||||
SUBDIRS = dumpbuf stackchk monitor cpuuse rtmonuse untar wrapup
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
||||
include $(top_srcdir)/../../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../../automake/local.am
|
||||
@@ -1,23 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
This directory contains for the "miscellaneous" library. Currently
|
||||
this library contains a number of useful support libraries:
|
||||
|
||||
+ Task Stack Overflow Checker
|
||||
+ Workspace Consistency Checker
|
||||
+ Task Execution Time Monitor
|
||||
+ Period Statistics Monitor
|
||||
+ Debug Monitor
|
||||
|
||||
The following ideas have been mentioned for items which could go
|
||||
in this library, but this list is not all inclusive:
|
||||
|
||||
+ there are no outstanding suggestions.
|
||||
|
||||
The intent of this library is to provide a home for useful utility routines
|
||||
which are dependent upon RTEMS.
|
||||
|
||||
--joel
|
||||
16 Sept 97
|
||||
@@ -1,44 +0,0 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
dnl $Id$
|
||||
|
||||
AC_PREREQ(2.13)
|
||||
AC_INIT(dumpbuf)
|
||||
RTEMS_TOP(../../../..)
|
||||
AC_CONFIG_AUX_DIR(../../../..)
|
||||
|
||||
RTEMS_CANONICAL_TARGET_CPU
|
||||
|
||||
AM_INIT_AUTOMAKE(rtems-c-src-lib-libmisc,$RTEMS_VERSION,no)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
RTEMS_ENABLE_MULTIPROCESSING
|
||||
RTEMS_ENABLE_NETWORKING
|
||||
RTEMS_ENABLE_LIBCDIR
|
||||
RTEMS_ENABLE_BARE
|
||||
|
||||
RTEMS_ENV_RTEMSBSP
|
||||
|
||||
RTEMS_CHECK_CPU
|
||||
RTEMS_CANONICAL_HOST
|
||||
|
||||
RTEMS_PROJECT_ROOT
|
||||
|
||||
dnl check target cc
|
||||
RTEMS_PROG_CC_FOR_TARGET
|
||||
RTEMS_CANONICALIZE_TOOLS
|
||||
|
||||
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
|
||||
RTEMS_CHECK_MULTIPROCESSING(RTEMS_BSP)
|
||||
|
||||
# Try to explicitly list a Makefile here
|
||||
AC_OUTPUT(
|
||||
Makefile
|
||||
cpuuse/Makefile
|
||||
dumpbuf/Makefile
|
||||
monitor/Makefile
|
||||
rtmonuse/Makefile
|
||||
stackchk/Makefile
|
||||
untar/Makefile
|
||||
wrapup/Makefile
|
||||
)
|
||||
@@ -1,72 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = cpuuse
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
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_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
#
|
||||
# (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} preinstall ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
all: ${ARCH} $(SRCS) preinstall $(LIB)
|
||||
|
||||
preinstall:
|
||||
@$(INSTALL_CHANGE) -m 644 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,41 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
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.
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* CPU Usage Reporter
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998. 1996.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
extern rtems_configuration_table BSP_Configuration;
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/* cpuuse.h
|
||||
*
|
||||
* This include file contains information necessary to utilize
|
||||
* and install the cpu usage reporting mechanism.
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998. 1996.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -1,72 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = dumpbuf
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
LIB = ${ARCH}/libdumpbuf-tmp.a
|
||||
|
||||
# C source names, if any, go here -- minus the .c
|
||||
C_PIECES = dumpbuf
|
||||
C_FILES = $(C_PIECES:%=%.c)
|
||||
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
|
||||
|
||||
H_FILES =
|
||||
INSTALLED_H_FILES = $(srcdir)/dumpbuf.h
|
||||
|
||||
SRCS = $(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
#
|
||||
# (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} preinstall ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
all: ${ARCH} $(SRCS) preinstall $(LIB)
|
||||
|
||||
preinstall:
|
||||
@$(INSTALL_CHANGE) -m 644 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 1997.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may in
|
||||
* the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <rtems/dumpbuf.h>
|
||||
|
||||
/*
|
||||
* Put the body below Dump_Buffer so it won't get inlined.
|
||||
*/
|
||||
|
||||
static inline void Dump_Line(
|
||||
unsigned char *buffer,
|
||||
int length
|
||||
);
|
||||
|
||||
void Dump_Buffer(
|
||||
unsigned char *buffer,
|
||||
int length
|
||||
)
|
||||
{
|
||||
|
||||
int i, mod, max;
|
||||
|
||||
if ( !length ) return;
|
||||
|
||||
mod = length % 16;
|
||||
|
||||
max = length - mod;
|
||||
|
||||
for ( i=0 ; i<max ; i+=16 )
|
||||
Dump_Line( &buffer[ i ], 16 );
|
||||
|
||||
if ( mod )
|
||||
Dump_Line( &buffer[ max ], mod );
|
||||
}
|
||||
|
||||
static inline void Dump_Line(
|
||||
unsigned char *buffer,
|
||||
int length
|
||||
)
|
||||
{
|
||||
|
||||
int i;
|
||||
char line_buffer[120];
|
||||
|
||||
line_buffer[0] = '\0';
|
||||
|
||||
for( i=0 ; i<length ; i++ )
|
||||
sprintf( line_buffer, "%s%02x ", line_buffer, buffer[ i ] );
|
||||
|
||||
for( ; i<16 ; i++ )
|
||||
strcat( line_buffer, " " );
|
||||
|
||||
strcat( line_buffer, "|" );
|
||||
for( i=0 ; i<length ; i++ )
|
||||
sprintf( line_buffer, "%s%c", line_buffer,
|
||||
isprint( buffer[ i ] ) ? buffer[ i ] : '.' );
|
||||
|
||||
for( ; i<16 ; i++ )
|
||||
strcat( line_buffer, " " );
|
||||
|
||||
strcat( line_buffer, "|\n" );
|
||||
|
||||
printf( line_buffer );
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT (c) 1997.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* The license and distribution terms for this file may in
|
||||
* the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __DUMP_BUFFER_h
|
||||
#define __DUMP_BUFFER_h
|
||||
|
||||
void Dump_Buffer(
|
||||
unsigned char *buffer,
|
||||
int length
|
||||
);
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
@@ -1,80 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = monitor
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
LIB = ${ARCH}/libmonitor-tmp.a
|
||||
|
||||
# C source names, if any, go here -- minus the .c
|
||||
# We only build multiprocessing related files if HAS_MP was defined
|
||||
MP_C_PIECES_yes_V = mon-mpci
|
||||
MP_C_PIECES = $(MP_C_PIECES_$(HAS_MP)_V)
|
||||
|
||||
C_PIECES = mon-command mon-symbols mon-prmisc mon-monitor mon-object \
|
||||
mon-server mon-task mon-queue mon-driver mon-dname mon-itask \
|
||||
mon-extension mon-manager mon-config $(MP_C_PIECES)
|
||||
C_FILES = $(C_PIECES:%=%.c)
|
||||
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
|
||||
|
||||
H_FILES =
|
||||
INSTALLED_H_FILES = $(srcdir)/monitor.h $(srcdir)/symbols.h
|
||||
|
||||
SRCS = README $(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
#
|
||||
# (OPTIONAL) Add local stuff here using +=
|
||||
#
|
||||
|
||||
DEFINES +=
|
||||
CPPFLAGS += -I$(srcdir)
|
||||
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'
|
||||
#
|
||||
|
||||
.PHONY: preinstall
|
||||
|
||||
CLEAN_ADDITIONS +=
|
||||
CLOBBER_ADDITIONS +=
|
||||
|
||||
${LIB}: ${SRCS} ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
all: preinstall ${ARCH} $(SRCS) $(LIB)
|
||||
|
||||
preinstall: $(INSTALLED_H_FILES)
|
||||
@$(INSTALL_CHANGE) -m 644 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,97 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
monitor task
|
||||
|
||||
The monitor task is an optional task that knows about RTEMS
|
||||
data structures and can print out information about them.
|
||||
It is a work-in-progress and needs many more commands, but
|
||||
is useful now.
|
||||
|
||||
The monitor works best when it is the highest priority task,
|
||||
so all your other tasks should ideally be at some priority
|
||||
greater than 1.
|
||||
|
||||
To use the monitor:
|
||||
-------------------
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
...
|
||||
|
||||
rtems_monitor_init(0);
|
||||
|
||||
The parameter to rtems_monitor_init() tells the monitor whether
|
||||
to suspend itself on startup. A value of 0 causes the monitor
|
||||
to immediately enter command mode; a non-zero value causes the
|
||||
monitor to suspend itself after creation and wait for explicit
|
||||
wakeup.
|
||||
|
||||
|
||||
rtems_monitor_wakeup();
|
||||
|
||||
wakes up a suspended monitor and causes it to reenter command mode.
|
||||
|
||||
Monitor commands
|
||||
----------------
|
||||
|
||||
The monitor prompt is 'rtems> '.
|
||||
Can abbreviate commands to "uniquity"
|
||||
There is a 'help' command. Here is the output from various
|
||||
help commands:
|
||||
|
||||
Commands (may be abbreviated)
|
||||
|
||||
help -- get this message or command specific help
|
||||
task -- show task information
|
||||
queue -- show message queue information
|
||||
symbol -- show entries from symbol table
|
||||
pause -- pause monitor for a specified number of ticks
|
||||
fatal -- invoke a fatal RTEMS error
|
||||
|
||||
task [id [id ...] ]
|
||||
display information about the specified tasks.
|
||||
Default is to display information about all tasks on this node
|
||||
|
||||
queue [id [id ... ] ]
|
||||
display information about the specified message queues
|
||||
Default is to display information about all queues on this node
|
||||
|
||||
symbol [ symbolname [symbolname ... ] ]
|
||||
display value associated with specified symbol.
|
||||
Defaults to displaying all known symbols.
|
||||
|
||||
pause [ticks]
|
||||
monitor goes to "sleep" for specified ticks (default is 1)
|
||||
monitor will resume at end of period or if explicitly awakened
|
||||
|
||||
fatal [status]
|
||||
Invoke 'rtems_fatal_error_occurred' with 'status'
|
||||
(default is RTEMS_INTERNAL_ERROR)
|
||||
|
||||
continue
|
||||
put the monitor to sleep waiting for an explicit wakeup from the
|
||||
program running.
|
||||
|
||||
|
||||
Sample output from 'task' command
|
||||
---------------------------------
|
||||
|
||||
rtems> task
|
||||
ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES
|
||||
------------------------------------------------------------------------
|
||||
00010001 UI1 2 READY P:T:nA NONE15: 0x40606348
|
||||
00010002 RMON 1 READY nP NONE15: 0x40604110
|
||||
|
||||
'RMON' is the monitor itself, so we have 1 "user" task.
|
||||
Its modes are P:T:nA which translate to:
|
||||
|
||||
preemptable
|
||||
timesliced
|
||||
no ASRS
|
||||
|
||||
It has no events.
|
||||
It has a notepad value for notepad 15 which is 0x40606348
|
||||
(this is the libc thread state)
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
/*
|
||||
* Command parsing routines for RTEMS monitor
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* make_argv(cp): token-count
|
||||
* Break up the command line in 'cp' into global argv[] and argc (return
|
||||
* value).
|
||||
*/
|
||||
|
||||
int
|
||||
rtems_monitor_make_argv(
|
||||
char *cp,
|
||||
int *argc_p,
|
||||
char **argv)
|
||||
{
|
||||
int argc = 0;
|
||||
|
||||
while ((cp = strtok(cp, " \t\n\r")))
|
||||
{
|
||||
argv[argc++] = cp;
|
||||
cp = (char *) NULL;
|
||||
}
|
||||
argv[argc] = (char *) NULL; /* end of argv */
|
||||
|
||||
return *argc_p = argc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read and break up a monitor command
|
||||
*
|
||||
* We have to loop on the gets call, since it will return NULL under UNIX
|
||||
* RTEMS when we get a signal (eg: SIGALRM).
|
||||
*/
|
||||
|
||||
int
|
||||
rtems_monitor_command_read(char *command,
|
||||
int *argc,
|
||||
char **argv)
|
||||
{
|
||||
extern rtems_configuration_table BSP_Configuration;
|
||||
static char monitor_prompt[32];
|
||||
|
||||
/*
|
||||
* put node number in the prompt if we are multiprocessing
|
||||
*/
|
||||
|
||||
if (BSP_Configuration.User_multiprocessing_table == 0)
|
||||
sprintf(monitor_prompt, "%s", MONITOR_PROMPT);
|
||||
else if (rtems_monitor_default_node != rtems_monitor_node)
|
||||
sprintf(monitor_prompt, "%d-%s-%d", rtems_monitor_node, MONITOR_PROMPT, rtems_monitor_default_node);
|
||||
else
|
||||
sprintf(monitor_prompt, "%d-%s", rtems_monitor_node, MONITOR_PROMPT);
|
||||
|
||||
#ifdef RTEMS_UNIX
|
||||
/* RTEMS on unix gets so many interrupt system calls this is hosed */
|
||||
printf("%s> ", monitor_prompt);
|
||||
fflush(stdout);
|
||||
while (gets(command) == (char *) 0)
|
||||
;
|
||||
#else
|
||||
do
|
||||
{
|
||||
printf("%s> ", monitor_prompt);
|
||||
fflush(stdout);
|
||||
} while (gets(command) == (char *) 0);
|
||||
#endif
|
||||
|
||||
return rtems_monitor_make_argv(command, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up a command in a command table
|
||||
*
|
||||
*/
|
||||
|
||||
rtems_monitor_command_entry_t *
|
||||
rtems_monitor_command_lookup(
|
||||
rtems_monitor_command_entry_t *table,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
rtems_monitor_command_entry_t *p;
|
||||
rtems_monitor_command_entry_t *abbreviated_match = 0;
|
||||
int abbreviated_matches = 0;
|
||||
char *command;
|
||||
int command_length;
|
||||
|
||||
command = argv[0];
|
||||
|
||||
if ((table == 0) || (command == 0))
|
||||
goto failed;
|
||||
|
||||
command_length = strlen(command);
|
||||
|
||||
for (p = table; p->command; p++)
|
||||
if (STREQ(command, p->command)) /* exact match */
|
||||
goto done;
|
||||
else if (STRNEQ(command, p->command, command_length))
|
||||
{
|
||||
abbreviated_matches++;
|
||||
abbreviated_match = p;
|
||||
}
|
||||
|
||||
/* no perfect match; is there a non-ambigous abbreviated match? */
|
||||
if ( ! abbreviated_match)
|
||||
{
|
||||
printf("Unrecognized command '%s'; try 'help'\n", command);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (abbreviated_matches > 1)
|
||||
{
|
||||
printf("Command '%s' is ambiguous; try 'help'\n", command);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
p = abbreviated_match;
|
||||
|
||||
done:
|
||||
if (p->command_function == 0)
|
||||
goto failed;
|
||||
return p;
|
||||
|
||||
failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_command_usage(rtems_monitor_command_entry_t *table,
|
||||
char *command_string)
|
||||
{
|
||||
rtems_monitor_command_entry_t *help = 0;
|
||||
char *help_command_argv[2];
|
||||
|
||||
/* if first entry in table is a usage, then print it out */
|
||||
if (command_string == 0)
|
||||
{
|
||||
if (STREQ(table->command, "--usage--") && table->usage)
|
||||
help = table;
|
||||
}
|
||||
else
|
||||
{
|
||||
help_command_argv[0] = command_string;
|
||||
help_command_argv[1] = 0;
|
||||
help = rtems_monitor_command_lookup(table, 1, help_command_argv);
|
||||
}
|
||||
|
||||
if (help)
|
||||
printf("%s\n", help->usage);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_help_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
int arg;
|
||||
rtems_monitor_command_entry_t *command;
|
||||
|
||||
command = (rtems_monitor_command_entry_t *) command_arg;
|
||||
|
||||
if (argc == 1)
|
||||
rtems_monitor_command_usage(command, 0);
|
||||
else
|
||||
{
|
||||
for (arg=1; argv[arg]; arg++)
|
||||
rtems_monitor_command_usage(command, argv[arg]);
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* RTEMS Config display support
|
||||
*
|
||||
* TODO
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
|
||||
#define DATACOL 15
|
||||
#define CONTCOL DATACOL /* continued col */
|
||||
|
||||
/*
|
||||
* Fill in entire monitor config table
|
||||
* for sending to a remote monitor or printing on the local system
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_config_canonical(
|
||||
rtems_monitor_config_t *canonical_config,
|
||||
void *config_void
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = (rtems_configuration_table *) config_void;
|
||||
rtems_api_configuration_table *r = c->RTEMS_api_configuration;
|
||||
|
||||
canonical_config->work_space_start = c->work_space_start;
|
||||
canonical_config->work_space_size = c->work_space_size;
|
||||
canonical_config->maximum_tasks = r->maximum_tasks;
|
||||
canonical_config->maximum_timers = r->maximum_timers;
|
||||
canonical_config->maximum_semaphores = r->maximum_semaphores;
|
||||
canonical_config->maximum_message_queues = r->maximum_message_queues;
|
||||
canonical_config->maximum_partitions = r->maximum_partitions;
|
||||
canonical_config->maximum_regions = r->maximum_regions;
|
||||
canonical_config->maximum_ports = r->maximum_ports;
|
||||
canonical_config->maximum_periods = r->maximum_periods;
|
||||
canonical_config->maximum_extensions = c->maximum_extensions;
|
||||
canonical_config->microseconds_per_tick = c->microseconds_per_tick;
|
||||
canonical_config->ticks_per_timeslice = c->ticks_per_timeslice;
|
||||
canonical_config->number_of_initialization_tasks = r->number_of_initialization_tasks;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is easy, since there is only 1 (altho we could get them from
|
||||
* other nodes...)
|
||||
*/
|
||||
|
||||
void *
|
||||
rtems_monitor_config_next(
|
||||
void *object_info,
|
||||
rtems_monitor_config_t *canonical_config,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = _Configuration_Table;
|
||||
int n = rtems_get_index(*next_id);
|
||||
|
||||
if (n >= 1)
|
||||
goto failed;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
*next_id += 1;
|
||||
return (void *) c;
|
||||
|
||||
failed:
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_config_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
INITIAL (startup) Configuration Info\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_config_dump(
|
||||
rtems_monitor_config_t *monitor_config,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length = 0;
|
||||
length += printf("WORKSPACE");
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
length += printf("start: 0x%x; size: 0x%x\n",
|
||||
(unsigned32) monitor_config->work_space_start,
|
||||
monitor_config->work_space_size);
|
||||
|
||||
length = 0;
|
||||
length += printf("TIME");
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
length += printf("usec/tick: %d; tick/timeslice: %d; tick/sec: %d\n",
|
||||
monitor_config->microseconds_per_tick,
|
||||
monitor_config->ticks_per_timeslice,
|
||||
1000000 / monitor_config->microseconds_per_tick);
|
||||
|
||||
length = 0;
|
||||
length += printf("MAXIMUMS");
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
length += printf("tasks: %d; timers: %d; sems: %d; que's: %d; ext's: %d\n",
|
||||
monitor_config->maximum_tasks,
|
||||
monitor_config->maximum_timers,
|
||||
monitor_config->maximum_semaphores,
|
||||
monitor_config->maximum_message_queues,
|
||||
monitor_config->maximum_extensions);
|
||||
length = 0;
|
||||
length += rtems_monitor_pad(CONTCOL, length);
|
||||
length += printf("partitions: %d; regions: %d; ports: %d; periods: %d\n",
|
||||
monitor_config->maximum_partitions,
|
||||
monitor_config->maximum_regions,
|
||||
monitor_config->maximum_ports,
|
||||
monitor_config->maximum_periods);
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* RTEMS monitor driver names support.
|
||||
*
|
||||
* There are 2 "driver" things the monitor knows about.
|
||||
*
|
||||
* 1. Regular RTEMS drivers.
|
||||
* This is a table indexed by major device number and
|
||||
* containing driver entry points only.
|
||||
*
|
||||
* 2. Driver name table.
|
||||
* A separate table of names for drivers.
|
||||
* The table converts driver names to a major number
|
||||
* as index into the driver table and a minor number
|
||||
* for an argument to driver.
|
||||
*
|
||||
* Drivers are displayed with 'driver' command.
|
||||
* Names are displayed with 'dname' command.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
#include <string.h> /* strncpy() */
|
||||
|
||||
#define DATACOL 15
|
||||
#define CONTCOL DATACOL /* continued col */
|
||||
|
||||
void
|
||||
rtems_monitor_dname_canonical(
|
||||
rtems_monitor_dname_t *canonical_dname,
|
||||
void *dname_void
|
||||
)
|
||||
{
|
||||
rtems_driver_name_t *np = (rtems_driver_name_t *) dname_void;
|
||||
|
||||
(void) strncpy(canonical_dname->name_string, np->device_name, sizeof(canonical_dname->name_string));
|
||||
canonical_dname->major = np->major;
|
||||
canonical_dname->minor = np->minor;
|
||||
}
|
||||
|
||||
void *
|
||||
rtems_monitor_dname_next(
|
||||
void *object_information,
|
||||
rtems_monitor_dname_t *canonical_dname,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_unsigned32 n = rtems_get_index(*next_id);
|
||||
rtems_driver_name_t *table = _IO_Driver_name_table;
|
||||
rtems_driver_name_t *np = 0;
|
||||
|
||||
/* XXX should we be using _IO_Number_of_devices */
|
||||
for (np = table + n ; n<_IO_Number_of_devices; n++, np++)
|
||||
if (np->device_name)
|
||||
goto done;
|
||||
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
|
||||
done:
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
/*
|
||||
* dummy up a fake id and name for this item
|
||||
*/
|
||||
|
||||
canonical_dname->id = n;
|
||||
canonical_dname->name = rtems_build_name('-', '-', '-', '-');
|
||||
|
||||
*next_id += 1;
|
||||
return np;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_dname_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
Major:Minor Name\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_dname_dump(
|
||||
rtems_monitor_dname_t *monitor_dname,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length += rtems_monitor_pad(6, length);
|
||||
length += rtems_monitor_dump_hex(monitor_dname->major);
|
||||
length += printf(":");
|
||||
length += rtems_monitor_dump_hex(monitor_dname->minor);
|
||||
|
||||
length += rtems_monitor_pad(16, length);
|
||||
length += printf("%.*s",
|
||||
(int) sizeof(monitor_dname->name_string),
|
||||
(char *) monitor_dname->name_string);
|
||||
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* RTEMS monitor IO (device drivers) support
|
||||
*
|
||||
* There are 2 "driver" things the monitor knows about.
|
||||
*
|
||||
* 1. Regular RTEMS drivers.
|
||||
* This is a table indexed by major device number and
|
||||
* containing driver entry points only.
|
||||
*
|
||||
* 2. Driver name table.
|
||||
* A separate table of names for drivers.
|
||||
* The table converts driver names to a major number
|
||||
* as index into the driver table and a minor number
|
||||
* for an argument to driver.
|
||||
*
|
||||
* Drivers are displayed with 'driver' command.
|
||||
* Names are displayed with 'name' command.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
|
||||
#define DATACOL 15
|
||||
#define CONTCOL DATACOL /* continued col */
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_driver_canonical(
|
||||
rtems_monitor_driver_t *canonical_driver,
|
||||
void *driver_void
|
||||
)
|
||||
{
|
||||
rtems_driver_address_table *d = (rtems_driver_address_table *) driver_void;
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->initialization,
|
||||
(void *) d->initialization);
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->open,
|
||||
(void *) d->open);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->close,
|
||||
(void *) d->close);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->read,
|
||||
(void *) d->read);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->write,
|
||||
(void *) d->write);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_driver->control,
|
||||
(void *) d->control);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
rtems_monitor_driver_next(
|
||||
void *object_info,
|
||||
rtems_monitor_driver_t *canonical_driver,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = _Configuration_Table;
|
||||
rtems_unsigned32 n = rtems_get_index(*next_id);
|
||||
|
||||
if (n >= c->number_of_device_drivers)
|
||||
goto failed;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
/*
|
||||
* dummy up a fake id and name for this item
|
||||
*/
|
||||
|
||||
canonical_driver->id = n;
|
||||
canonical_driver->name = rtems_build_name('-', '-', '-', '-');
|
||||
|
||||
*next_id += 1;
|
||||
return (void *) (c->Device_driver_table + n);
|
||||
|
||||
failed:
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_driver_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
Major Entry points\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_driver_dump(
|
||||
rtems_monitor_driver_t *monitor_driver,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length += printf(" %d", monitor_driver->id);
|
||||
|
||||
length += rtems_monitor_pad(13, length);
|
||||
length += printf("init: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->initialization, verbose);
|
||||
length += printf("; control: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->control, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
|
||||
length += rtems_monitor_pad(13, length);
|
||||
|
||||
length += printf("open: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->open, verbose);
|
||||
length += printf("; close: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->close, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
|
||||
length += rtems_monitor_pad(13, length);
|
||||
|
||||
length += printf("read: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->read, verbose);
|
||||
length += printf("; write: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_driver->write, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* RTEMS Monitor extension support
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
rtems_monitor_extension_canonical(
|
||||
rtems_monitor_extension_t *canonical_extension,
|
||||
void *extension_void
|
||||
)
|
||||
{
|
||||
Extension_Control *rtems_extension = (Extension_Control *) extension_void;
|
||||
rtems_extensions_table *e = &rtems_extension->Extension.Callouts;
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_create,
|
||||
(void *) e->thread_create);
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_start,
|
||||
(void *) e->thread_start);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_restart,
|
||||
(void *) e->thread_restart);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_delete,
|
||||
(void *) e->thread_delete);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_tswitch,
|
||||
(void *) e->thread_switch);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_begin,
|
||||
(void *) e->thread_begin);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_exitted,
|
||||
(void *) e->thread_exitted);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_extension->e_fatal,
|
||||
(void *) e->fatal);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_extension_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
ID NAME\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dump out the canonical form
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_extension_dump(
|
||||
rtems_monitor_extension_t *monitor_extension,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length += rtems_monitor_dump_id(monitor_extension->id);
|
||||
length += rtems_monitor_pad(11, length);
|
||||
length += rtems_monitor_dump_name(monitor_extension->name);
|
||||
|
||||
length += rtems_monitor_pad(18, length);
|
||||
length += printf("create: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_create, verbose);
|
||||
length += printf("; start: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_start, verbose);
|
||||
length += printf("; restart: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_restart, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
|
||||
length += rtems_monitor_pad(18, length);
|
||||
length += printf("delete: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_delete, verbose);
|
||||
length += printf("; switch: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_tswitch, verbose);
|
||||
length += printf("; begin: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_begin, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
|
||||
length += rtems_monitor_pad(18, length);
|
||||
length += printf("exitted: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_exitted, verbose);
|
||||
length += printf("; fatal: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_extension->e_fatal, verbose);
|
||||
length += printf("\n");
|
||||
length = 0;
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* RTEMS Monitor init task support
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* As above, but just for init tasks
|
||||
*/
|
||||
void
|
||||
rtems_monitor_init_task_canonical(
|
||||
rtems_monitor_init_task_t *canonical_itask,
|
||||
void *itask_void
|
||||
)
|
||||
{
|
||||
rtems_initialization_tasks_table *rtems_itask = itask_void;
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_itask->entry,
|
||||
(void *) rtems_itask->entry_point);
|
||||
|
||||
canonical_itask->argument = rtems_itask->argument;
|
||||
canonical_itask->stack_size = rtems_itask->stack_size;
|
||||
canonical_itask->priority = rtems_itask->initial_priority;
|
||||
canonical_itask->modes = rtems_itask->mode_set;
|
||||
canonical_itask->attributes = rtems_itask->attribute_set;
|
||||
}
|
||||
|
||||
void *
|
||||
rtems_monitor_init_task_next(
|
||||
void *object_info,
|
||||
rtems_monitor_init_task_t *canonical_init_task,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = _Configuration_Table;
|
||||
rtems_initialization_tasks_table *itask;
|
||||
rtems_unsigned32 n = rtems_get_index(*next_id);
|
||||
|
||||
if (n >= c->RTEMS_api_configuration->number_of_initialization_tasks)
|
||||
goto failed;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
itask = c->RTEMS_api_configuration->User_initialization_tasks_table + n;
|
||||
|
||||
/*
|
||||
* dummy up a fake id and name for this item
|
||||
*/
|
||||
|
||||
canonical_init_task->id = n;
|
||||
canonical_init_task->name = itask->name;
|
||||
|
||||
*next_id += 1;
|
||||
return (void *) itask;
|
||||
|
||||
failed:
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_init_task_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
# NAME ENTRY ARGUMENT PRIO MODES ATTRIBUTES STACK SIZE\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_init_task_dump(
|
||||
rtems_monitor_init_task_t *monitor_itask,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
length += rtems_monitor_dump_decimal(monitor_itask->id);
|
||||
|
||||
length += rtems_monitor_pad(7, length);
|
||||
length += rtems_monitor_dump_name(monitor_itask->name);
|
||||
|
||||
length += rtems_monitor_pad(14, length);
|
||||
length += rtems_monitor_symbol_dump(&monitor_itask->entry, verbose);
|
||||
|
||||
length += rtems_monitor_pad(25, length);
|
||||
length += printf("%d [0x%x]", monitor_itask->argument, monitor_itask->argument);
|
||||
|
||||
length += rtems_monitor_pad(39, length);
|
||||
length += rtems_monitor_dump_priority(monitor_itask->priority);
|
||||
|
||||
length += rtems_monitor_pad(46, length);
|
||||
length += rtems_monitor_dump_modes(monitor_itask->modes);
|
||||
|
||||
length += rtems_monitor_pad(54, length);
|
||||
length += rtems_monitor_dump_attributes(monitor_itask->attributes);
|
||||
|
||||
length += rtems_monitor_pad(66, length);
|
||||
length += printf("%d [0x%x]", monitor_itask->stack_size, monitor_itask->stack_size);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* RTEMS Monitor "manager" support.
|
||||
* Used to traverse object (chain) lists and print them out.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* "next" routine for all objects that are RTEMS manager objects
|
||||
*/
|
||||
|
||||
void *
|
||||
rtems_monitor_manager_next(
|
||||
void *table_void,
|
||||
void *canonical,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
Objects_Information *table = table_void;
|
||||
rtems_monitor_generic_t *copy;
|
||||
Objects_Control *object = 0;
|
||||
Objects_Locations location;
|
||||
|
||||
/*
|
||||
* When we are called, it must be local
|
||||
*/
|
||||
|
||||
if ( ! _Objects_Is_local_id(*next_id))
|
||||
goto done;
|
||||
|
||||
object = _Objects_Get_next(table, *next_id, &location, next_id);
|
||||
|
||||
if (object)
|
||||
{
|
||||
copy = (rtems_monitor_generic_t *) canonical;
|
||||
copy->id = object->id;
|
||||
_Objects_Copy_name_raw(object->name, ©->name, sizeof(copy->name));
|
||||
}
|
||||
|
||||
done:
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -1,518 +0,0 @@
|
||||
/*
|
||||
* RTEMS monitor main body
|
||||
*
|
||||
* TODO:
|
||||
* add stuff to RTEMS api
|
||||
* rtems_get_name(id)
|
||||
* rtems_get_type(id)
|
||||
* rtems_build_id(node, type, num)
|
||||
* Add a command to dump out info about an arbitrary id when
|
||||
* types are added to id's
|
||||
* rtems> id idnum
|
||||
* idnum: node n, object: whatever, id: whatever
|
||||
* allow id's to be specified as n:t:id, where 'n:t' is optional
|
||||
* should have a separate monitor FILE stream (ala the debugger)
|
||||
* remote request/response stuff should be cleaned up
|
||||
* maybe we can use real rpc??
|
||||
* 'info' command to print out:
|
||||
* interrupt stack location, direction and size
|
||||
* floating point config stuff
|
||||
* interrupt config stuff
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
/* set by trap handler */
|
||||
extern rtems_tcb *debugger_interrupted_task;
|
||||
extern rtems_context *debugger_interrupted_task_context;
|
||||
extern rtems_unsigned32 debugger_trap;
|
||||
|
||||
/*
|
||||
* Various id's for the monitor
|
||||
* They need to be public variables for access by other agencies
|
||||
* such as debugger and remote servers'
|
||||
*/
|
||||
|
||||
rtems_id rtems_monitor_task_id;
|
||||
|
||||
unsigned32 rtems_monitor_node; /* our node number */
|
||||
unsigned32 rtems_monitor_default_node; /* current default for commands */
|
||||
|
||||
/*
|
||||
* The rtems symbol table
|
||||
*/
|
||||
|
||||
rtems_symbol_table_t *rtems_monitor_symbols;
|
||||
|
||||
/*
|
||||
* The top-level commands
|
||||
*/
|
||||
|
||||
rtems_monitor_command_entry_t rtems_monitor_commands[] = {
|
||||
{ "--usage--",
|
||||
"\n"
|
||||
"RTEMS monitor\n"
|
||||
"\n"
|
||||
"Commands (may be abbreviated)\n"
|
||||
"\n"
|
||||
" help -- get this message or command specific help\n"
|
||||
" pause -- pause monitor for a specified number of ticks\n"
|
||||
" exit -- invoke a fatal RTEMS error\n"
|
||||
" symbol -- show entries from symbol table\n"
|
||||
" continue -- put monitor to sleep waiting for explicit wakeup\n"
|
||||
" config -- show system configuration\n"
|
||||
" itask -- list init tasks\n"
|
||||
" mpci -- list mpci config\n"
|
||||
" task -- show task information\n"
|
||||
" queue -- show message queue information\n"
|
||||
" extension -- user extensions\n"
|
||||
" driver -- show information about named drivers\n"
|
||||
" dname -- show information about named drivers\n"
|
||||
" object -- generic object information\n"
|
||||
" node -- specify default node for commands that take id's\n"
|
||||
#ifdef CPU_INVOKE_DEBUGGER
|
||||
" debugger -- invoke system debugger\n"
|
||||
#endif
|
||||
,
|
||||
0,
|
||||
0,
|
||||
(unsigned32) rtems_monitor_commands,
|
||||
},
|
||||
{ "config",
|
||||
"config\n"
|
||||
" Show the system configuration.\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_CONFIG,
|
||||
},
|
||||
{ "itask",
|
||||
"itask\n"
|
||||
" List init tasks for the system\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_INIT_TASK,
|
||||
},
|
||||
{ "mpci",
|
||||
"mpci\n"
|
||||
" Show the MPCI system configuration, if configured.\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_MPCI,
|
||||
},
|
||||
{ "pause",
|
||||
"pause [ticks]\n"
|
||||
" monitor goes to \"sleep\" for specified ticks (default is 1)\n"
|
||||
" monitor will resume at end of period or if explicitly awakened\n",
|
||||
0,
|
||||
rtems_monitor_pause_cmd,
|
||||
0,
|
||||
},
|
||||
{ "continue",
|
||||
"continue\n"
|
||||
" put the monitor to sleep waiting for an explicit wakeup from the\n"
|
||||
" program running.\n",
|
||||
0,
|
||||
rtems_monitor_continue_cmd,
|
||||
0,
|
||||
},
|
||||
{ "go",
|
||||
"go\n"
|
||||
" Alias for 'continue'\n",
|
||||
0,
|
||||
rtems_monitor_continue_cmd,
|
||||
0,
|
||||
},
|
||||
{ "node",
|
||||
"node [ node number ]\n"
|
||||
" Specify default node number for commands that take id's\n",
|
||||
0,
|
||||
rtems_monitor_node_cmd,
|
||||
0,
|
||||
},
|
||||
{ "symbol",
|
||||
"symbol [ symbolname [symbolname ... ] ]\n"
|
||||
" display value associated with specified symbol.\n"
|
||||
" Defaults to displaying all known symbols.\n",
|
||||
0,
|
||||
rtems_monitor_symbol_cmd,
|
||||
(unsigned32) &rtems_monitor_symbols,
|
||||
},
|
||||
{ "extension",
|
||||
"extension [id [id ...] ]\n"
|
||||
" display information about specified extensions.\n"
|
||||
" Default is to display information about all extensions on this node\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_EXTENSION,
|
||||
},
|
||||
{ "task",
|
||||
"task [id [id ...] ]\n"
|
||||
" display information about the specified tasks.\n"
|
||||
" Default is to display information about all tasks on this node\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_TASK,
|
||||
},
|
||||
{ "queue",
|
||||
"queue [id [id ... ] ]\n"
|
||||
" display information about the specified message queues\n"
|
||||
" Default is to display information about all queues on this node\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_QUEUE,
|
||||
},
|
||||
{ "object",
|
||||
"object [id [id ...] ]\n"
|
||||
" display information about specified RTEMS objects.\n"
|
||||
" Object id's must include 'type' information.\n"
|
||||
" (which may normally be defaulted)\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_INVALID,
|
||||
},
|
||||
{ "driver",
|
||||
"driver [ major [ major ... ] ]\n"
|
||||
" Display the RTEMS device driver table.\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_DRIVER,
|
||||
},
|
||||
{ "dname",
|
||||
"dname\n"
|
||||
" Displays information about named drivers.\n",
|
||||
0,
|
||||
rtems_monitor_object_cmd,
|
||||
RTEMS_MONITOR_OBJECT_DNAME,
|
||||
},
|
||||
{ "exit",
|
||||
"exit [status]\n"
|
||||
" Invoke 'rtems_fatal_error_occurred' with 'status'\n"
|
||||
" (default is RTEMS_SUCCESSFUL)\n",
|
||||
0,
|
||||
rtems_monitor_fatal_cmd,
|
||||
RTEMS_SUCCESSFUL,
|
||||
},
|
||||
{ "fatal",
|
||||
"fatal [status]\n"
|
||||
" 'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n",
|
||||
0,
|
||||
rtems_monitor_fatal_cmd,
|
||||
RTEMS_TASK_EXITTED, /* exit value */
|
||||
},
|
||||
{ "quit",
|
||||
"quit [status]\n"
|
||||
" Alias for 'exit'\n",
|
||||
0,
|
||||
rtems_monitor_fatal_cmd,
|
||||
RTEMS_SUCCESSFUL, /* exit value */
|
||||
},
|
||||
{ "help",
|
||||
"help [ command [ command ] ]\n"
|
||||
" provide information about commands\n"
|
||||
" Default is show basic command summary.\n",
|
||||
0,
|
||||
rtems_monitor_help_cmd,
|
||||
(unsigned32) rtems_monitor_commands,
|
||||
},
|
||||
#ifdef CPU_INVOKE_DEBUGGER
|
||||
{ "debugger",
|
||||
"debugger\n"
|
||||
" Enter the debugger, if possible.\n"
|
||||
" A continue from the debugger will return to the monitor.\n",
|
||||
0,
|
||||
rtems_monitor_debugger_cmd,
|
||||
0,
|
||||
},
|
||||
#endif
|
||||
{ 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
||||
rtems_status_code
|
||||
rtems_monitor_suspend(rtems_interval timeout)
|
||||
{
|
||||
rtems_event_set event_set;
|
||||
rtems_status_code status;
|
||||
|
||||
status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
|
||||
RTEMS_DEFAULT_OPTIONS,
|
||||
timeout,
|
||||
&event_set);
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_wakeup(void)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_debugger_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
#ifdef CPU_INVOKE_DEBUGGER
|
||||
CPU_INVOKE_DEBUGGER;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_pause_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
if (argc == 1)
|
||||
rtems_monitor_suspend(1);
|
||||
else
|
||||
rtems_monitor_suspend(strtoul(argv[1], 0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_fatal_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
if (argc == 1)
|
||||
rtems_fatal_error_occurred(command_arg);
|
||||
else
|
||||
rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_continue_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_node_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 new_node = rtems_monitor_default_node;
|
||||
|
||||
switch (argc)
|
||||
{
|
||||
case 1: /* no node, just set back to ours */
|
||||
new_node = rtems_monitor_node;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
new_node = strtoul(argv[1], 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("invalid syntax, try 'help node'\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((new_node >= 1) &&
|
||||
_Configuration_MP_table &&
|
||||
(new_node <= _Configuration_MP_table->maximum_nodes))
|
||||
rtems_monitor_default_node = new_node;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: rtems_monitor_symbols_loadup
|
||||
*
|
||||
* Description:
|
||||
* Create and load the monitor's symbol table.
|
||||
* We are reading the output format of 'gnm' which looks like this:
|
||||
*
|
||||
* 400a7068 ? _Rate_monotonic_Information
|
||||
* 400a708c ? _Thread_Dispatch_disable_level
|
||||
* 400a7090 ? _Configuration_Table
|
||||
*
|
||||
* We ignore the type field.
|
||||
*
|
||||
* Side Effects:
|
||||
* Creates and fills in 'rtems_monitor_symbols' table
|
||||
*
|
||||
* TODO
|
||||
* there should be a BSP #define or something like that
|
||||
* to do this; Assuming stdio is crazy.
|
||||
* Someday this should know BFD
|
||||
* Maybe we could get objcopy to just copy the symbol areas
|
||||
* and copy that down.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_symbols_loadup(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char buffer[128];
|
||||
|
||||
if (rtems_monitor_symbols)
|
||||
rtems_symbol_table_destroy(rtems_monitor_symbols);
|
||||
|
||||
rtems_monitor_symbols = rtems_symbol_table_create(10);
|
||||
if (rtems_monitor_symbols == 0)
|
||||
return;
|
||||
|
||||
fp = fopen("symbols", "r");
|
||||
|
||||
if (fp == 0)
|
||||
return;
|
||||
|
||||
while (fgets(buffer, sizeof(buffer) - 1, fp))
|
||||
{
|
||||
char *symbol;
|
||||
char *value;
|
||||
char *ignored_type;
|
||||
|
||||
value = strtok(buffer, " \t\n");
|
||||
ignored_type = strtok(0, " \t\n");
|
||||
symbol = strtok(0, " \t\n");
|
||||
|
||||
if (symbol && ignored_type && value)
|
||||
{
|
||||
rtems_symbol_t *sp;
|
||||
sp = rtems_symbol_create(rtems_monitor_symbols,
|
||||
symbol,
|
||||
(rtems_unsigned32) strtoul(value, 0, 16));
|
||||
if (sp == 0)
|
||||
{
|
||||
printf("could not define symbol '%s'\n", symbol);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("parsing error on '%s'\n", buffer);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Main monitor command loop
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_task(
|
||||
rtems_task_argument monitor_flags
|
||||
)
|
||||
{
|
||||
rtems_tcb *debugee = 0;
|
||||
rtems_context *rp;
|
||||
rtems_context_fp *fp;
|
||||
char command_buffer[513];
|
||||
int argc;
|
||||
char *argv[64];
|
||||
boolean verbose = FALSE;
|
||||
|
||||
if (monitor_flags & RTEMS_MONITOR_SUSPEND)
|
||||
(void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
extern rtems_tcb * _Thread_Executing;
|
||||
rtems_monitor_command_entry_t *command;
|
||||
|
||||
debugee = _Thread_Executing;
|
||||
rp = &debugee->Registers;
|
||||
fp = (rtems_context_fp *) debugee->fp_context; /* possibly 0 */
|
||||
|
||||
if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
|
||||
continue;
|
||||
if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
|
||||
argc,
|
||||
argv)) == 0)
|
||||
continue;
|
||||
|
||||
command->command_function(argc, argv, command->command_arg, verbose);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_kill(void)
|
||||
{
|
||||
if (rtems_monitor_task_id)
|
||||
rtems_task_delete(rtems_monitor_task_id);
|
||||
rtems_monitor_task_id = 0;
|
||||
|
||||
rtems_monitor_server_kill();
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_init(
|
||||
unsigned32 monitor_flags
|
||||
)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
rtems_monitor_kill();
|
||||
|
||||
status = rtems_task_create(RTEMS_MONITOR_NAME,
|
||||
1,
|
||||
RTEMS_MINIMUM_STACK_SIZE * 2,
|
||||
RTEMS_INTERRUPT_LEVEL(0),
|
||||
RTEMS_DEFAULT_ATTRIBUTES,
|
||||
&rtems_monitor_task_id);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not create monitor task");
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
|
||||
rtems_monitor_default_node = rtems_monitor_node;
|
||||
|
||||
rtems_monitor_symbols_loadup();
|
||||
|
||||
if (monitor_flags & RTEMS_MONITOR_GLOBAL)
|
||||
rtems_monitor_server_init(monitor_flags);
|
||||
|
||||
/*
|
||||
* Start the monitor task itself
|
||||
*/
|
||||
|
||||
status = rtems_task_start(rtems_monitor_task_id,
|
||||
rtems_monitor_task,
|
||||
monitor_flags);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not start monitor");
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* RTEMS MPCI Config display support
|
||||
*
|
||||
* TODO
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
|
||||
#define DATACOL 15
|
||||
|
||||
/*
|
||||
* Fill in entire monitor config table
|
||||
* for sending to a remote monitor or printing on the local system
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_mpci_canonical(
|
||||
rtems_monitor_mpci_t *canonical_mpci,
|
||||
void *config_void
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = _Configuration_Table;
|
||||
rtems_multiprocessing_table *m;
|
||||
rtems_mpci_table *mt;
|
||||
|
||||
m = c->User_multiprocessing_table;
|
||||
if (m == 0)
|
||||
return;
|
||||
mt = m->User_mpci_table;
|
||||
|
||||
canonical_mpci->node = m->node;
|
||||
canonical_mpci->maximum_nodes = m->maximum_nodes;
|
||||
canonical_mpci->maximum_global_objects = m->maximum_global_objects;
|
||||
canonical_mpci->maximum_proxies = m->maximum_proxies;
|
||||
|
||||
canonical_mpci->default_timeout = mt->default_timeout;
|
||||
canonical_mpci->maximum_packet_size = mt->maximum_packet_size;
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_mpci->initialization,
|
||||
(void *) mt->initialization);
|
||||
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_mpci->get_packet,
|
||||
(void *) mt->get_packet);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_mpci->return_packet,
|
||||
(void *) mt->return_packet);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_mpci->send_packet,
|
||||
(void *) mt->send_packet);
|
||||
rtems_monitor_symbol_canonical_by_value(&canonical_mpci->receive_packet,
|
||||
(void *) mt->receive_packet);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is easy, since there is only 1 (altho we could get them from
|
||||
* other nodes...)
|
||||
*/
|
||||
|
||||
void *
|
||||
rtems_monitor_mpci_next(
|
||||
void *object_info,
|
||||
rtems_monitor_mpci_t *canonical_mpci,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_configuration_table *c = _Configuration_Table;
|
||||
int n = rtems_get_index(*next_id);
|
||||
|
||||
if (n >= 1)
|
||||
goto failed;
|
||||
|
||||
if ( ! c->User_multiprocessing_table)
|
||||
goto failed;
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
*next_id += 1;
|
||||
return (void *) c;
|
||||
|
||||
failed:
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_mpci_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
max max max default max\n\
|
||||
node nodes globals proxies timeout pktsize\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_mpci_dump(
|
||||
rtems_monitor_mpci_t *monitor_mpci,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length += rtems_monitor_pad(2, length);
|
||||
length += printf(" %d", monitor_mpci->node);
|
||||
length += rtems_monitor_pad(11, length);
|
||||
length += printf("%d", monitor_mpci->maximum_nodes);
|
||||
|
||||
length += rtems_monitor_pad(18, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_mpci->maximum_global_objects);
|
||||
|
||||
length += rtems_monitor_pad(28, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_mpci->maximum_proxies);
|
||||
|
||||
length += rtems_monitor_pad(37, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_mpci->default_timeout);
|
||||
|
||||
length += rtems_monitor_pad(46, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_mpci->maximum_packet_size);
|
||||
|
||||
printf("\n");
|
||||
length = 0;
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
|
||||
length += printf("init: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_mpci->initialization, verbose);
|
||||
|
||||
printf("\n");
|
||||
length = 0;
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
|
||||
length += printf("get: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_mpci->get_packet, verbose);
|
||||
length += printf("; return: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_mpci->return_packet, verbose);
|
||||
|
||||
printf("\n");
|
||||
length = 0;
|
||||
length += rtems_monitor_pad(DATACOL, length);
|
||||
|
||||
length += printf("send: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_mpci->send_packet, verbose);
|
||||
length += printf("; receive: ");
|
||||
length += rtems_monitor_symbol_dump(&monitor_mpci->receive_packet, verbose);
|
||||
|
||||
printf("\n");
|
||||
length = 0;
|
||||
}
|
||||
@@ -1,382 +0,0 @@
|
||||
/*
|
||||
* RTEMS Monitor "object" support.
|
||||
*
|
||||
* Used to traverse object lists and print them out.
|
||||
* An object can be an RTEMS object (chain based stuff) or
|
||||
* a "misc" object such as a device driver.
|
||||
*
|
||||
* Each object has its own file in this directory (eg: extension.c)
|
||||
* That file provides routines to convert a "native" structure
|
||||
* to its canonical form, print a canonical structure, etc.
|
||||
*
|
||||
* TODO:
|
||||
* should allow for non-numeric id's???
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* strtoul() */
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
/*
|
||||
* add:
|
||||
* next
|
||||
*/
|
||||
|
||||
rtems_monitor_object_info_t rtems_monitor_object_info[] =
|
||||
{
|
||||
{ RTEMS_MONITOR_OBJECT_CONFIG,
|
||||
(void *) 0,
|
||||
sizeof(rtems_monitor_config_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_config_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_config_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_config_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_config_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_MPCI,
|
||||
(void *) 0,
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
sizeof(rtems_monitor_mpci_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_mpci_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_mpci_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_mpci_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_mpci_dump,
|
||||
#else
|
||||
0,
|
||||
(rtems_monitor_object_next_fn) 0,
|
||||
(rtems_monitor_object_canonical_fn) 0,
|
||||
(rtems_monitor_object_dump_header_fn) 0,
|
||||
(rtems_monitor_object_dump_fn) 0,
|
||||
#endif
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_INIT_TASK,
|
||||
(void *) 0,
|
||||
sizeof(rtems_monitor_init_task_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_init_task_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_init_task_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_init_task_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_init_task_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_TASK,
|
||||
(void *) &_RTEMS_tasks_Information,
|
||||
sizeof(rtems_monitor_task_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_manager_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_task_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_task_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_task_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_QUEUE,
|
||||
(void *) &_Message_queue_Information,
|
||||
sizeof(rtems_monitor_queue_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_manager_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_queue_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_queue_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_queue_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_EXTENSION,
|
||||
(void *) &_Extension_Information,
|
||||
sizeof(rtems_monitor_extension_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_manager_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_extension_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_extension_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_extension_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_DRIVER,
|
||||
(void *) 0,
|
||||
sizeof(rtems_monitor_driver_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_driver_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_driver_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_driver_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_driver_dump,
|
||||
},
|
||||
{ RTEMS_MONITOR_OBJECT_DNAME,
|
||||
/* XXX now that the driver name table is allocated from the */
|
||||
/* XXX Workspace, this does not work */
|
||||
(void *) 0,
|
||||
/* (void *) _IO_Driver_name_table, */
|
||||
sizeof(rtems_monitor_dname_t),
|
||||
(rtems_monitor_object_next_fn) rtems_monitor_dname_next,
|
||||
(rtems_monitor_object_canonical_fn) rtems_monitor_dname_canonical,
|
||||
(rtems_monitor_object_dump_header_fn) rtems_monitor_dname_dump_header,
|
||||
(rtems_monitor_object_dump_fn) rtems_monitor_dname_dump,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Allow id's to be specified without the node number or
|
||||
* type for convenience.
|
||||
*/
|
||||
|
||||
rtems_id
|
||||
rtems_monitor_id_fixup(
|
||||
rtems_id id,
|
||||
unsigned32 default_node,
|
||||
rtems_monitor_object_type_t type
|
||||
)
|
||||
{
|
||||
unsigned32 node;
|
||||
|
||||
node = rtems_get_node(id);
|
||||
if (node == 0)
|
||||
{
|
||||
if (rtems_get_class(id) != OBJECTS_NO_CLASS)
|
||||
type = rtems_get_class(id);
|
||||
|
||||
id = _Objects_Build_id(type, default_node, rtems_get_index(id));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
rtems_monitor_object_info_t *
|
||||
rtems_monitor_object_lookup(
|
||||
rtems_monitor_object_type_t type
|
||||
)
|
||||
{
|
||||
rtems_monitor_object_info_t *p;
|
||||
for (p = &rtems_monitor_object_info[0];
|
||||
p < &rtems_monitor_object_info[NUMELEMS(rtems_monitor_object_info)];
|
||||
p++)
|
||||
{
|
||||
if (p->type == type)
|
||||
return p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rtems_id
|
||||
rtems_monitor_object_canonical_next_remote(
|
||||
rtems_monitor_object_type_t type,
|
||||
rtems_id id,
|
||||
void *canonical
|
||||
)
|
||||
{
|
||||
rtems_id next_id;
|
||||
rtems_status_code status;
|
||||
rtems_monitor_server_request_t request;
|
||||
rtems_monitor_server_response_t response;
|
||||
|
||||
/*
|
||||
* Send request
|
||||
*/
|
||||
|
||||
request.command = RTEMS_MONITOR_SERVER_CANONICAL;
|
||||
request.argument0 = (unsigned32) type;
|
||||
request.argument1 = (unsigned32) id;
|
||||
|
||||
status = rtems_monitor_server_request(rtems_get_node(id), &request, &response);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
goto failed;
|
||||
|
||||
/*
|
||||
* process response
|
||||
*/
|
||||
|
||||
next_id = (rtems_id) response.result0;
|
||||
if (next_id != RTEMS_OBJECT_ID_FINAL)
|
||||
(void) memcpy(canonical, &response.payload, response.result1);
|
||||
|
||||
return next_id;
|
||||
|
||||
failed:
|
||||
return RTEMS_OBJECT_ID_FINAL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
rtems_id
|
||||
rtems_monitor_object_canonical_next(
|
||||
rtems_monitor_object_info_t *info,
|
||||
rtems_id id,
|
||||
void *canonical
|
||||
)
|
||||
{
|
||||
rtems_id next_id;
|
||||
void *raw_item;
|
||||
|
||||
if ( ! _Objects_Is_local_id(id))
|
||||
next_id = rtems_monitor_object_canonical_next_remote(info->type,
|
||||
id,
|
||||
canonical);
|
||||
else
|
||||
{
|
||||
next_id = id;
|
||||
|
||||
raw_item = (void *) info->next(info->object_information,
|
||||
canonical,
|
||||
&next_id);
|
||||
|
||||
if (raw_item)
|
||||
{
|
||||
info->canonical(canonical, raw_item);
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
}
|
||||
return next_id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* this is routine server invokes locally to get the type
|
||||
*/
|
||||
|
||||
rtems_id
|
||||
rtems_monitor_object_canonical_get(
|
||||
rtems_monitor_object_type_t type,
|
||||
rtems_id id,
|
||||
void *canonical,
|
||||
unsigned32 *size_p
|
||||
)
|
||||
{
|
||||
rtems_monitor_object_info_t *info;
|
||||
rtems_id next_id;
|
||||
|
||||
*size_p = 0;
|
||||
|
||||
info = rtems_monitor_object_lookup(type);
|
||||
|
||||
if (info == 0)
|
||||
return RTEMS_OBJECT_ID_FINAL;
|
||||
|
||||
next_id = rtems_monitor_object_canonical_next(info, id, canonical);
|
||||
*size_p = info->size;
|
||||
|
||||
return next_id;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_object_dump_1(
|
||||
rtems_monitor_object_info_t *info,
|
||||
rtems_id id,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
rtems_id next_id;
|
||||
rtems_monitor_union_t canonical;
|
||||
|
||||
if ((next_id = rtems_monitor_object_canonical_next(
|
||||
info,
|
||||
id,
|
||||
&canonical)) != RTEMS_OBJECT_ID_FINAL)
|
||||
{
|
||||
/*
|
||||
* If the one we actually got is the one we wanted, then
|
||||
* print it out.
|
||||
* For ones that have an id field, this works fine,
|
||||
* for all others, always dump it out.
|
||||
*
|
||||
* HACK: the way we determine whether there is an id is a hack.
|
||||
*
|
||||
* by the way: the reason we try to not have an id, is that some
|
||||
* of the canonical structures are almost too big for shared
|
||||
* memory driver (eg: mpci)
|
||||
*/
|
||||
|
||||
if ((info->next != rtems_monitor_manager_next) ||
|
||||
(id == canonical.generic.id))
|
||||
info->dump(&canonical, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_object_dump_all(
|
||||
rtems_monitor_object_info_t *info,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
rtems_id next_id;
|
||||
rtems_monitor_union_t canonical;
|
||||
|
||||
next_id = RTEMS_OBJECT_ID_INITIAL(info->type, rtems_monitor_default_node);
|
||||
|
||||
while ((next_id = rtems_monitor_object_canonical_next(
|
||||
info,
|
||||
next_id,
|
||||
&canonical)) != RTEMS_OBJECT_ID_FINAL)
|
||||
{
|
||||
info->dump(&canonical, verbose);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_object_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
int arg;
|
||||
rtems_monitor_object_info_t *info = 0;
|
||||
rtems_monitor_object_type_t type = (rtems_monitor_object_type_t) command_arg;
|
||||
|
||||
/* what is the default type? */
|
||||
type = (rtems_monitor_object_type_t) command_arg;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
if (type == RTEMS_MONITOR_OBJECT_INVALID)
|
||||
{
|
||||
printf("A type must be specified to \"dump all\"\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
info = rtems_monitor_object_lookup(type);
|
||||
if (info == 0)
|
||||
goto not_found;
|
||||
|
||||
if (info->dump_header)
|
||||
info->dump_header(verbose);
|
||||
rtems_monitor_object_dump_all(info, verbose);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned32 default_node = rtems_monitor_default_node;
|
||||
rtems_monitor_object_type_t last_type = RTEMS_MONITOR_OBJECT_INVALID;
|
||||
rtems_id id;
|
||||
|
||||
for (arg=1; argv[arg]; arg++)
|
||||
{
|
||||
id = (rtems_id) strtoul(argv[arg], 0, 16);
|
||||
id = rtems_monitor_id_fixup(id, default_node, type);
|
||||
type = (rtems_monitor_object_type_t) rtems_get_class(id);
|
||||
|
||||
/*
|
||||
* Allow the item type to change in the middle
|
||||
* of the command. If the type changes, then
|
||||
* just dump out a new header and keep on going.
|
||||
*/
|
||||
if (type != last_type)
|
||||
{
|
||||
info = rtems_monitor_object_lookup(type);
|
||||
if (info == 0)
|
||||
goto not_found;
|
||||
|
||||
if (info->dump_header)
|
||||
info->dump_header(verbose);
|
||||
}
|
||||
|
||||
if (info == 0)
|
||||
{
|
||||
not_found: printf("Invalid or unsupported type %d\n", type);
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtems_monitor_object_dump_1(info, id, verbose);
|
||||
|
||||
default_node = rtems_get_node(id);
|
||||
|
||||
last_type = type;
|
||||
}
|
||||
}
|
||||
done:
|
||||
return;
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/*
|
||||
* Print misc stuff for the monitor dump routines
|
||||
* Each routine returns the number of characters it output.
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <rtems/assoc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void
|
||||
rtems_monitor_separator(void)
|
||||
{
|
||||
printf("------------------------------------------------------------------------------\n");
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_pad(
|
||||
unsigned32 destination_column,
|
||||
unsigned32 current_column
|
||||
)
|
||||
{
|
||||
int pad_length;
|
||||
|
||||
if (destination_column <= current_column)
|
||||
pad_length = 1;
|
||||
else
|
||||
pad_length = destination_column - current_column;
|
||||
|
||||
return printf("%*s", pad_length, "");
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_char(rtems_unsigned8 ch)
|
||||
{
|
||||
if (isprint(ch))
|
||||
return printf("%c", ch);
|
||||
else
|
||||
return printf("%02x", ch);
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_decimal(unsigned32 num)
|
||||
{
|
||||
return printf("%4d", num);
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_hex(unsigned32 num)
|
||||
{
|
||||
return printf("0x%x", num);
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_assoc_bitfield(
|
||||
rtems_assoc_t *ap,
|
||||
char *separator,
|
||||
unsigned32 value
|
||||
)
|
||||
{
|
||||
unsigned32 b;
|
||||
unsigned32 length = 0;
|
||||
const char *name;
|
||||
|
||||
for (b = 1; b; b <<= 1)
|
||||
if (b & value)
|
||||
{
|
||||
if (length)
|
||||
length += printf("%s", separator);
|
||||
|
||||
name = rtems_assoc_name_by_local(ap, b);
|
||||
|
||||
if (name)
|
||||
length += printf("%s", name);
|
||||
else
|
||||
length += printf("0x%x", b);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_id(rtems_id id)
|
||||
{
|
||||
return printf("%08x", id);
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_name(rtems_name name)
|
||||
{
|
||||
unsigned32 i;
|
||||
unsigned32 length = 0;
|
||||
union {
|
||||
unsigned32 ui;
|
||||
char c[4];
|
||||
} u;
|
||||
|
||||
u.ui = (rtems_unsigned32) name;
|
||||
|
||||
#if (CPU_BIG_ENDIAN == TRUE)
|
||||
for (i=0; i<sizeof(u.c); i++)
|
||||
length += rtems_monitor_dump_char(u.c[i]);
|
||||
#else
|
||||
for (i=sizeof(u.c)-1; i ; i--)
|
||||
length += rtems_monitor_dump_char(u.c[i]);
|
||||
#endif
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_priority(rtems_task_priority priority)
|
||||
{
|
||||
return printf("%3d", priority);
|
||||
}
|
||||
|
||||
|
||||
rtems_assoc_t rtems_monitor_state_assoc[] = {
|
||||
{ "DORM", STATES_DORMANT },
|
||||
{ "SUSP", STATES_SUSPENDED },
|
||||
{ "TRANS", STATES_TRANSIENT },
|
||||
{ "DELAY", STATES_DELAYING },
|
||||
{ "Wbuf", STATES_WAITING_FOR_BUFFER },
|
||||
{ "Wseg", STATES_WAITING_FOR_SEGMENT },
|
||||
{ "Wmsg" , STATES_WAITING_FOR_MESSAGE },
|
||||
{ "Wevnt", STATES_WAITING_FOR_EVENT },
|
||||
{ "Wsem", STATES_WAITING_FOR_SEMAPHORE },
|
||||
{ "Wtime", STATES_WAITING_FOR_TIME },
|
||||
{ "Wrpc", STATES_WAITING_FOR_RPC_REPLY },
|
||||
{ "WRATE", STATES_WAITING_FOR_PERIOD },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_state(States_Control state)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
if (state == STATES_READY) /* assoc doesn't deal with this as it is 0 */
|
||||
length += printf("READY");
|
||||
|
||||
length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_state_assoc,
|
||||
":",
|
||||
state);
|
||||
return length;
|
||||
}
|
||||
|
||||
rtems_assoc_t rtems_monitor_attribute_assoc[] = {
|
||||
{ "FL", RTEMS_FLOATING_POINT },
|
||||
{ "GL", RTEMS_GLOBAL },
|
||||
{ "PR", RTEMS_PRIORITY },
|
||||
{ "BI", RTEMS_BINARY_SEMAPHORE },
|
||||
{ "IN", RTEMS_INHERIT_PRIORITY },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_attributes(rtems_attribute attributes)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
if (attributes == RTEMS_DEFAULT_ATTRIBUTES) /* value is 0 */
|
||||
length += printf("DEFAULT");
|
||||
|
||||
length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_attribute_assoc,
|
||||
":",
|
||||
attributes);
|
||||
return length;
|
||||
}
|
||||
|
||||
rtems_assoc_t rtems_monitor_modes_assoc[] = {
|
||||
{ "nP", RTEMS_NO_PREEMPT },
|
||||
{ "T", RTEMS_TIMESLICE },
|
||||
{ "nA", RTEMS_NO_ASR },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_modes(rtems_mode modes)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
if (modes == RTEMS_DEFAULT_MODES) /* value is 0 */
|
||||
length += printf("P:T:nA");
|
||||
|
||||
length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_modes_assoc,
|
||||
":",
|
||||
modes);
|
||||
return length;
|
||||
}
|
||||
|
||||
rtems_assoc_t rtems_monitor_events_assoc[] = {
|
||||
{ "0", RTEMS_EVENT_0 },
|
||||
{ "1", RTEMS_EVENT_1 },
|
||||
{ "2", RTEMS_EVENT_2 },
|
||||
{ "3", RTEMS_EVENT_3 },
|
||||
{ "4", RTEMS_EVENT_4 },
|
||||
{ "5", RTEMS_EVENT_5 },
|
||||
{ "6", RTEMS_EVENT_6 },
|
||||
{ "7", RTEMS_EVENT_7 },
|
||||
{ "8", RTEMS_EVENT_8 },
|
||||
{ "9", RTEMS_EVENT_9 },
|
||||
{ "10", RTEMS_EVENT_10 },
|
||||
{ "11", RTEMS_EVENT_11 },
|
||||
{ "12", RTEMS_EVENT_12 },
|
||||
{ "13", RTEMS_EVENT_13 },
|
||||
{ "14", RTEMS_EVENT_14 },
|
||||
{ "15", RTEMS_EVENT_15 },
|
||||
{ "16", RTEMS_EVENT_16 },
|
||||
{ "17", RTEMS_EVENT_17 },
|
||||
{ "18", RTEMS_EVENT_18 },
|
||||
{ "19", RTEMS_EVENT_19 },
|
||||
{ "20", RTEMS_EVENT_20 },
|
||||
{ "21", RTEMS_EVENT_21 },
|
||||
{ "22", RTEMS_EVENT_22 },
|
||||
{ "23", RTEMS_EVENT_23 },
|
||||
{ "24", RTEMS_EVENT_24 },
|
||||
{ "25", RTEMS_EVENT_25 },
|
||||
{ "26", RTEMS_EVENT_26 },
|
||||
{ "27", RTEMS_EVENT_27 },
|
||||
{ "28", RTEMS_EVENT_28 },
|
||||
{ "29", RTEMS_EVENT_29 },
|
||||
{ "30", RTEMS_EVENT_30 },
|
||||
{ "31", RTEMS_EVENT_31 },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_events(rtems_event_set events)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
if (events == EVENT_SETS_NONE_PENDING) /* value is 0 */
|
||||
length += printf("NONE");
|
||||
|
||||
length += rtems_monitor_dump_assoc_bitfield(rtems_monitor_events_assoc,
|
||||
":",
|
||||
events);
|
||||
return length;
|
||||
}
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_dump_notepad(unsigned32 *notepad)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
int i;
|
||||
|
||||
for (i=0; i < RTEMS_NUMBER_NOTEPADS; i++)
|
||||
if (notepad[i])
|
||||
length += printf("%d: 0x%x ", i, notepad[i]);
|
||||
|
||||
return length;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
rtems_monitor_queue_canonical(
|
||||
rtems_monitor_queue_t *canonical_queue,
|
||||
void *queue_void
|
||||
)
|
||||
{
|
||||
Message_queue_Control *rtems_queue = (Message_queue_Control *) queue_void;
|
||||
|
||||
canonical_queue->attributes = rtems_queue->attribute_set;
|
||||
canonical_queue->maximum_message_size = rtems_queue->message_queue.maximum_message_size;
|
||||
canonical_queue->maximum_pending_messages = rtems_queue->message_queue.maximum_pending_messages;
|
||||
canonical_queue->number_of_pending_messages = rtems_queue->message_queue.number_of_pending_messages;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_queue_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
ID NAME ATTRIBUTES PEND MAXPEND MAXSIZE\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dump out the "next" queue indicated by 'id'.
|
||||
* Returns next one to check.
|
||||
* Returns RTEMS_OBJECT_ID_FINAL when all done
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_queue_dump(
|
||||
rtems_monitor_queue_t *monitor_queue,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
length += rtems_monitor_dump_id(monitor_queue->id);
|
||||
length += rtems_monitor_pad(11, length);
|
||||
length += rtems_monitor_dump_name(monitor_queue->name);
|
||||
length += rtems_monitor_pad(19, length);
|
||||
length += rtems_monitor_dump_attributes(monitor_queue->attributes);
|
||||
length += rtems_monitor_pad(31, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_queue->number_of_pending_messages);
|
||||
length += rtems_monitor_pad(39, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_queue->maximum_pending_messages);
|
||||
length += rtems_monitor_pad(48, length);
|
||||
length += rtems_monitor_dump_decimal(monitor_queue->maximum_message_size);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1,303 +0,0 @@
|
||||
/*
|
||||
* RTEMS monitor server (handles requests for info from RTEMS monitors
|
||||
* running on other nodes)
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
/*
|
||||
* Various id's for the server
|
||||
*/
|
||||
|
||||
rtems_id rtems_monitor_server_task_id;
|
||||
rtems_id rtems_monitor_server_request_queue_id; /* our server */
|
||||
rtems_id *rtems_monitor_server_request_queue_ids; /* all servers */
|
||||
rtems_id rtems_monitor_server_response_queue_id; /* our server */
|
||||
|
||||
|
||||
/*
|
||||
* Send a request to a server task
|
||||
*/
|
||||
|
||||
rtems_status_code
|
||||
rtems_monitor_server_request(
|
||||
unsigned32 server_node,
|
||||
rtems_monitor_server_request_t *request,
|
||||
rtems_monitor_server_response_t *response
|
||||
)
|
||||
{
|
||||
rtems_id server_id;
|
||||
rtems_status_code status;
|
||||
unsigned32 size;
|
||||
|
||||
/*
|
||||
* What is id of monitor on target node?
|
||||
* Look it up if we don't know it yet.
|
||||
*/
|
||||
|
||||
server_id = rtems_monitor_server_request_queue_ids[server_node];
|
||||
if (server_id == 0)
|
||||
{
|
||||
status = rtems_message_queue_ident(RTEMS_MONITOR_QUEUE_NAME,
|
||||
server_node,
|
||||
&server_id);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "ident of remote server failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
rtems_monitor_server_request_queue_ids[server_node] = server_id;
|
||||
}
|
||||
|
||||
request->return_id = rtems_monitor_server_response_queue_id;
|
||||
|
||||
status = rtems_message_queue_send(server_id, request, sizeof(*request));
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "monitor server request send failed");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Await response, if requested
|
||||
*/
|
||||
|
||||
if (response)
|
||||
{
|
||||
status = rtems_message_queue_receive(rtems_monitor_server_response_queue_id,
|
||||
response,
|
||||
&size,
|
||||
RTEMS_WAIT,
|
||||
100);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "server did not respond");
|
||||
|
||||
/* maybe server task was restarted; look it up again next time */
|
||||
rtems_monitor_server_request_queue_ids[server_node] = 0;
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (response->command != RTEMS_MONITOR_SERVER_RESPONSE)
|
||||
{
|
||||
status = RTEMS_INCORRECT_STATE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* monitor server task
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_server_task(
|
||||
rtems_task_argument monitor_flags
|
||||
)
|
||||
{
|
||||
rtems_monitor_server_request_t request;
|
||||
rtems_monitor_server_response_t response;
|
||||
rtems_status_code status;
|
||||
unsigned32 size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
status = rtems_message_queue_receive(
|
||||
rtems_monitor_server_request_queue_id,
|
||||
&request,
|
||||
&size,
|
||||
RTEMS_WAIT,
|
||||
(rtems_interval) 0);
|
||||
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "monitor server msg queue receive error");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (size != sizeof(request))
|
||||
{
|
||||
rtems_error(0, "monitor server bad size on receive");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
switch (request.command)
|
||||
{
|
||||
case RTEMS_MONITOR_SERVER_CANONICAL:
|
||||
{
|
||||
rtems_monitor_object_type_t object_type;
|
||||
rtems_id id;
|
||||
rtems_id next_id;
|
||||
|
||||
object_type = (rtems_monitor_object_type_t) request.argument0;
|
||||
id = (rtems_id) request.argument1;
|
||||
next_id = rtems_monitor_object_canonical_get(object_type,
|
||||
id,
|
||||
&response.payload,
|
||||
&size);
|
||||
|
||||
response.command = RTEMS_MONITOR_SERVER_RESPONSE;
|
||||
response.result0 = next_id;
|
||||
response.result1 = size;
|
||||
|
||||
#define SERVER_OVERHEAD (RTEMS_offsetof(rtems_monitor_server_response_t, \
|
||||
payload))
|
||||
|
||||
status = rtems_message_queue_send(request.return_id,
|
||||
&response,
|
||||
size + SERVER_OVERHEAD);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "response send failed");
|
||||
goto failed;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
rtems_error(0, "invalid command to monitor server: %d", request.command);
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
failed:
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Kill off any old server
|
||||
* Not sure if this is useful, but it doesn't help
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_server_kill(void)
|
||||
{
|
||||
if (rtems_monitor_server_task_id)
|
||||
rtems_task_delete(rtems_monitor_server_task_id);
|
||||
rtems_monitor_task_id = 0;
|
||||
|
||||
if (rtems_monitor_server_request_queue_id)
|
||||
rtems_message_queue_delete(rtems_monitor_server_request_queue_id);
|
||||
rtems_monitor_server_response_queue_id = 0;
|
||||
|
||||
if (rtems_monitor_server_response_queue_id)
|
||||
rtems_message_queue_delete(rtems_monitor_server_response_queue_id);
|
||||
rtems_monitor_server_request_queue_ids = 0;
|
||||
|
||||
if (rtems_monitor_server_request_queue_ids)
|
||||
free(rtems_monitor_server_request_queue_ids);
|
||||
rtems_monitor_server_request_queue_ids = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_server_init(
|
||||
unsigned32 monitor_flags
|
||||
)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
if (_System_state_Is_multiprocessing &&
|
||||
(_Configuration_MP_table->maximum_nodes > 1))
|
||||
{
|
||||
unsigned32 maximum_nodes = _Configuration_MP_table->maximum_nodes;
|
||||
|
||||
/*
|
||||
* create the msg que our server will listen
|
||||
* Since we only get msgs from other RTEMS monitors, we just
|
||||
* need reserve space for 1 msg from each node.
|
||||
*/
|
||||
|
||||
status = rtems_message_queue_create(
|
||||
RTEMS_MONITOR_QUEUE_NAME,
|
||||
maximum_nodes,
|
||||
sizeof(rtems_monitor_server_request_t),
|
||||
RTEMS_GLOBAL,
|
||||
&rtems_monitor_server_request_queue_id);
|
||||
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not create monitor server message queue");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* create the msg que our responses will come on
|
||||
* Since monitor just does one thing at a time, we only need 1 item
|
||||
* message queue.
|
||||
*/
|
||||
|
||||
status = rtems_message_queue_create(
|
||||
RTEMS_MONITOR_RESPONSE_QUEUE_NAME,
|
||||
1, /* depth */
|
||||
sizeof(rtems_monitor_server_response_t),
|
||||
RTEMS_GLOBAL,
|
||||
&rtems_monitor_server_response_queue_id);
|
||||
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not create monitor response message queue");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* need an id for queue of each other server we might talk to */
|
||||
/* indexed by node, so add 1 to maximum_nodes */
|
||||
rtems_monitor_server_request_queue_ids =
|
||||
(rtems_id *) malloc((maximum_nodes + 1) * sizeof(rtems_id));
|
||||
(void) memset(rtems_monitor_server_request_queue_ids,
|
||||
0,
|
||||
(maximum_nodes + 1) * sizeof(rtems_id));
|
||||
|
||||
rtems_monitor_server_request_queue_ids[rtems_monitor_node] =
|
||||
rtems_monitor_server_request_queue_id;
|
||||
|
||||
/*
|
||||
* create the server task
|
||||
*/
|
||||
status = rtems_task_create(RTEMS_MONITOR_SERVER_NAME,
|
||||
1,
|
||||
0 /* default stack */,
|
||||
RTEMS_INTERRUPT_LEVEL(0),
|
||||
RTEMS_DEFAULT_ATTRIBUTES,
|
||||
&rtems_monitor_server_task_id);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not create monitor server task");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the server task
|
||||
*/
|
||||
status = rtems_task_start(rtems_monitor_server_task_id,
|
||||
rtems_monitor_server_task,
|
||||
monitor_flags);
|
||||
if (status != RTEMS_SUCCESSFUL)
|
||||
{
|
||||
rtems_error(status, "could not start monitor server");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return;
|
||||
}
|
||||
@@ -1,483 +0,0 @@
|
||||
/*
|
||||
* File: symbols.c
|
||||
*
|
||||
* Description:
|
||||
* Symbol table manager for the RTEMS monitor.
|
||||
* These routines may be used by other system resources also.
|
||||
*
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
/* for strcasecmp in linux and solaris */
|
||||
#include <string.h>
|
||||
|
||||
#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
|
||||
#include <rtems.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/monitor.h>
|
||||
#include <rtems/symbols.h>
|
||||
|
||||
|
||||
rtems_symbol_table_t *
|
||||
rtems_symbol_table_create()
|
||||
{
|
||||
rtems_symbol_table_t *table;
|
||||
|
||||
table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
|
||||
memset((void *) table, 0, sizeof(*table));
|
||||
|
||||
table->growth_factor = 30; /* 30 percent */
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_symbol_table_destroy(rtems_symbol_table_t *table)
|
||||
{
|
||||
rtems_symbol_string_block_t *p, *pnext;
|
||||
|
||||
if (table)
|
||||
{
|
||||
if (table->addresses)
|
||||
(void) free(table->addresses);
|
||||
table->addresses = 0;
|
||||
p = table->string_buffer_head;
|
||||
while (p)
|
||||
{
|
||||
pnext = p->next;
|
||||
free(p);
|
||||
p = pnext;
|
||||
}
|
||||
table->string_buffer_head = 0;
|
||||
table->string_buffer_current = 0;
|
||||
|
||||
free(table);
|
||||
}
|
||||
}
|
||||
|
||||
rtems_symbol_t *
|
||||
rtems_symbol_create(
|
||||
rtems_symbol_table_t *table,
|
||||
char *name,
|
||||
rtems_unsigned32 value
|
||||
)
|
||||
{
|
||||
int symbol_length;
|
||||
size_t newsize;
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
symbol_length = strlen(name) + 1; /* include '\000' in length */
|
||||
|
||||
/* need to grow the table? */
|
||||
if (table->next >= table->size)
|
||||
{
|
||||
if (table->size == 0)
|
||||
newsize = 100;
|
||||
else
|
||||
newsize = table->size + (table->size / (100 / table->growth_factor));
|
||||
|
||||
table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
|
||||
if (table->addresses == 0) /* blew it; lost orig */
|
||||
goto failed;
|
||||
table->size = newsize;
|
||||
}
|
||||
|
||||
sp = &table->addresses[table->next];
|
||||
sp->value = value;
|
||||
|
||||
/* Have to add it to string pool */
|
||||
/* need to grow pool? */
|
||||
|
||||
if ((table->string_buffer_head == 0) ||
|
||||
(table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
|
||||
{
|
||||
rtems_symbol_string_block_t *p;
|
||||
|
||||
p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
|
||||
if (p == 0)
|
||||
goto failed;
|
||||
p->next = 0;
|
||||
if (table->string_buffer_head == 0)
|
||||
table->string_buffer_head = p;
|
||||
else
|
||||
table->string_buffer_current->next = p;
|
||||
table->string_buffer_current = p;
|
||||
|
||||
table->strings_next = 0;
|
||||
}
|
||||
|
||||
sp->name = table->string_buffer_current->buffer + table->strings_next;
|
||||
(void) strcpy(sp->name, name);
|
||||
|
||||
table->strings_next += symbol_length;
|
||||
table->sorted = 0;
|
||||
table->next++;
|
||||
|
||||
return sp;
|
||||
|
||||
/* XXX Not sure what to do here. We've possibly destroyed the initial
|
||||
symbol table due to realloc failure */
|
||||
failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Qsort entry point for compare by address
|
||||
*/
|
||||
|
||||
static int
|
||||
rtems_symbol_compare(const void *e1,
|
||||
const void *e2)
|
||||
{
|
||||
rtems_symbol_t *s1, *s2;
|
||||
s1 = (rtems_symbol_t *) e1;
|
||||
s2 = (rtems_symbol_t *) e2;
|
||||
|
||||
if (s1->value < s2->value)
|
||||
return -1;
|
||||
if (s1->value > s2->value)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Sort the symbol table using qsort
|
||||
*/
|
||||
|
||||
static void
|
||||
rtems_symbol_sort(rtems_symbol_table_t *table)
|
||||
{
|
||||
qsort((void *) table->addresses, (size_t) table->next,
|
||||
sizeof(rtems_symbol_t), rtems_symbol_compare);
|
||||
table->sorted = 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search the symbol table by address
|
||||
* This code based on CYGNUS newlib bsearch, but changed
|
||||
* to allow for finding closest symbol <= key
|
||||
*/
|
||||
|
||||
rtems_symbol_t *
|
||||
rtems_symbol_value_lookup(
|
||||
rtems_symbol_table_t *table,
|
||||
rtems_unsigned32 value
|
||||
)
|
||||
{
|
||||
rtems_symbol_t *sp;
|
||||
rtems_symbol_t *base;
|
||||
rtems_symbol_t *best = 0;
|
||||
rtems_unsigned32 distance;
|
||||
rtems_unsigned32 best_distance = ~0;
|
||||
rtems_unsigned32 elements;
|
||||
|
||||
if (table == 0)
|
||||
table = rtems_monitor_symbols;
|
||||
|
||||
if ((table == 0) || (table->size == 0))
|
||||
return 0;
|
||||
|
||||
if (table->sorted == 0)
|
||||
rtems_symbol_sort(table);
|
||||
|
||||
base = table->addresses;
|
||||
elements = table->next;
|
||||
|
||||
while (elements)
|
||||
{
|
||||
sp = base + (elements / 2);
|
||||
if (value < sp->value)
|
||||
elements /= 2;
|
||||
else if (value > sp->value)
|
||||
{
|
||||
distance = value - sp->value;
|
||||
if (distance < best_distance)
|
||||
{
|
||||
best_distance = distance;
|
||||
best = sp;
|
||||
}
|
||||
base = sp + 1;
|
||||
elements = (elements / 2) - (elements % 2 ? 0 : 1);
|
||||
}
|
||||
else
|
||||
return sp;
|
||||
}
|
||||
|
||||
if (value == base->value)
|
||||
return base;
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search the symbol table for the exact matching address.
|
||||
* If the symbol table has already been sorted, then
|
||||
* call the regular symbol value lookup, however, it it
|
||||
* has not yet been sorted, search it sequentially.
|
||||
* This routine is primarily used for low level symbol
|
||||
* lookups (eg. from exception handler and interrupt routines)
|
||||
* where the penality of sorted is not wanted and where
|
||||
* an exact match is needed such that symbol table order
|
||||
* is not important.
|
||||
*/
|
||||
const rtems_symbol_t *
|
||||
rtems_symbol_value_lookup_exact(
|
||||
rtems_symbol_table_t *table,
|
||||
rtems_unsigned32 value
|
||||
)
|
||||
{
|
||||
rtems_unsigned32 s;
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
if (table == 0)
|
||||
{
|
||||
table = rtems_monitor_symbols;
|
||||
if (table == 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (table->sorted)
|
||||
{
|
||||
sp = rtems_symbol_value_lookup(table, value);
|
||||
if ( rtems_symbol_value(sp) == value )
|
||||
return sp;
|
||||
else
|
||||
return NULL; /* not an exact match */
|
||||
}
|
||||
|
||||
for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
|
||||
{
|
||||
if ( sp->value == value )
|
||||
return sp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search the symbol table by string name (case independent)
|
||||
*/
|
||||
|
||||
rtems_symbol_t *
|
||||
rtems_symbol_name_lookup(
|
||||
rtems_symbol_table_t *table,
|
||||
char *name
|
||||
)
|
||||
{
|
||||
rtems_unsigned32 s;
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
if (table == 0)
|
||||
{
|
||||
table = rtems_monitor_symbols;
|
||||
if (table == 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
|
||||
{
|
||||
if ( strcasecmp(sp->name, name) == 0 )
|
||||
return sp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
rtems_monitor_symbol_next(
|
||||
void *object_info,
|
||||
rtems_monitor_symbol_t *canonical,
|
||||
rtems_id *next_id
|
||||
)
|
||||
{
|
||||
rtems_symbol_table_t *table;
|
||||
rtems_unsigned32 n = rtems_get_index(*next_id);
|
||||
|
||||
table = *(rtems_symbol_table_t **) object_info;
|
||||
if (table == 0)
|
||||
goto failed;
|
||||
|
||||
if (n >= table->next)
|
||||
goto failed;
|
||||
|
||||
/* NOTE: symbols do not have id and name fields */
|
||||
|
||||
if (table->sorted == 0)
|
||||
rtems_symbol_sort(table);
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
*next_id += 1;
|
||||
return (void *) (table->addresses + n);
|
||||
|
||||
failed:
|
||||
*next_id = RTEMS_OBJECT_ID_FINAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_symbol_canonical(
|
||||
rtems_monitor_symbol_t *canonical_symbol,
|
||||
rtems_symbol_t *sp
|
||||
)
|
||||
{
|
||||
canonical_symbol->value = sp->value;
|
||||
canonical_symbol->offset = 0;
|
||||
strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_symbol_canonical_by_name(
|
||||
rtems_monitor_symbol_t *canonical_symbol,
|
||||
char *name
|
||||
)
|
||||
{
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
sp = rtems_symbol_name_lookup(0, name);
|
||||
|
||||
canonical_symbol->value = sp ? sp->value : 0;
|
||||
|
||||
strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name));
|
||||
canonical_symbol->offset = 0;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_monitor_symbol_canonical_by_value(
|
||||
rtems_monitor_symbol_t *canonical_symbol,
|
||||
void *value_void_p
|
||||
)
|
||||
{
|
||||
unsigned32 value = (unsigned32) value_void_p;
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
sp = rtems_symbol_value_lookup(0, value);
|
||||
if (sp)
|
||||
{
|
||||
canonical_symbol->value = sp->value;
|
||||
canonical_symbol->offset = value - sp->value;
|
||||
strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
|
||||
}
|
||||
else
|
||||
{
|
||||
canonical_symbol->value = value;
|
||||
canonical_symbol->offset = 0;
|
||||
canonical_symbol->name[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned32
|
||||
rtems_monitor_symbol_dump(
|
||||
rtems_monitor_symbol_t *canonical_symbol,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
unsigned32 length = 0;
|
||||
|
||||
/*
|
||||
* print the name if it exists AND if value is non-zero
|
||||
* Ie: don't print some garbage symbol for address 0
|
||||
*/
|
||||
|
||||
if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
|
||||
{
|
||||
if (canonical_symbol->offset == 0)
|
||||
length += printf("%.*s",
|
||||
(int) sizeof(canonical_symbol->name),
|
||||
canonical_symbol->name);
|
||||
else
|
||||
length += printf("<%.*s+0x%x>",
|
||||
(int) sizeof(canonical_symbol->name),
|
||||
canonical_symbol->name,
|
||||
canonical_symbol->offset);
|
||||
if (verbose)
|
||||
length += printf(" [0x%x]", canonical_symbol->value);
|
||||
}
|
||||
else
|
||||
length += printf("[0x%x]", canonical_symbol->value);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_symbol_dump_all(
|
||||
rtems_symbol_table_t *table,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
rtems_unsigned32 s;
|
||||
rtems_symbol_t *sp;
|
||||
|
||||
if (table == 0)
|
||||
{
|
||||
table = rtems_monitor_symbols;
|
||||
if (table == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (table->sorted == 0)
|
||||
rtems_symbol_sort(table);
|
||||
|
||||
for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
|
||||
{
|
||||
rtems_monitor_symbol_t canonical_symbol;
|
||||
|
||||
rtems_monitor_symbol_canonical(&canonical_symbol, sp);
|
||||
rtems_monitor_symbol_dump(&canonical_symbol, TRUE);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'symbol' command
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_symbol_cmd(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
int arg;
|
||||
rtems_symbol_table_t *table;
|
||||
|
||||
table = *(rtems_symbol_table_t **) command_arg;
|
||||
if (table == 0)
|
||||
{
|
||||
table = rtems_monitor_symbols;
|
||||
if (table == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Use object command to dump out whole symbol table
|
||||
*/
|
||||
if (argc == 1)
|
||||
rtems_monitor_symbol_dump_all(table, verbose);
|
||||
else
|
||||
{
|
||||
rtems_monitor_symbol_t canonical_symbol;
|
||||
|
||||
for (arg=1; argv[arg]; arg++)
|
||||
{
|
||||
rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
|
||||
rtems_monitor_symbol_dump(&canonical_symbol, verbose);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
/*
|
||||
* RTEMS Monitor task support
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/monitor.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memcpy() */
|
||||
|
||||
void
|
||||
rtems_monitor_task_canonical(
|
||||
rtems_monitor_task_t *canonical_task,
|
||||
void *thread_void
|
||||
)
|
||||
{
|
||||
Thread_Control *rtems_thread = (Thread_Control *) thread_void;
|
||||
RTEMS_API_Control *api;
|
||||
|
||||
api = rtems_thread->API_Extensions[ THREAD_API_RTEMS ];
|
||||
|
||||
canonical_task->entry = rtems_thread->Start.entry_point;
|
||||
canonical_task->argument = rtems_thread->Start.numeric_argument;
|
||||
canonical_task->stack = rtems_thread->Start.Initial_stack.area;
|
||||
canonical_task->stack_size = rtems_thread->Start.Initial_stack.size;
|
||||
canonical_task->priority = rtems_thread->current_priority;
|
||||
canonical_task->state = rtems_thread->current_state;
|
||||
canonical_task->wait_id = rtems_thread->Wait.id;
|
||||
canonical_task->events = api->pending_events;
|
||||
|
||||
/* XXX modes and attributes only exist in the RTEMS API .. */
|
||||
/* XXX not directly in the core thread.. they will have to be derived */
|
||||
/* XXX if they are important enough to include anymore. */
|
||||
canonical_task->modes = 0; /* XXX FIX ME.... rtems_thread->current_modes; */
|
||||
canonical_task->attributes = 0 /* XXX FIX ME rtems_thread->API_Extensions[ THREAD_API_RTEMS ]->attribute_set */;
|
||||
(void) memcpy(canonical_task->notepad, api ->Notepads, sizeof(canonical_task->notepad));
|
||||
/* XXX more to fix */
|
||||
/*
|
||||
(void) memcpy(&canonical_task->wait_args, &rtems_thread->Wait.Extra, sizeof(canonical_task->wait_args));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtems_monitor_task_dump_header(
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
printf("\
|
||||
ID NAME PRIO STAT MODES EVENTS WAITID WAITARG NOTES\n");
|
||||
/*23456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
|
||||
0 1 2 3 4 5 6 7 */
|
||||
|
||||
rtems_monitor_separator();
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
void
|
||||
rtems_monitor_task_dump(
|
||||
rtems_monitor_task_t *monitor_task,
|
||||
boolean verbose
|
||||
)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
length += rtems_monitor_dump_id(monitor_task->id);
|
||||
length += rtems_monitor_pad(11, length);
|
||||
length += rtems_monitor_dump_name(monitor_task->name);
|
||||
length += rtems_monitor_pad(18, length);
|
||||
length += rtems_monitor_dump_priority(monitor_task->priority);
|
||||
length += rtems_monitor_pad(24, length);
|
||||
length += rtems_monitor_dump_state(monitor_task->state);
|
||||
length += rtems_monitor_pad(31, length);
|
||||
length += rtems_monitor_dump_modes(monitor_task->modes);
|
||||
length += rtems_monitor_pad(39, length);
|
||||
length += rtems_monitor_dump_events(monitor_task->events);
|
||||
if (monitor_task->wait_id)
|
||||
{
|
||||
length += rtems_monitor_pad(47, length);
|
||||
length += rtems_monitor_dump_id(monitor_task->wait_id);
|
||||
length += rtems_monitor_pad(57, length);
|
||||
length += rtems_monitor_dump_hex(monitor_task->wait_args);
|
||||
}
|
||||
|
||||
length += rtems_monitor_pad(65, length);
|
||||
length += rtems_monitor_dump_notepad(monitor_task->notepad);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -1,449 +0,0 @@
|
||||
/*
|
||||
* File: monitor.h
|
||||
*
|
||||
* Description:
|
||||
* The RTEMS monitor task include file.
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __MONITOR_H
|
||||
#define __MONITOR_H
|
||||
|
||||
#include <rtems/symbols.h>
|
||||
#include <rtems/error.h> /* rtems_error() */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Monitor types are derived from rtems object classes
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
RTEMS_MONITOR_OBJECT_INVALID = OBJECTS_NO_CLASS,
|
||||
RTEMS_MONITOR_OBJECT_TASK = OBJECTS_RTEMS_TASKS,
|
||||
RTEMS_MONITOR_OBJECT_EXTENSION = OBJECTS_RTEMS_EXTENSIONS,
|
||||
RTEMS_MONITOR_OBJECT_QUEUE = OBJECTS_RTEMS_MESSAGE_QUEUES,
|
||||
RTEMS_MONITOR_OBJECT_SEMAPHORE = OBJECTS_RTEMS_SEMAPHORES,
|
||||
RTEMS_MONITOR_OBJECT_PARTITION = OBJECTS_RTEMS_PARTITIONS,
|
||||
RTEMS_MONITOR_OBJECT_REGION = OBJECTS_RTEMS_REGIONS,
|
||||
RTEMS_MONITOR_OBJECT_PORT = OBJECTS_RTEMS_PORTS,
|
||||
|
||||
/* following monitor objects are not known to RTEMS, but
|
||||
* we like to have "types" for them anyway */
|
||||
|
||||
RTEMS_MONITOR_OBJECT_DRIVER = OBJECTS_CLASSES_LAST+1,
|
||||
RTEMS_MONITOR_OBJECT_DNAME,
|
||||
RTEMS_MONITOR_OBJECT_CONFIG,
|
||||
RTEMS_MONITOR_OBJECT_INIT_TASK,
|
||||
RTEMS_MONITOR_OBJECT_MPCI,
|
||||
RTEMS_MONITOR_OBJECT_SYMBOL
|
||||
} rtems_monitor_object_type_t;
|
||||
|
||||
/*
|
||||
* rtems_monitor_init() flags
|
||||
*/
|
||||
|
||||
#define RTEMS_MONITOR_SUSPEND 0x0001 /* suspend monitor on startup */
|
||||
#define RTEMS_MONITOR_GLOBAL 0x0002 /* monitor should be global */
|
||||
|
||||
|
||||
/*
|
||||
* Public interfaces for RTEMS data structures monitor is aware of.
|
||||
* These are only used by the monitor.
|
||||
*
|
||||
* NOTE:
|
||||
* All the canonical objects that correspond to RTEMS managed "objects"
|
||||
* must have an identical first portion with 'id' and 'name' fields.
|
||||
*
|
||||
* Others do not have that restriction, even tho we would like them to.
|
||||
* This is because some of the canonical structures are almost too big
|
||||
* for shared memory driver (eg: mpci) and we are nickel and diming it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Type of a pointer that may be a symbol
|
||||
*/
|
||||
|
||||
#define MONITOR_SYMBOL_LEN 20
|
||||
typedef struct {
|
||||
char name[MONITOR_SYMBOL_LEN];
|
||||
unsigned32 value;
|
||||
unsigned32 offset;
|
||||
} rtems_monitor_symbol_t;
|
||||
|
||||
typedef struct {
|
||||
rtems_id id;
|
||||
rtems_name name;
|
||||
/* end of common portion */
|
||||
} rtems_monitor_generic_t;
|
||||
|
||||
/*
|
||||
* Task
|
||||
*/
|
||||
typedef struct {
|
||||
rtems_id id;
|
||||
rtems_name name;
|
||||
/* end of common portion */
|
||||
Thread_Entry entry;
|
||||
unsigned32 argument;
|
||||
void *stack;
|
||||
unsigned32 stack_size;
|
||||
rtems_task_priority priority;
|
||||
States_Control state;
|
||||
rtems_event_set events;
|
||||
rtems_mode modes;
|
||||
rtems_attribute attributes;
|
||||
unsigned32 notepad[RTEMS_NUMBER_NOTEPADS];
|
||||
rtems_id wait_id;
|
||||
unsigned32 wait_args;
|
||||
} rtems_monitor_task_t;
|
||||
|
||||
/*
|
||||
* Init task
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
rtems_id id; /* not really an id */
|
||||
rtems_name name;
|
||||
/* end of common portion */
|
||||
rtems_monitor_symbol_t entry;
|
||||
unsigned32 argument;
|
||||
unsigned32 stack_size;
|
||||
rtems_task_priority priority;
|
||||
rtems_mode modes;
|
||||
rtems_attribute attributes;
|
||||
} rtems_monitor_init_task_t;
|
||||
|
||||
|
||||
/*
|
||||
* Message queue
|
||||
*/
|
||||
typedef struct {
|
||||
rtems_id id;
|
||||
rtems_name name;
|
||||
/* end of common portion */
|
||||
rtems_attribute attributes;
|
||||
unsigned32 number_of_pending_messages;
|
||||
unsigned32 maximum_pending_messages;
|
||||
unsigned32 maximum_message_size;
|
||||
} rtems_monitor_queue_t;
|
||||
|
||||
/*
|
||||
* Extension
|
||||
*/
|
||||
typedef struct {
|
||||
rtems_id id;
|
||||
rtems_name name;
|
||||
/* end of common portion */
|
||||
rtems_monitor_symbol_t e_create;
|
||||
rtems_monitor_symbol_t e_start;
|
||||
rtems_monitor_symbol_t e_restart;
|
||||
rtems_monitor_symbol_t e_delete;
|
||||
rtems_monitor_symbol_t e_tswitch;
|
||||
rtems_monitor_symbol_t e_begin;
|
||||
rtems_monitor_symbol_t e_exitted;
|
||||
rtems_monitor_symbol_t e_fatal;
|
||||
} rtems_monitor_extension_t;
|
||||
|
||||
/*
|
||||
* Device driver
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
rtems_id id; /* not really an id (should be tho) */
|
||||
rtems_name name; /* ditto */
|
||||
/* end of common portion */
|
||||
rtems_monitor_symbol_t initialization; /* initialization procedure */
|
||||
rtems_monitor_symbol_t open; /* open request procedure */
|
||||
rtems_monitor_symbol_t close; /* close request procedure */
|
||||
rtems_monitor_symbol_t read; /* read request procedure */
|
||||
rtems_monitor_symbol_t write; /* write request procedure */
|
||||
rtems_monitor_symbol_t control; /* special functions procedure */
|
||||
} rtems_monitor_driver_t;
|
||||
|
||||
typedef struct {
|
||||
rtems_id id; /* not used for drivers (yet) */
|
||||
rtems_name name; /* not used for drivers (yet) */
|
||||
/* end of common portion */
|
||||
unsigned32 major;
|
||||
unsigned32 minor;
|
||||
char name_string[64];
|
||||
} rtems_monitor_dname_t;
|
||||
|
||||
/*
|
||||
* System config
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
void *work_space_start;
|
||||
unsigned32 work_space_size;
|
||||
unsigned32 maximum_tasks;
|
||||
unsigned32 maximum_timers;
|
||||
unsigned32 maximum_semaphores;
|
||||
unsigned32 maximum_message_queues;
|
||||
unsigned32 maximum_partitions;
|
||||
unsigned32 maximum_regions;
|
||||
unsigned32 maximum_ports;
|
||||
unsigned32 maximum_periods;
|
||||
unsigned32 maximum_extensions;
|
||||
unsigned32 microseconds_per_tick;
|
||||
unsigned32 ticks_per_timeslice;
|
||||
unsigned32 number_of_initialization_tasks;
|
||||
} rtems_monitor_config_t;
|
||||
|
||||
/*
|
||||
* MPCI config
|
||||
*/
|
||||
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
typedef struct {
|
||||
unsigned32 node; /* local node number */
|
||||
unsigned32 maximum_nodes; /* maximum # nodes in system */
|
||||
unsigned32 maximum_global_objects; /* maximum # global objects */
|
||||
unsigned32 maximum_proxies; /* maximum # proxies */
|
||||
|
||||
unsigned32 default_timeout; /* in ticks */
|
||||
unsigned32 maximum_packet_size;
|
||||
rtems_monitor_symbol_t initialization;
|
||||
rtems_monitor_symbol_t get_packet;
|
||||
rtems_monitor_symbol_t return_packet;
|
||||
rtems_monitor_symbol_t send_packet;
|
||||
rtems_monitor_symbol_t receive_packet;
|
||||
} rtems_monitor_mpci_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The generic canonical information union
|
||||
*/
|
||||
|
||||
typedef union {
|
||||
rtems_monitor_generic_t generic;
|
||||
rtems_monitor_task_t task;
|
||||
rtems_monitor_queue_t queue;
|
||||
rtems_monitor_extension_t extension;
|
||||
rtems_monitor_driver_t driver;
|
||||
rtems_monitor_dname_t dname;
|
||||
rtems_monitor_config_t config;
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
rtems_monitor_mpci_t mpci;
|
||||
#endif
|
||||
rtems_monitor_init_task_t itask;
|
||||
} rtems_monitor_union_t;
|
||||
|
||||
/*
|
||||
* Support for talking to other monitors
|
||||
*/
|
||||
|
||||
/*
|
||||
* Names of other monitors
|
||||
*/
|
||||
|
||||
#define RTEMS_MONITOR_NAME (rtems_build_name('R', 'M', 'O', 'N'))
|
||||
#define RTEMS_MONITOR_SERVER_NAME (rtems_build_name('R', 'M', 'S', 'V'))
|
||||
#define RTEMS_MONITOR_QUEUE_NAME (rtems_build_name('R', 'M', 'S', 'Q'))
|
||||
#define RTEMS_MONITOR_RESPONSE_QUEUE_NAME (rtems_build_name('R', 'M', 'R', 'Q'))
|
||||
|
||||
#define RTEMS_MONITOR_SERVER_RESPONSE 0x0001
|
||||
#define RTEMS_MONITOR_SERVER_CANONICAL 0x0002
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned32 command;
|
||||
rtems_id return_id;
|
||||
unsigned32 argument0;
|
||||
unsigned32 argument1;
|
||||
unsigned32 argument2;
|
||||
unsigned32 argument3;
|
||||
unsigned32 argument4;
|
||||
unsigned32 argument5;
|
||||
} rtems_monitor_server_request_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned32 command;
|
||||
unsigned32 result0;
|
||||
unsigned32 result1;
|
||||
rtems_monitor_union_t payload;
|
||||
} rtems_monitor_server_response_t;
|
||||
|
||||
extern rtems_id rtems_monitor_task_id;
|
||||
|
||||
extern unsigned32 rtems_monitor_node; /* our node number */
|
||||
extern unsigned32 rtems_monitor_default_node; /* current default for commands */
|
||||
|
||||
/*
|
||||
* Monitor command function and table entry
|
||||
*/
|
||||
|
||||
typedef struct rtems_monitor_command_entry_s rtems_monitor_command_entry_t;
|
||||
|
||||
typedef void ( *rtems_monitor_command_function_t )(
|
||||
int argc,
|
||||
char **argv,
|
||||
unsigned32 command_arg,
|
||||
boolean verbose
|
||||
);
|
||||
|
||||
struct rtems_monitor_command_entry_s {
|
||||
char *command; /* command name */
|
||||
char *usage; /* usage string for the command */
|
||||
unsigned32 arguments_required; /* # of required args */
|
||||
rtems_monitor_command_function_t command_function;
|
||||
|
||||
/* Some argument for the command */
|
||||
unsigned32 command_arg;
|
||||
};
|
||||
|
||||
typedef void *(*rtems_monitor_object_next_fn)(void *, void *, rtems_id *);
|
||||
typedef void (*rtems_monitor_object_canonical_fn)(void *, void *);
|
||||
typedef void (*rtems_monitor_object_dump_header_fn)(boolean);
|
||||
typedef void (*rtems_monitor_object_dump_fn)(void *, boolean);
|
||||
|
||||
typedef struct {
|
||||
rtems_monitor_object_type_t type;
|
||||
void *object_information;
|
||||
int size; /* of canonical object */
|
||||
rtems_monitor_object_next_fn next;
|
||||
rtems_monitor_object_canonical_fn canonical;
|
||||
rtems_monitor_object_dump_header_fn dump_header;
|
||||
rtems_monitor_object_dump_fn dump;
|
||||
} rtems_monitor_object_info_t;
|
||||
|
||||
|
||||
/* monitor.c */
|
||||
void rtems_monitor_kill(void);
|
||||
void rtems_monitor_init(unsigned32);
|
||||
void rtems_monitor_wakeup(void);
|
||||
void rtems_monitor_pause_cmd(int, char **, unsigned32, boolean);
|
||||
void rtems_monitor_fatal_cmd(int, char **, unsigned32, boolean);
|
||||
void rtems_monitor_continue_cmd(int, char **, unsigned32, boolean);
|
||||
void rtems_monitor_debugger_cmd(int, char **, unsigned32, boolean);
|
||||
void rtems_monitor_node_cmd(int, char **, unsigned32, boolean);
|
||||
void rtems_monitor_symbols_loadup(void);
|
||||
void rtems_monitor_task(rtems_task_argument);
|
||||
|
||||
/* server.c */
|
||||
void rtems_monitor_server_kill(void);
|
||||
rtems_status_code rtems_monitor_server_request(unsigned32, rtems_monitor_server_request_t *, rtems_monitor_server_response_t *);
|
||||
void rtems_monitor_server_task(rtems_task_argument);
|
||||
void rtems_monitor_server_init(unsigned32);
|
||||
|
||||
/* command.c */
|
||||
int rtems_monitor_make_argv(char *, int *, char **);
|
||||
int rtems_monitor_command_read(char *, int *, char **);
|
||||
rtems_monitor_command_entry_t *rtems_monitor_command_lookup(
|
||||
rtems_monitor_command_entry_t * table, int argc, char **argv);
|
||||
void rtems_monitor_command_usage(rtems_monitor_command_entry_t *, char *);
|
||||
void rtems_monitor_help_cmd(int, char **, unsigned32, boolean);
|
||||
|
||||
/* prmisc.c */
|
||||
void rtems_monitor_separator(void);
|
||||
unsigned32 rtems_monitor_pad(unsigned32 dest_col, unsigned32 curr_col);
|
||||
unsigned32 rtems_monitor_dump_char(unsigned8 ch);
|
||||
unsigned32 rtems_monitor_dump_decimal(unsigned32 num);
|
||||
unsigned32 rtems_monitor_dump_hex(unsigned32 num);
|
||||
unsigned32 rtems_monitor_dump_id(rtems_id id);
|
||||
unsigned32 rtems_monitor_dump_name(rtems_name name);
|
||||
unsigned32 rtems_monitor_dump_priority(rtems_task_priority priority);
|
||||
unsigned32 rtems_monitor_dump_state(States_Control state);
|
||||
unsigned32 rtems_monitor_dump_modes(rtems_mode modes);
|
||||
unsigned32 rtems_monitor_dump_attributes(rtems_attribute attributes);
|
||||
unsigned32 rtems_monitor_dump_events(rtems_event_set events);
|
||||
unsigned32 rtems_monitor_dump_notepad(unsigned32 *notepad);
|
||||
|
||||
/* object.c */
|
||||
rtems_id rtems_monitor_id_fixup(rtems_id, unsigned32, rtems_monitor_object_type_t);
|
||||
rtems_id rtems_monitor_object_canonical_get(rtems_monitor_object_type_t, rtems_id, void *, unsigned32 *size_p);
|
||||
rtems_id rtems_monitor_object_canonical_next(rtems_monitor_object_info_t *, rtems_id, void *);
|
||||
void *rtems_monitor_object_next(void *, void *, rtems_id, rtems_id *);
|
||||
rtems_id rtems_monitor_object_canonical(rtems_id, void *);
|
||||
void rtems_monitor_object_cmd(int, char **, unsigned32, boolean);
|
||||
|
||||
/* manager.c */
|
||||
void *rtems_monitor_manager_next(void *, void *, rtems_id *);
|
||||
|
||||
/* config.c */
|
||||
void rtems_monitor_config_canonical(rtems_monitor_config_t *, void *);
|
||||
void *rtems_monitor_config_next(void *, rtems_monitor_config_t *, rtems_id *);
|
||||
void rtems_monitor_config_dump_header(boolean);
|
||||
void rtems_monitor_config_dump(rtems_monitor_config_t *, boolean verbose);
|
||||
|
||||
/* mpci.c */
|
||||
#if defined(RTEMS_MULTIPROCESSING)
|
||||
void rtems_monitor_mpci_canonical(rtems_monitor_mpci_t *, void *);
|
||||
void *rtems_monitor_mpci_next(void *, rtems_monitor_mpci_t *, rtems_id *);
|
||||
void rtems_monitor_mpci_dump_header(boolean);
|
||||
void rtems_monitor_mpci_dump(rtems_monitor_mpci_t *, boolean verbose);
|
||||
#endif
|
||||
|
||||
/* itask.c */
|
||||
void rtems_monitor_init_task_canonical(rtems_monitor_init_task_t *, void *);
|
||||
void *rtems_monitor_init_task_next(void *, rtems_monitor_init_task_t *, rtems_id *);
|
||||
void rtems_monitor_init_task_dump_header(boolean);
|
||||
void rtems_monitor_init_task_dump(rtems_monitor_init_task_t *, boolean verbose);
|
||||
|
||||
/* extension.c */
|
||||
void rtems_monitor_extension_canonical(rtems_monitor_extension_t *, void *);
|
||||
void rtems_monitor_extension_dump_header(boolean verbose);
|
||||
void rtems_monitor_extension_dump(rtems_monitor_extension_t *, boolean);
|
||||
|
||||
/* task.c */
|
||||
void rtems_monitor_task_canonical(rtems_monitor_task_t *, void *);
|
||||
void rtems_monitor_task_dump_header(boolean verbose);
|
||||
void rtems_monitor_task_dump(rtems_monitor_task_t *, boolean);
|
||||
|
||||
/* queue.c */
|
||||
void rtems_monitor_queue_canonical(rtems_monitor_queue_t *, void *);
|
||||
void rtems_monitor_queue_dump_header(boolean verbose);
|
||||
void rtems_monitor_queue_dump(rtems_monitor_queue_t *, boolean);
|
||||
|
||||
/* driver.c */
|
||||
void *rtems_monitor_driver_next(void *, rtems_monitor_driver_t *, rtems_id *);
|
||||
void rtems_monitor_driver_canonical(rtems_monitor_driver_t *, void *);
|
||||
void rtems_monitor_driver_dump_header(boolean);
|
||||
void rtems_monitor_driver_dump(rtems_monitor_driver_t *, boolean);
|
||||
|
||||
/* dname.c */
|
||||
void *rtems_monitor_dname_next(void *, rtems_monitor_dname_t *, rtems_id *);
|
||||
void rtems_monitor_dname_canonical(rtems_monitor_dname_t *, void *);
|
||||
void rtems_monitor_dname_dump_header(boolean);
|
||||
void rtems_monitor_dname_dump(rtems_monitor_dname_t *, boolean);
|
||||
|
||||
/* symbols.c */
|
||||
rtems_symbol_table_t *rtems_symbol_table_create();
|
||||
void rtems_symbol_table_destroy(rtems_symbol_table_t *table);
|
||||
|
||||
rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, char *, unsigned32);
|
||||
rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, unsigned32);
|
||||
const rtems_symbol_t *rtems_symbol_value_lookup_exact(rtems_symbol_table_t *, unsigned32);
|
||||
rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, char *);
|
||||
void *rtems_monitor_symbol_next(void *object_info, rtems_monitor_symbol_t *, rtems_id *);
|
||||
void rtems_monitor_symbol_canonical(rtems_monitor_symbol_t *, rtems_symbol_t *);
|
||||
void rtems_monitor_symbol_canonical_by_name(rtems_monitor_symbol_t *, char *);
|
||||
void rtems_monitor_symbol_canonical_by_value(rtems_monitor_symbol_t *, void *);
|
||||
unsigned32 rtems_monitor_symbol_dump(rtems_monitor_symbol_t *, boolean);
|
||||
void rtems_monitor_symbol_cmd(int, char **, unsigned32, boolean);
|
||||
|
||||
|
||||
extern rtems_symbol_table_t *rtems_monitor_symbols;
|
||||
|
||||
#ifndef MONITOR_PROMPT
|
||||
#define MONITOR_PROMPT "rtems" /* will have '> ' appended */
|
||||
#endif
|
||||
|
||||
#define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0
|
||||
|
||||
|
||||
#define STREQ(a,b) (strcmp(a,b) == 0)
|
||||
#define STRNEQ(a,b,n) (strncmp(a,b,n) == 0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! __MONITOR_H */
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* RTEMS monitor symbol table functions
|
||||
*
|
||||
* Description:
|
||||
* Entry points for symbol table routines.
|
||||
*
|
||||
*
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SYMBOLS_H
|
||||
#define _INCLUDE_SYMBOLS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
rtems_unsigned32 value;
|
||||
char *name;
|
||||
} rtems_symbol_t;
|
||||
|
||||
#define SYMBOL_STRING_BLOCK_SIZE 4080
|
||||
typedef struct rtems_symbol_string_block_s {
|
||||
struct rtems_symbol_string_block_s *next;
|
||||
char buffer[SYMBOL_STRING_BLOCK_SIZE];
|
||||
} rtems_symbol_string_block_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
rtems_unsigned32 sorted; /* are symbols sorted right now? */
|
||||
rtems_unsigned32 growth_factor; /* % to grow by when needed */
|
||||
rtems_unsigned32 next; /* next symbol slot to use when adding */
|
||||
rtems_unsigned32 size; /* max # of symbols */
|
||||
|
||||
/*
|
||||
* Symbol list -- sorted by address (when we do a lookup)
|
||||
*/
|
||||
|
||||
rtems_symbol_t *addresses; /* symbol array by address */
|
||||
|
||||
/*
|
||||
* String pool, unsorted, a list of blocks of string data
|
||||
*/
|
||||
|
||||
rtems_symbol_string_block_t *string_buffer_head;
|
||||
rtems_symbol_string_block_t *string_buffer_current;
|
||||
rtems_unsigned32 strings_next; /* next byte to use in this block */
|
||||
|
||||
} rtems_symbol_table_t;
|
||||
|
||||
#define rtems_symbol_name(sp) ((sp)->name)
|
||||
#define rtems_symbol_value(sp) ((sp)->value)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ! _INCLUDE_SYMBOLS_H */
|
||||
@@ -1,72 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = rtmonuse
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
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_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
#
|
||||
# (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} preinstall ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
all: ${ARCH} $(SRCS) preinstall $(LIB)
|
||||
|
||||
preinstall:
|
||||
@$(INSTALL_CHANGE) -m 644 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <rtems/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];
|
||||
|
||||
if ( !Period_usage_Information ) {
|
||||
printf( "Period statistics library is not initialized\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* $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
|
||||
@@ -1,72 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = stackchk
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
LIB = ${ARCH}/libstackchk-tmp.a
|
||||
|
||||
# C source names, if any, go here -- minus the .c
|
||||
C_PIECES = check
|
||||
C_FILES = $(C_PIECES:%=%.c)
|
||||
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
|
||||
|
||||
H_FILES = internal.h
|
||||
INSTALLED_H_FILES = $(srcdir)/stackchk.h
|
||||
|
||||
SRCS = $(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
#
|
||||
# (OPTIONAL) Add local stuff here using +=
|
||||
#
|
||||
|
||||
DEFINES +=
|
||||
CPPFLAGS +=
|
||||
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} preinstall ${OBJS}
|
||||
$(make-library)
|
||||
|
||||
all: ${ARCH} $(SRCS) $(LIB)
|
||||
|
||||
preinstall:
|
||||
@$(INSTALL_CHANGE) -m 644 $(INSTALLED_H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,56 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
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
|
||||
|
||||
Enabling
|
||||
========
|
||||
|
||||
Add the stack checker extension to the initial user extension set.
|
||||
If using confdefs.h to build your configuration table, this is
|
||||
as simple as adding -DSTACK_CHECK_ON to the gcc command line which
|
||||
compiles the file defining the configuration table. In the RTEMS
|
||||
test suites and samples, this is always init.c
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
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.
|
||||
@@ -1,535 +0,0 @@
|
||||
/*
|
||||
* 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-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
/*
|
||||
* HACK
|
||||
* the stack dump information should be printed by a "fatal" extension.
|
||||
* Fatal extensions only get called via rtems_fatal_error_occurred()
|
||||
* and not when rtems_shutdown_executive() is called.
|
||||
* I hope/think this is changing so that fatal extensions are renamed
|
||||
* to "shutdown" extensions.
|
||||
* When that happens, this #define should be deleted and all the code
|
||||
* it marks.
|
||||
*/
|
||||
#define DONT_USE_FATAL_EXTENSION
|
||||
|
||||
|
||||
extern rtems_configuration_table BSP_Configuration;
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rtems/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 */
|
||||
#ifdef DONT_USE_FATAL_EXTENSION
|
||||
0, /* fatal */
|
||||
#else
|
||||
Stack_check_Fatal_extension, /* fatal */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* The "magic pattern" used to mark the end of the stack.
|
||||
*/
|
||||
|
||||
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_area( _the_stack ) \
|
||||
((Stack_check_Control *) ((char *)(_the_stack)->area + \
|
||||
(_the_stack)->size - sizeof( Stack_check_Control ) ))
|
||||
|
||||
#define Stack_check_Calculate_used( _low, _size, _high_water ) \
|
||||
((char *)(_high_water) - (char *)(_low))
|
||||
|
||||
#define Stack_check_usable_stack_start(_the_stack) \
|
||||
((_the_stack)->area)
|
||||
|
||||
#else
|
||||
|
||||
#define Stack_check_Get_pattern_area( _the_stack ) \
|
||||
((Stack_check_Control *) ((char *)(_the_stack)->area + HEAP_OVERHEAD))
|
||||
|
||||
#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 + sizeof(Stack_check_Control))
|
||||
|
||||
#endif
|
||||
|
||||
#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;
|
||||
|
||||
/*
|
||||
* Prototypes necessary for forward references
|
||||
*/
|
||||
|
||||
void Stack_check_Dump_usage( void );
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
{
|
||||
#if 0
|
||||
rtems_status_code status;
|
||||
Objects_Id id_ignored;
|
||||
#endif
|
||||
unsigned32 *p;
|
||||
#if 0
|
||||
unsigned32 i;
|
||||
unsigned32 class_index;
|
||||
Thread_Control *the_thread;
|
||||
Objects_Information *information;
|
||||
#endif
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#if 0
|
||||
status = rtems_extension_create(
|
||||
rtems_build_name( 'S', 'T', 'C', 'K' ),
|
||||
&Stack_check_Extension_table,
|
||||
&id_ignored
|
||||
);
|
||||
assert ( status == RTEMS_SUCCESSFUL );
|
||||
#endif
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/* XXX
|
||||
*
|
||||
* Technically this has not been done for any task created before this
|
||||
* happened. So just run through them and fix the situation.
|
||||
*/
|
||||
#if 0
|
||||
if (_Thread_Executing)
|
||||
{
|
||||
Stack_check_Create_extension(_Thread_Executing, _Thread_Executing);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 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 ];
|
||||
Stack_check_Create_extension( the_thread, the_thread );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 = (char *) _CPU_Interrupt_stack_high -
|
||||
(char *) _CPU_Interrupt_stack_low;
|
||||
|
||||
stack_check_dope_stack(&stack_check_interrupt_stack);
|
||||
}
|
||||
|
||||
#ifdef DONT_USE_FATAL_EXTENSION
|
||||
#ifdef RTEMS_DEBUG
|
||||
/*
|
||||
* this would normally be called by a fatal extension
|
||||
* handler, but we don't run fatal extensions unless
|
||||
* we fatal error.
|
||||
*/
|
||||
atexit(Stack_check_Dump_usage);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
stack_check_initialized = 1;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* Stack_check_Create_extension
|
||||
*/
|
||||
|
||||
boolean Stack_check_Create_extension(
|
||||
Thread_Control *running,
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
if (!stack_check_initialized)
|
||||
Stack_check_Initialize();
|
||||
|
||||
if (the_thread /* XXX && (the_thread != _Thread_Executing) */ )
|
||||
stack_check_dope_stack(&the_thread->Start.Initial_stack);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* Stack_check_Begin_extension
|
||||
*/
|
||||
|
||||
void Stack_check_Begin_extension(
|
||||
Thread_Control *the_thread
|
||||
)
|
||||
{
|
||||
Stack_check_Control *the_pattern;
|
||||
|
||||
if (!stack_check_initialized)
|
||||
Stack_check_Initialize();
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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,
|
||||
*(unsigned32 *)running->Object.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
|
||||
)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void *Stack_check_find_high_water_mark(
|
||||
const void *s,
|
||||
size_t n
|
||||
)
|
||||
{
|
||||
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 (*base != U32_PATTERN)
|
||||
return (void *) base;
|
||||
#else
|
||||
/*
|
||||
* start at lower memory and find first word that does not
|
||||
* match pattern
|
||||
*/
|
||||
|
||||
base += PATTERN_SIZE_WORDS;
|
||||
for (ebase = base + length; base < ebase; base++)
|
||||
if (*base != U32_PATTERN)
|
||||
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
|
||||
)
|
||||
{
|
||||
unsigned32 size, used;
|
||||
void *low;
|
||||
void *high_water_mark;
|
||||
Stack_Control *stack;
|
||||
unsigned32 u32_name;
|
||||
char name[5];
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
if ( the_thread )
|
||||
u32_name = *(unsigned32 *)the_thread->Object.name;
|
||||
else
|
||||
u32_name = rtems_build_name('I', 'N', 'T', 'R');
|
||||
|
||||
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 0x%08x 0x%08x %8d %8d\n",
|
||||
the_thread ? the_thread->Object.id : ~0,
|
||||
name,
|
||||
(unsigned32) stack->area,
|
||||
(unsigned32) stack->area + (unsigned32) stack->size - 1,
|
||||
size,
|
||||
used
|
||||
);
|
||||
}
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* Stack_check_Fatal_extension
|
||||
*/
|
||||
|
||||
void Stack_check_Fatal_extension(
|
||||
Internal_errors_Source source,
|
||||
boolean is_internal,
|
||||
unsigned32 status
|
||||
)
|
||||
{
|
||||
#ifndef DONT_USE_FATAL_EXTENSION
|
||||
if (status == 0)
|
||||
Stack_check_Dump_usage();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*PAGE
|
||||
*
|
||||
* Stack_check_Dump_usage
|
||||
*/
|
||||
|
||||
void Stack_check_Dump_usage( void )
|
||||
{
|
||||
unsigned32 i;
|
||||
unsigned32 class_index;
|
||||
Thread_Control *the_thread;
|
||||
unsigned32 hit_running = 0;
|
||||
Objects_Information *information;
|
||||
|
||||
if (stack_check_initialized == 0)
|
||||
return;
|
||||
|
||||
printf("Stack usage by thread\n");
|
||||
printf(
|
||||
" ID NAME LOW HIGH AVAILABLE USED\n"
|
||||
);
|
||||
|
||||
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 ];
|
||||
Stack_check_Dump_threads_usage( the_thread );
|
||||
if ( the_thread == _Thread_Executing )
|
||||
hit_running = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !hit_running )
|
||||
Stack_check_Dump_threads_usage( _Thread_Executing );
|
||||
|
||||
/* dump interrupt stack info if any */
|
||||
Stack_check_Dump_threads_usage((Thread_Control *) -1);
|
||||
}
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
/* internal.h
|
||||
*
|
||||
* This include file contains internal information
|
||||
* for the RTEMS stack checker.
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#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 */
|
||||
@@ -1,83 +0,0 @@
|
||||
/* stackchk.h
|
||||
*
|
||||
* This include file contains information necessary to utilize
|
||||
* and install the stack checker mechanism.
|
||||
*
|
||||
* COPYRIGHT (c) 1989-1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __STACK_CHECK_h
|
||||
#define __STACK_CHECK_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Stack_check_Initialize
|
||||
*/
|
||||
|
||||
void Stack_check_Initialize( void );
|
||||
|
||||
/*
|
||||
* Stack_check_Dump_usage
|
||||
*/
|
||||
|
||||
void Stack_check_Dump_usage( void );
|
||||
|
||||
/*
|
||||
* 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
|
||||
);
|
||||
|
||||
/*
|
||||
* Extension set definition
|
||||
*/
|
||||
|
||||
#define STACK_CHECKER_EXTENSION \
|
||||
{ \
|
||||
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 */ \
|
||||
0 /* Stack_check_Fatal_extension */, /* fatal */ \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* end of include file */
|
||||
@@ -1,69 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = untar
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
LIB = ${ARCH}/libuntar-tmp.a
|
||||
|
||||
# C source names, if any, go here -- minus the .c
|
||||
C_PIECES = untar
|
||||
C_FILES = $(C_PIECES:%=%.c)
|
||||
C_O_FILES = $(C_PIECES:%=${ARCH}/%.o)
|
||||
|
||||
H_FILES = $(srcdir)/untar.h
|
||||
|
||||
SRCS = $(C_FILES) $(H_FILES) $(INSTALLED_H_FILES)
|
||||
OBJS = $(C_O_FILES)
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/@RTEMS_TOPdir@/mkinstalldirs
|
||||
|
||||
INSTALLDIRS = $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
$(INSTALLDIRS):
|
||||
@$(mkinstalldirs) $(INSTALLDIRS)
|
||||
|
||||
#
|
||||
# (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_CHANGE) -m 644 $(H_FILES) $(PROJECT_INCLUDE)/rtems
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
@@ -1,26 +0,0 @@
|
||||
#
|
||||
#
|
||||
# untar information
|
||||
#
|
||||
# Author: Jake Janovetz 7.6.1999
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
untar.c contains two procedures for extracting files from a UNIX
|
||||
tar file:
|
||||
|
||||
int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
|
||||
int Untar_FromFile(char *tar_name);
|
||||
|
||||
Untar_FromMemory(...) takes its input from a chunk of allocated memory.
|
||||
This is particularly useful when the tar is stored in Flash memory or
|
||||
comes from the FTP daemon by way of a hook.
|
||||
|
||||
Untar_FromFile(...) is identical except the source is from an existing
|
||||
file. The fully qualified filename is passed through char *tar_name.
|
||||
|
||||
|
||||
|
||||
BUGS: Please email janovetz@uiuc.edu
|
||||
-----
|
||||
@@ -1,382 +0,0 @@
|
||||
/* FIXME:
|
||||
* 1. Symbolic links are not created.
|
||||
* 2. Untar_FromMemory has printfs.
|
||||
* 3. Untar_FromMemory uses FILE *fp.
|
||||
* 4. How to determine end of archive?
|
||||
*
|
||||
* Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "untar.h"
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* TAR file format:
|
||||
*
|
||||
* Offset Length Contents
|
||||
* 0 100 bytes File name ('\0' terminated, 99 maxmum length)
|
||||
* 100 8 bytes File mode (in octal ascii)
|
||||
* 108 8 bytes User ID (in octal ascii)
|
||||
* 116 8 bytes Group ID (in octal ascii)
|
||||
* 124 12 bytes File size (s) (in octal ascii)
|
||||
* 136 12 bytes Modify time (in octal ascii)
|
||||
* 148 8 bytes Header checksum (in octal ascii)
|
||||
* 156 1 bytes Link flag
|
||||
* 157 100 bytes Linkname ('\0' terminated, 99 maxmum length)
|
||||
* 257 8 bytes Magic ("ustar \0")
|
||||
* 265 32 bytes User name ('\0' terminated, 31 maxmum length)
|
||||
* 297 32 bytes Group name ('\0' terminated, 31 maxmum length)
|
||||
* 329 8 bytes Major device ID (in octal ascii)
|
||||
* 337 8 bytes Minor device ID (in octal ascii)
|
||||
* 345 167 bytes Padding
|
||||
* 512 (s+p)bytes File contents (s+p) := (((s) + 511) & ~511),
|
||||
* round up to 512 bytes
|
||||
*
|
||||
* Checksum:
|
||||
* int i, sum;
|
||||
* char* header = tar_header_pointer;
|
||||
* sum = 0;
|
||||
* for(i = 0; i < 512; i++)
|
||||
* sum += 0xFF & header[i];
|
||||
*************************************************************************/
|
||||
|
||||
#define LF_OLDNORMAL '\0' /* Normal disk file, Unix compatible */
|
||||
#define LF_NORMAL '0' /* Normal disk file */
|
||||
#define LF_LINK '1' /* Link to previously dumped file */
|
||||
#define LF_SYMLINK '2' /* Symbolic link */
|
||||
#define LF_CHR '3' /* Character special file */
|
||||
#define LF_BLK '4' /* Block special file */
|
||||
#define LF_DIR '5' /* Directory */
|
||||
#define LF_FIFO '6' /* FIFO special file */
|
||||
#define LF_CONFIG '7' /* Contiguous file */
|
||||
|
||||
#define MAX_NAME_FIELD_SIZE 99
|
||||
|
||||
#define MIN(a,b) ((a)>(b)?(b):(a))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* This converts octal ASCII number representations into an
|
||||
* unsigned long. Only support 32-bit numbers for now.
|
||||
*************************************************************************/
|
||||
static unsigned long
|
||||
octal2ulong(char *octascii, int len)
|
||||
{
|
||||
int i;
|
||||
unsigned long num;
|
||||
unsigned long mult;
|
||||
|
||||
num = 0;
|
||||
mult = 1;
|
||||
for (i=len-1; i>=0; i--)
|
||||
{
|
||||
if ((octascii[i] < '0') || (octascii[i] > '9'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
num += mult*((unsigned long)(octascii[i] - '0'));
|
||||
mult *= 8;
|
||||
}
|
||||
return(num);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Function: Untar_FromMemory *
|
||||
**************************************************************************
|
||||
* Description: *
|
||||
* *
|
||||
* This is a simple subroutine used to rip links, directories, and *
|
||||
* files out of a block of memory. *
|
||||
* *
|
||||
* *
|
||||
* Inputs: *
|
||||
* *
|
||||
* unsigned char *tar_buf - Pointer to TAR buffer. *
|
||||
* unsigned long size - Length of TAR buffer. *
|
||||
* *
|
||||
* *
|
||||
* Output: *
|
||||
* *
|
||||
* int - UNTAR_SUCCESSFUL (0) on successful completion. *
|
||||
* UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
|
||||
* UNTAR_INVALID_HEADER for an invalid header. *
|
||||
* *
|
||||
**************************************************************************
|
||||
* Change History: *
|
||||
* 12/30/1998 - Creation (JWJ) *
|
||||
*************************************************************************/
|
||||
int
|
||||
Untar_FromMemory(unsigned char *tar_buf, unsigned long size)
|
||||
{
|
||||
FILE *fp;
|
||||
char *bufr;
|
||||
size_t n;
|
||||
char fname[100];
|
||||
char linkname[100];
|
||||
int sum;
|
||||
int hdr_chksum;
|
||||
int retval;
|
||||
unsigned long ptr;
|
||||
unsigned long i;
|
||||
unsigned long nblocks;
|
||||
unsigned long file_size;
|
||||
unsigned char linkflag;
|
||||
|
||||
|
||||
ptr = 0;
|
||||
while (1)
|
||||
{
|
||||
if (ptr + 512 > size)
|
||||
{
|
||||
retval = UNTAR_SUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the header */
|
||||
bufr = &tar_buf[ptr];
|
||||
ptr += 512;
|
||||
if (strncmp(&bufr[257], "ustar ", 7))
|
||||
{
|
||||
retval = UNTAR_SUCCESSFUL;
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
|
||||
fname[MAX_NAME_FIELD_SIZE] = '\0';
|
||||
|
||||
linkflag = bufr[156];
|
||||
file_size = octal2ulong(&bufr[124], 12);
|
||||
|
||||
/******************************************************************
|
||||
* Compute the TAR checksum and check with the value in
|
||||
* the archive. The checksum is computed over the entire
|
||||
* header, but the checksum field is substituted with blanks.
|
||||
******************************************************************/
|
||||
hdr_chksum = (int)octal2ulong(&bufr[148], 8);
|
||||
sum = 0;
|
||||
for (i=0; i<512; i++)
|
||||
{
|
||||
if ((i >= 148) && (i < 156))
|
||||
{
|
||||
sum += 0xff & ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
sum += 0xff & bufr[i];
|
||||
}
|
||||
}
|
||||
if (sum != hdr_chksum)
|
||||
{
|
||||
retval = UNTAR_INVALID_CHECKSUM;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* We've decoded the header, now figure out what it contains and
|
||||
* do something with it.
|
||||
*****************************************************************/
|
||||
if (linkflag == LF_SYMLINK)
|
||||
{
|
||||
strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
|
||||
linkname[MAX_NAME_FIELD_SIZE] = '\0';
|
||||
/* symlink(fname, linkname); */
|
||||
}
|
||||
else if (linkflag == LF_NORMAL)
|
||||
{
|
||||
nblocks = (((file_size) + 511) & ~511) / 512;
|
||||
if ((fp = fopen(fname, "w")) == NULL)
|
||||
{
|
||||
printf("Untar failed to create file %s\n", fname);
|
||||
ptr += 512 * nblocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long sizeToGo = file_size;
|
||||
unsigned long len;
|
||||
|
||||
/***************************************************************
|
||||
* Read out the data. There are nblocks of data where nblocks
|
||||
* is the file_size rounded to the nearest 512-byte boundary.
|
||||
**************************************************************/
|
||||
for (i=0; i<nblocks; i++)
|
||||
{
|
||||
len = ((sizeToGo < 512L)?(sizeToGo):(512L));
|
||||
n = fwrite(&tar_buf[ptr], 1, len, fp);
|
||||
if (n != len)
|
||||
{
|
||||
printf("Error during write\n");
|
||||
break;
|
||||
}
|
||||
ptr += 512;
|
||||
sizeToGo -= n;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
else if (linkflag == LF_DIR)
|
||||
{
|
||||
mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
}
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Function: Untar_FromFile *
|
||||
**************************************************************************
|
||||
* Description: *
|
||||
* *
|
||||
* This is a simple subroutine used to rip links, directories, and *
|
||||
* files out of a TAR file. *
|
||||
* *
|
||||
* *
|
||||
* Inputs: *
|
||||
* *
|
||||
* char *tar_name - TAR filename. *
|
||||
* *
|
||||
* *
|
||||
* Output: *
|
||||
* *
|
||||
* int - UNTAR_SUCCESSFUL (0) on successful completion. *
|
||||
* UNTAR_INVALID_CHECKSUM for an invalid header checksum. *
|
||||
* UNTAR_INVALID_HEADER for an invalid header. *
|
||||
* *
|
||||
**************************************************************************
|
||||
* Change History: *
|
||||
* 12/30/1998 - Creation (JWJ) *
|
||||
*************************************************************************/
|
||||
int
|
||||
Untar_FromFile(char *tar_name)
|
||||
{
|
||||
int fd;
|
||||
char *bufr;
|
||||
size_t n;
|
||||
char fname[100];
|
||||
char linkname[100];
|
||||
int sum;
|
||||
int hdr_chksum;
|
||||
int retval;
|
||||
unsigned long i;
|
||||
unsigned long nblocks;
|
||||
unsigned long size;
|
||||
unsigned char linkflag;
|
||||
|
||||
|
||||
retval = UNTAR_SUCCESSFUL;
|
||||
bufr = (char *)malloc(512);
|
||||
if (bufr == NULL)
|
||||
{
|
||||
return(UNTAR_FAIL);
|
||||
}
|
||||
|
||||
fd = open(tar_name, O_RDONLY);
|
||||
while (1)
|
||||
{
|
||||
/* Read the header */
|
||||
/* If the header read fails, we just consider it the end
|
||||
of the tarfile. */
|
||||
if ((n = read(fd, bufr, 512)) != 512)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (strncmp(&bufr[257], "ustar ", 7))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(fname, bufr, MAX_NAME_FIELD_SIZE);
|
||||
fname[MAX_NAME_FIELD_SIZE] = '\0';
|
||||
|
||||
linkflag = bufr[156];
|
||||
size = octal2ulong(&bufr[124], 12);
|
||||
|
||||
/******************************************************************
|
||||
* Compute the TAR checksum and check with the value in
|
||||
* the archive. The checksum is computed over the entire
|
||||
* header, but the checksum field is substituted with blanks.
|
||||
******************************************************************/
|
||||
hdr_chksum = (int)octal2ulong(&bufr[148], 8);
|
||||
sum = 0;
|
||||
for (i=0; i<512; i++)
|
||||
{
|
||||
if ((i >= 148) && (i < 156))
|
||||
{
|
||||
sum += 0xff & ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
sum += 0xff & bufr[i];
|
||||
}
|
||||
}
|
||||
if (sum != hdr_chksum)
|
||||
{
|
||||
retval = UNTAR_INVALID_CHECKSUM;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* We've decoded the header, now figure out what it contains and
|
||||
* do something with it.
|
||||
*****************************************************************/
|
||||
if (linkflag == LF_SYMLINK)
|
||||
{
|
||||
strncpy(linkname, &bufr[157], MAX_NAME_FIELD_SIZE);
|
||||
linkname[MAX_NAME_FIELD_SIZE] = '\0';
|
||||
}
|
||||
else if (linkflag == LF_NORMAL)
|
||||
{
|
||||
int out_fd;
|
||||
|
||||
/******************************************************************
|
||||
* Read out the data. There are nblocks of data where nblocks
|
||||
* is the size rounded to the nearest 512-byte boundary.
|
||||
*****************************************************************/
|
||||
nblocks = (((size) + 511) & ~511) / 512;
|
||||
|
||||
if ((out_fd = creat(fname, 0644)) == -1)
|
||||
{
|
||||
for (i=0; i<nblocks; i++)
|
||||
{
|
||||
n = read(fd, bufr, 512);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<nblocks; i++)
|
||||
{
|
||||
n = read(fd, bufr, 512);
|
||||
n = MIN(n, size - i*512);
|
||||
write(out_fd, bufr, n);
|
||||
}
|
||||
close(out_fd);
|
||||
}
|
||||
}
|
||||
else if (linkflag == LF_DIR)
|
||||
{
|
||||
mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
}
|
||||
free(bufr);
|
||||
close(fd);
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Written by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __UNTAR_H__
|
||||
#define __UNTAR_H__
|
||||
|
||||
|
||||
#define UNTAR_SUCCESSFUL 0
|
||||
#define UNTAR_FAIL 1
|
||||
#define UNTAR_INVALID_CHECKSUM 2
|
||||
#define UNTAR_INVALID_HEADER 3
|
||||
|
||||
|
||||
int Untar_FromMemory(unsigned char *tar_buf, unsigned long size);
|
||||
int Untar_FromFile(char *tar_name);
|
||||
|
||||
|
||||
#endif /* __UNTAR_H__ */
|
||||
@@ -1,50 +0,0 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
@SET_MAKE@
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ..
|
||||
subdir = wrapup
|
||||
|
||||
RTEMS_ROOT = @RTEMS_ROOT@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
VPATH = @srcdir@
|
||||
|
||||
LIB = $(ARCH)/libmisc.a
|
||||
|
||||
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
|
||||
include $(RTEMS_ROOT)/make/lib.cfg
|
||||
|
||||
INSTALL_CHANGE = @INSTALL_CHANGE@
|
||||
|
||||
# Using the wildcard on the Purify support makes sure it may not be there
|
||||
|
||||
LIBS = ../monitor/$(ARCH)/libmonitor-tmp.a ../untar/$(ARCH)/libuntar-tmp.a \
|
||||
../stackchk/$(ARCH)/libstackchk-tmp.a ../cpuuse/$(ARCH)/libcpuuse-tmp.a \
|
||||
../rtmonuse/$(ARCH)/librtmonuse-tmp.a \
|
||||
../dumpbuf/$(ARCH)/libdumpbuf-tmp.a
|
||||
|
||||
RELS =
|
||||
|
||||
CLEAN_ADDITIONS +=
|
||||
CLOBBER_ADDITIONS +=
|
||||
|
||||
$(LIB): ${LIBS} $(RELS)
|
||||
$(RM) -r $(ARCH)
|
||||
mkdir $(ARCH)
|
||||
cd $(ARCH); for lib in $(LIBS:%=../%); do \
|
||||
$(AR) -xv $$lib; \
|
||||
done
|
||||
$(RM) $@
|
||||
$(AR) ruv $@ $(ARCH)/*
|
||||
$(RANLIB) $@
|
||||
|
||||
all: ${ARCH} $(SRCS) $(LIB)
|
||||
@$(INSTALL_VARIANT) -m 644 $(LIB) $(PROJECT_RELEASE)/lib
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) \
|
||||
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
|
||||
Reference in New Issue
Block a user