From b06e68ef1f6df69cc86d72356c3a002054a35fad Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 17 Aug 1995 19:51:51 +0000 Subject: Numerous miscellaneous features incorporated from Tony Bennett (tbennett@divnc.com) including the following major additions: + variable length messages + named devices + debug monitor + association tables/variables --- cpukit/libcsupport/include/clockdrv.h | 31 +- cpukit/libcsupport/include/rtems/assoc.h | 44 +++ cpukit/libcsupport/include/rtems/error.h | 26 ++ cpukit/libcsupport/include/rtems/libio.h | 101 ++++++ cpukit/libcsupport/src/assoc.c | 258 +++++++++++++ cpukit/libcsupport/src/error.c | 212 +++++++++++ cpukit/libcsupport/src/libio.c | 433 ++++++++++++++++++++++ cpukit/libmisc/monitor/README | 94 ++++- cpukit/libmisc/monitor/mon-command.c | 190 ++++++++++ cpukit/libmisc/monitor/mon-config.c | 132 +++++++ cpukit/libmisc/monitor/mon-dname.c | 113 ++++++ cpukit/libmisc/monitor/mon-driver.c | 138 +++++++ cpukit/libmisc/monitor/mon-extension.c | 101 ++++++ cpukit/libmisc/monitor/mon-itask.c | 117 ++++++ cpukit/libmisc/monitor/mon-manager.c | 52 +++ cpukit/libmisc/monitor/mon-monitor.c | 545 +++++++++++++++++++--------- cpukit/libmisc/monitor/mon-mpci.c | 161 ++++++++ cpukit/libmisc/monitor/mon-object.c | 376 +++++++++++++++++++ cpukit/libmisc/monitor/mon-prmisc.c | 257 +++++++++++++ cpukit/libmisc/monitor/mon-queue.c | 66 ++++ cpukit/libmisc/monitor/mon-server.c | 305 ++++++++++++++++ cpukit/libmisc/monitor/mon-symbols.c | 233 ++++++++++-- cpukit/libmisc/monitor/mon-task.c | 85 +++++ cpukit/libmisc/monitor/monitor.h | 417 ++++++++++++++++++++- cpukit/libmisc/monitor/symbols.h | 15 +- cpukit/rtems/include/rtems/rtems/message.h | 73 ++-- cpukit/rtems/include/rtems/rtems/msgmp.h | 14 +- cpukit/rtems/inline/rtems/rtems/attr.inl | 13 - cpukit/rtems/inline/rtems/rtems/message.inl | 37 +- cpukit/rtems/macros/rtems/rtems/attr.inl | 9 - cpukit/sapi/include/rtems/config.h | 63 ++-- cpukit/sapi/include/rtems/io.h | 98 ++--- cpukit/sapi/src/exinit.c | 3 +- cpukit/sapi/src/io.c | 268 +++++++------- cpukit/score/include/rtems/score/object.h | 28 ++ cpukit/score/include/rtems/score/thread.h | 1 + cpukit/score/include/rtems/system.h | 7 +- cpukit/score/src/object.c | 67 ++++ 38 files changed, 4640 insertions(+), 543 deletions(-) create mode 100644 cpukit/libcsupport/include/rtems/assoc.h create mode 100644 cpukit/libcsupport/include/rtems/error.h create mode 100644 cpukit/libcsupport/include/rtems/libio.h create mode 100644 cpukit/libcsupport/src/assoc.c create mode 100644 cpukit/libcsupport/src/error.c create mode 100644 cpukit/libcsupport/src/libio.c create mode 100644 cpukit/libmisc/monitor/mon-command.c create mode 100644 cpukit/libmisc/monitor/mon-config.c create mode 100644 cpukit/libmisc/monitor/mon-dname.c create mode 100644 cpukit/libmisc/monitor/mon-driver.c create mode 100644 cpukit/libmisc/monitor/mon-extension.c create mode 100644 cpukit/libmisc/monitor/mon-itask.c create mode 100644 cpukit/libmisc/monitor/mon-manager.c create mode 100644 cpukit/libmisc/monitor/mon-mpci.c create mode 100644 cpukit/libmisc/monitor/mon-object.c create mode 100644 cpukit/libmisc/monitor/mon-prmisc.c create mode 100644 cpukit/libmisc/monitor/mon-queue.c create mode 100644 cpukit/libmisc/monitor/mon-server.c create mode 100644 cpukit/libmisc/monitor/mon-task.c (limited to 'cpukit') diff --git a/cpukit/libcsupport/include/clockdrv.h b/cpukit/libcsupport/include/clockdrv.h index aad9bd6d3b..258c590e0d 100644 --- a/cpukit/libcsupport/include/clockdrv.h +++ b/cpukit/libcsupport/include/clockdrv.h @@ -23,31 +23,24 @@ extern "C" { /* variables */ extern volatile rtems_unsigned32 Clock_driver_ticks; +extern rtems_device_major_number rtems_clock_major; +extern rtems_device_minor_number rtems_clock_minor; -/* functions */ - -rtems_task Exit_task(); -void exit_task_init(); - -void Install_clock( rtems_isr_entry ); -void ReInstall_clock( rtems_isr_entry ); -void Clock_exit(); - -rtems_isr Clock_isr( - rtems_vector_number -); - -/* driver entries */ +/* default clock driver entry */ #define CLOCK_DRIVER_TABLE_ENTRY \ - { Clock_initialize, NULL, NULL, NULL, NULL, NULL } - + { Clock_initialize, NULL, NULL, NULL, NULL, Clock_control } + rtems_device_driver Clock_initialize( rtems_device_major_number, rtems_device_minor_number, - void *, - rtems_id, - rtems_unsigned32 * + void * +); + +rtems_device_driver Clock_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp ); #ifdef __cplusplus diff --git a/cpukit/libcsupport/include/rtems/assoc.h b/cpukit/libcsupport/include/rtems/assoc.h new file mode 100644 index 0000000000..c820cfa973 --- /dev/null +++ b/cpukit/libcsupport/include/rtems/assoc.h @@ -0,0 +1,44 @@ +/* + * @(#)assoc.h 1.2 - 95/06/28 + * + * + * Rtems associativity routines. Mainly used to convert a value from + * one space to another (eg: our errno's to host errno's and v.v) + * + * + * $Id$ + */ + +#ifndef _INCLUDE_ASSOC_H +#define _INCLUDE_ASSOC_H + +typedef struct { + char *name; + unsigned32 local_value; + unsigned32 remote_value; +} rtems_assoc_t; + +/* + * Flag/marker for optional default value in each table + */ + +#define RTEMS_ASSOC_DEFAULT_NAME "(default)" + +rtems_assoc_t *rtems_assoc_ptr_by_name(rtems_assoc_t *, char *); +rtems_assoc_t *rtems_assoc_ptr_by_value(rtems_assoc_t *, unsigned32); +rtems_assoc_t *rtems_assoc_ptr_by_remote(rtems_assoc_t *, unsigned32); + +unsigned32 rtems_assoc_remote_by_local(rtems_assoc_t *, unsigned32); +unsigned32 rtems_assoc_local_by_remote(rtems_assoc_t *, unsigned32); +unsigned32 rtems_assoc_remote_by_name(rtems_assoc_t *, char *); +unsigned32 rtems_assoc_local_by_name(rtems_assoc_t *, char *); +char *rtems_assoc_name_by_local(rtems_assoc_t *, unsigned32); +char *rtems_assoc_name_by_remote(rtems_assoc_t *, unsigned32); + +unsigned32 rtems_assoc_remote_by_local_bitfield(rtems_assoc_t *, unsigned32); +char *rtems_assoc_name_by_local_bitfield(rtems_assoc_t *, unsigned32, char *); +char *rtems_assoc_name_by_remote_bitfield(rtems_assoc_t *, unsigned32, char *); +unsigned32 rtems_assoc_local_by_remote_bitfield(rtems_assoc_t *ap, unsigned32); + + +#endif /* ! _INCLUDE_ASSOC_H */ diff --git a/cpukit/libcsupport/include/rtems/error.h b/cpukit/libcsupport/include/rtems/error.h new file mode 100644 index 0000000000..a41f0aa534 --- /dev/null +++ b/cpukit/libcsupport/include/rtems/error.h @@ -0,0 +1,26 @@ +/* + * @(#)error.h 1.1 - 95/08/02 + * + * + * Defines and externs for rtems error reporting + * + * $Id$ + */ + +/* + * rtems_error() and rtems_panic() support + */ + +#define RTEMS_ERROR_ERRNO (1<<((sizeof(int) * 8) - 2)) /* hi bit; use 'errno' */ +#define RTEMS_ERROR_PANIC (RTEMS_ERROR_ERRNO / 2) /* err fatal; no return */ +#define RTEMS_ERROR_ABORT (RTEMS_ERROR_ERRNO / 4) /* err is fatal; panic */ + +#define RTEMS_ERROR_MASK (RTEMS_ERROR_ERRNO | RTEMS_ERROR_ABORT | \ + RTEMS_ERROR_PANIC) /* all */ + +char *rtems_status_text(rtems_status_code); +int rtems_error(int error_code, char *printf_format, ...); +void rtems_panic(char *printf_format, ...); + +extern int rtems_panic_in_progress; + diff --git a/cpukit/libcsupport/include/rtems/libio.h b/cpukit/libcsupport/include/rtems/libio.h new file mode 100644 index 0000000000..f80a1954a3 --- /dev/null +++ b/cpukit/libcsupport/include/rtems/libio.h @@ -0,0 +1,101 @@ +/* + * @(#)libio.h 1.1 - 95/06/02 + * + * + * General purpose communication channel for RTEMS to allow UNIX/POSIX + * system call behavior on top of RTEMS IO devices. + * + * TODO + * stat(2) + * unlink(2) + * rename(2) + * + * $Id$ + */ + +#ifndef _RTEMS_LIBIO_H +#define _RTEMS_LIBIO_H + +typedef unsigned32 rtems_libio_offset_t; + +/* + * An open file data structure, indexed by 'fd' + * TODO: + * should really have a separate per/file data structure that this + * points to (eg: size, offset, driver, pathname should be in that) + */ + +typedef struct { + rtems_driver_name_t *driver; + rtems_libio_offset_t size; /* size of file */ + rtems_libio_offset_t offset; /* current offset into the file */ + unsigned32 flags; + char *pathname; /* opened pathname */ + Objects_Id sem; + unsigned32 data0; /* private to "driver" */ + unsigned32 data1; /* ... */ +} rtems_libio_t; + + +/* + * param block for read/write + * Note: it must include 'offset' instead of using iop's offset since + * we can have multiple outstanding i/o's on a device. + */ + +typedef struct { + rtems_libio_t *iop; + rtems_libio_offset_t offset; + unsigned8 *buffer; + unsigned32 count; + unsigned32 flags; + unsigned32 bytes_moved; +} rtems_libio_rw_args_t; + +/* + * param block for open/close + */ + +typedef struct { + rtems_libio_t *iop; + unsigned32 flags; + unsigned32 mode; +} rtems_libio_open_close_args_t; + +/* + * param block for ioctl + */ + +typedef struct { + rtems_libio_t *iop; + unsigned32 command; + void *buffer; + unsigned32 ioctl_return; +} rtems_libio_ioctl_args_t; + + +/* + * Values for 'flag' + */ + +#define LIBIO_FLAGS_NO_DELAY 0x0001 /* return immediately if no data */ +#define LIBIO_FLAGS_READ 0x0002 /* reading */ +#define LIBIO_FLAGS_WRITE 0x0004 /* writing */ +#define LIBIO_FLAGS_LINE_BUFFERED 0x0008 /* line buffered io (^h, ^u, etc) */ +#define LIBIO_FLAGS_OPEN 0x0100 /* device is open */ +#define LIBIO_FLAGS_APPEND 0x0200 /* all writes append */ +#define LIBIO_FLAGS_CREATE 0x0400 /* create file */ + +#define LIBIO_FLAGS_READ_WRITE (LIBIO_FLAGS_READ | LIBIO_FLAGS_WRITE) + +void rtems_libio_config(rtems_configuration_table *config, unsigned32 max_fds); +void rtems_libio_init(void); + +int __open(const char *pathname, unsigned32 flag, unsigned32 mode); +int __close(int fd); +int __read(int fd, void *buffer, unsigned32 count); +int __write(int fd, const void *buffer, unsigned32 count); +int __ioctl(int fd, unsigned32 command, void *buffer); +int __lseek(int fd, rtems_libio_offset_t offset, int whence); + +#endif /* _RTEMS_LIBIO_H */ diff --git a/cpukit/libcsupport/src/assoc.c b/cpukit/libcsupport/src/assoc.c new file mode 100644 index 0000000000..c18359ef8a --- /dev/null +++ b/cpukit/libcsupport/src/assoc.c @@ -0,0 +1,258 @@ +/* + * @(#)assoc.c 1.4 - 95/08/02 + * + * + * assoc.c + * rtems assoc routines + * + * $Id$ + */ + + +#include +#include "assoc.h" + +#include /* sprintf */ +#include /* strcat, strcmp */ + +#define STREQ(a,b) (strcmp((a), (b)) == 0) +#define rtems_assoc_is_default(ap) ((ap)->name && STREQ(ap->name, RTEMS_ASSOC_DEFAULT_NAME)) + +rtems_assoc_t * +rtems_assoc_ptr_by_name( + rtems_assoc_t *ap, + char *name + ) +{ + rtems_assoc_t *default_ap = 0; + + if (rtems_assoc_is_default(ap)) + default_ap = ap++; + + for ( ; ap->name; ap++) + if (strcmp(ap->name, name) == 0) + return ap; + + return default_ap; +} + +rtems_assoc_t * +rtems_assoc_ptr_by_local( + rtems_assoc_t *ap, + unsigned32 local_value + ) +{ + rtems_assoc_t *default_ap = 0; + + if (rtems_assoc_is_default(ap)) + default_ap = ap++; + + for ( ; ap->name; ap++) + if (ap->local_value == local_value) + return ap; + + return default_ap; +} + + +rtems_assoc_t * +rtems_assoc_ptr_by_remote( + rtems_assoc_t *ap, + unsigned32 remote_value + ) +{ + rtems_assoc_t *default_ap = 0; + + if (rtems_assoc_is_default(ap)) + default_ap = ap++; + + for ( ; ap->name; ap++) + if (ap->remote_value == remote_value) + return ap; + + return default_ap; +} + + +/* + * Get values + */ + +unsigned32 +rtems_assoc_remote_by_local( + rtems_assoc_t *ap, + unsigned32 local_value + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_local(ap, local_value); + if (nap) + return nap->remote_value; + + return 0; +} + +unsigned32 +rtems_assoc_local_by_remote( + rtems_assoc_t *ap, + unsigned32 remote_value + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_remote(ap, remote_value); + if (nap) + return nap->local_value; + + return 0; +} + +unsigned32 +rtems_assoc_remote_by_name( + rtems_assoc_t *ap, + char *name + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_name(ap, name); + if (nap) + return nap->remote_value; + + return 0; +} + +unsigned32 +rtems_assoc_local_by_name( + rtems_assoc_t *ap, + char *name + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_name(ap, name); + if (nap) + return nap->local_value; + + return 0; +} + +/* + * what to return if a value is not found + * this is not reentrant, but it really shouldn't be invoked anyway + */ + +char * +rtems_assoc_name_bad( + unsigned32 bad_value +) +{ + static char bad_buffer[32]; + + sprintf(bad_buffer, "< %d [0x%x] >", bad_value, bad_value); + return bad_buffer; +} + + +char * +rtems_assoc_name_by_local( + rtems_assoc_t *ap, + unsigned32 local_value + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_local(ap, local_value); + if (nap) + return nap->name; + + return rtems_assoc_name_bad(local_value); +} + +char * +rtems_assoc_name_by_remote( + rtems_assoc_t *ap, + unsigned32 remote_value + ) +{ + rtems_assoc_t *nap; + nap = rtems_assoc_ptr_by_remote(ap, remote_value); + if (nap) + return nap->name; + + return rtems_assoc_name_bad(remote_value); +} + +/* + * Bitfield functions assume just 1 bit set in each of remote and local + * entries; they do not check for this. + */ + +unsigned32 rtems_assoc_remote_by_local_bitfield( + rtems_assoc_t *ap, + unsigned32 local_value + ) +{ + unsigned32 b; + unsigned32 remote_value = 0; + + for (b = 1; b; b <<= 1) + if (b & local_value) + remote_value |= rtems_assoc_remote_by_local(ap, b); + + return remote_value; +} + + +unsigned32 rtems_assoc_local_by_remote_bitfield( + rtems_assoc_t *ap, + unsigned32 remote_value + ) +{ + unsigned32 b; + unsigned32 local_value = 0; + + for (b = 1; b; b <<= 1) + if (b & remote_value) + local_value |= rtems_assoc_local_by_remote(ap, b); + + return local_value; +} + +char *rtems_assoc_name_by_remote_bitfield( + rtems_assoc_t *ap, + unsigned32 value, + char *buffer + ) +{ + unsigned32 b; + + *buffer = 0; + + for (b = 1; b; b <<= 1) + if (b & value) + { + if (*buffer) + strcat(buffer, " "); + strcat(buffer, rtems_assoc_name_by_remote(ap, b)); + } + + return buffer; +} + +char *rtems_assoc_name_by_local_bitfield( + rtems_assoc_t *ap, + unsigned32 value, + char *buffer + ) +{ + unsigned32 b; + + *buffer = 0; + + for (b = 1; b; b <<= 1) + if (b & value) + { + if (*buffer) + strcat(buffer, " "); + strcat(buffer, rtems_assoc_name_by_local(ap, b)); + } + + return buffer; +} diff --git a/cpukit/libcsupport/src/error.c b/cpukit/libcsupport/src/error.c new file mode 100644 index 0000000000..8cf46f0565 --- /dev/null +++ b/cpukit/libcsupport/src/error.c @@ -0,0 +1,212 @@ +/* + * @(#)error.c 1.2 - 95/08/02 + * + * + * report errors and panics to RTEMS' stderr. + * Currently just used by RTEMS monitor. + * + * + * $Id$ + */ + + +/* + * These routines provide general purpose error reporting. + * rtems_error reports an error to stderr and allows use of + * printf style formatting. A newline is appended to all messages. + * + * error_flag can be specified as any of the following: + * + * RTEMS_ERROR_ERRNO -- include errno text in output + * RTEMS_ERROR_PANIC -- halts local system after output + * RTEMS_ERROR_ABORT -- abort after output + * + * It can also include a rtems_status value which can be OR'd + * with the above flags. * + * + * EXAMPLE + * #include + * #include + * rtems_error(0, "stray interrupt %d", intr); + * + * EXAMPLE + * if ((status = rtems_task_create(...)) != RTEMS_SUCCCESSFUL) + * { + * rtems_error(status | RTEMS_ERROR_ABORT, + * "could not create task"); + * } + * + * EXAMPLE + * if ((fd = open(pathname, O_RDNLY)) < 0) + * { + * rtems_error(FLOSS_ERROR_ERRNO, "open of '%s' failed", pathname); + * goto failed; + * } + */ + +#include + +#include "error.h" +#include "assoc.h" + +#include +#include +#include +#include +#include +#include /* _exit() */ + +/* bug in hpux : no prototypes unless you are C++ */ +#ifdef hpux9 +char *strerror(int); +#endif + +extern char *rtems_progname; +int rtems_panic_in_progress; + +rtems_assoc_t rtems_status_assoc[] = { + { "successful completion", RTEMS_SUCCESSFUL, }, + { "returned from a thread", RTEMS_TASK_EXITTED, }, + { "multiprocessing not configured", RTEMS_MP_NOT_CONFIGURED, }, + { "invalid object name", RTEMS_INVALID_NAME, }, + { "invalid object id", RTEMS_INVALID_ID, }, + { "too many", RTEMS_TOO_MANY, }, + { "timed out waiting", RTEMS_TIMEOUT, }, + { "object deleted while waiting", RTEMS_OBJECT_WAS_DELETED, }, + { "specified size was invalid", RTEMS_INVALID_SIZE, }, + { "address specified is invalid", RTEMS_INVALID_ADDRESS, }, + { "number was invalid", RTEMS_INVALID_NUMBER, }, + { "item has not been initialized", RTEMS_NOT_DEFINED, }, + { "resources still outstanding", RTEMS_RESOURCE_IN_USE, }, + { "request not satisfied", RTEMS_UNSATISFIED, }, + { "thread is in wrong state", RTEMS_INCORRECT_STATE, }, + { "thread already in state", RTEMS_ALREADY_SUSPENDED, }, + { "illegal on calling thread", RTEMS_ILLEGAL_ON_SELF, }, + { "illegal for remote object", RTEMS_ILLEGAL_ON_REMOTE_OBJECT, }, + { "called from wrong environment", RTEMS_CALLED_FROM_ISR, }, + { "invalid thread priority", RTEMS_INVALID_PRIORITY, }, + { "invalid date/time", RTEMS_INVALID_CLOCK, }, + { "invalid node id", RTEMS_INVALID_NODE, }, + { "directive not configured", RTEMS_NOT_CONFIGURED, }, + { "not owner of resource", RTEMS_NOT_OWNER_OF_RESOURCE , }, + { "directive not implemented", RTEMS_NOT_IMPLEMENTED, }, + { "RTEMS inconsistency detected", RTEMS_INTERNAL_ERROR, }, + { "internal multiprocessing only", RTEMS_PROXY_BLOCKING, }, + { "could not get enough memory", RTEMS_NO_MEMORY, }, + { 0, 0, 0 }, +}; + + +char * +rtems_status_text( + rtems_status_code status +) +{ + return rtems_assoc_name_by_local(rtems_status_assoc, status); +} + + +static int rtems_verror( + unsigned32 error_flag, + char *printf_format, + va_list arglist +) +{ + int local_errno = 0; + int chars_written = 0; + rtems_status_code status; + + if (error_flag & RTEMS_ERROR_PANIC) + { + rtems_panic_in_progress++; + + /* disable task switches */ + _Thread_Disable_dispatch(); + + /* don't aggravate things */ + if (rtems_panic_in_progress > 2) + return 0; + } + + (void) fflush(stdout); /* in case stdout/stderr same */ + + status = error_flag & ~RTEMS_ERROR_MASK; + if (error_flag & RTEMS_ERROR_ERRNO) /* include errno? */ + local_errno = errno; + + if (_Configuration_Is_multiprocessing()) + fprintf(stderr, "[%d] ", _Configuration_MP_table->node); + + if (rtems_progname && *rtems_progname) + chars_written += fprintf(stderr, "%s: ", rtems_progname); + chars_written += vfprintf(stderr, printf_format, arglist); + + if (status) + chars_written += fprintf(stderr, " (status: %s)", rtems_status_text(status)); + + if (local_errno) + if ((local_errno > 0) && *strerror(local_errno)) + chars_written += fprintf(stderr, " (errno: %s)", strerror(local_errno)); + else + chars_written += fprintf(stderr, " (unknown errno=%d)", local_errno); + + chars_written += fprintf(stderr, "\n"); + + (void) fflush(stderr); + + if (error_flag & (RTEMS_ERROR_PANIC | RTEMS_ERROR_ABORT)) + { + if (error_flag & RTEMS_ERROR_PANIC) + { + rtems_error(0, "fatal error, exiting"); + _exit(local_errno); + } + else + { + rtems_error(0, "fatal error, aborting"); + abort(); + } + } + return chars_written; +} + + +/* + * Report an error. + * error_flag is as above; printf_format is a normal + * printf(3) format string, with its concommitant arguments. + * + * Returns the number of characters written. + */ + +int rtems_error( + int error_flag, + char *printf_format, + ... + ) +{ + va_list arglist; + int chars_written; + + va_start(arglist, printf_format); + chars_written = rtems_verror(error_flag, printf_format, arglist); + va_end(arglist); + + return chars_written; +} + +/* + * rtems_panic is shorthand for rtems_error(RTEMS_ERROR_PANIC, ...) + */ + +void rtems_panic( + char *printf_format, + ... + ) +{ + va_list arglist; + + va_start(arglist, printf_format); + (void) rtems_verror(RTEMS_ERROR_PANIC, printf_format, arglist); + va_end(arglist); +} diff --git a/cpukit/libcsupport/src/libio.c b/cpukit/libcsupport/src/libio.c new file mode 100644 index 0000000000..ce41643a09 --- /dev/null +++ b/cpukit/libcsupport/src/libio.c @@ -0,0 +1,433 @@ +/* + * @(#)libio.c 1.1 - 95/06/02 + * + * + * Provide UNIX/POSIX-like io system calls for RTEMS using the + * RTEMS IO manager + * + * TODO + * + * $Id$ + */ + +#include +#include /* assoc.h not included by rtems.h */ + +#include /* O_RDONLY, et.al. */ +#if defined(solaris2) +#define O_NDELAY O_NONBLOCK +#endif +#include +#include /* strcmp */ +#include +#include /* calloc() */ + +#include "libio.h" /* libio.h not pulled in by rtems */ + +/* + * Semaphore to protect the io table + */ + +Objects_Id rtems_libio_semaphore; + +#define RTEMS_LIBIO_SEM rtems_build_name('L', 'B', 'I', 'O') +#define RTEMS_LIBIO_IOP_SEM(n) rtems_build_name('L', 'B', 'I', n) + +unsigned32 rtems_libio_number_iops; +rtems_libio_t *rtems_libio_iops; +rtems_libio_t *rtems_libio_last_iop; + +#define rtems_libio_iop(fd) ((((unsigned32)(fd)) < rtems_libio_number_iops) ? \ + &rtems_libio_iops[fd] : 0) + +#define rtems_libio_check_fd(fd) \ + do { \ + if ((fd) >= rtems_libio_number_iops) \ + { \ + errno = EBADF; \ + return -1; \ + } \ + } while (0) + +#define rtems_libio_check_buffer(buffer) \ + do { \ + if ((buffer) == 0) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) + +#define rtems_libio_check_count(count) \ + do { \ + if ((count) == 0) \ + { \ + return 0; \ + } \ + } while (0) + +#define rtems_libio_check_permissions(iop, flag) \ + do { \ + if (((iop)->flags & (flag)) == 0) \ + { \ + errno = EINVAL; \ + return -1; \ + } \ + } while (0) + + +void +rtems_libio_config( + rtems_configuration_table *config, + unsigned32 max_fds + ) +{ + rtems_libio_number_iops = max_fds; + + /* + * tweak config to reflect # of semaphores we will need + */ + + config->maximum_semaphores += 1; /* one for iop table */ + config->maximum_semaphores += max_fds; +} + +/* + * Called by bsp startup code to init the libio area. + */ + +void +rtems_libio_init(void) +{ + rtems_status_code rc; + + if (rtems_libio_number_iops > 0) + { + rtems_libio_iops = (rtems_libio_t *) calloc(rtems_libio_number_iops, + sizeof(rtems_libio_t)); + if (rtems_libio_iops == NULL) + rtems_fatal_error_occurred(RTEMS_NO_MEMORY); + + rtems_libio_last_iop = rtems_libio_iops + (rtems_libio_number_iops - 1); + } + + rc = rtems_semaphore_create(RTEMS_LIBIO_SEM, + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + &rtems_libio_semaphore); + if (rc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred(rc); +} + +/* + * Convert RTEMS status to a UNIX errno + */ + +rtems_assoc_t errno_assoc[] = { + { "OK", RTEMS_SUCCESSFUL, 0 }, + { "TIMEOUT", RTEMS_TIMEOUT, ETIME }, + { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, + { 0, 0, 0 }, +}; + +static unsigned32 +rtems_libio_errno(rtems_status_code code) +{ + int rc; + + if ((rc = rtems_assoc_remote_by_local(errno_assoc, (unsigned32) code))) + { + errno = rc; + return -1; + } + return 0; +} + +/* + * Convert UNIX fnctl(2) flags to ones that RTEMS drivers understand + */ + +rtems_assoc_t access_modes_assoc[] = { + { "READ", LIBIO_FLAGS_READ, O_RDONLY }, + { "WRITE", LIBIO_FLAGS_WRITE, O_WRONLY }, + { "READ/WRITE", LIBIO_FLAGS_READ_WRITE, O_RDWR }, + { 0, 0, 0 }, +}; + +rtems_assoc_t status_flags_assoc[] = { + { "NO DELAY", LIBIO_FLAGS_NO_DELAY, O_NDELAY }, + { "APPEND", LIBIO_FLAGS_APPEND, O_APPEND }, + { "CREATE", LIBIO_FLAGS_CREATE, O_CREAT }, + { 0, 0, 0 }, +}; + +static unsigned32 +rtems_libio_fcntl_flags(unsigned32 fcntl_flags) +{ + unsigned32 flags = 0; + unsigned32 access_modes; + + /* + * Access mode is a small integer + */ + + access_modes = fcntl_flags & O_ACCMODE; + fcntl_flags &= ~O_ACCMODE; + flags = rtems_assoc_local_by_remote(access_modes_assoc, access_modes); + + /* + * Everything else is single bits + */ + + flags |= rtems_assoc_local_by_remote_bitfield(status_flags_assoc, fcntl_flags); + return flags; +} + + +static rtems_libio_t * +rtems_libio_allocate(void) +{ + rtems_libio_t *iop; + rtems_status_code rc; + + rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + + for (iop = rtems_libio_iops; iop <= rtems_libio_last_iop; iop++) + if ((iop->flags & LIBIO_FLAGS_OPEN) == 0) + { + /* + * Got one; create a semaphore for it + */ + + rc = rtems_semaphore_create(RTEMS_LIBIO_IOP_SEM(iop - rtems_libio_iops), + 1, RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + &iop->sem); + if (rc != RTEMS_SUCCESSFUL) + goto failed; + + iop->flags = LIBIO_FLAGS_OPEN; + goto done; + } + +failed: + iop = 0; + +done: + rtems_semaphore_release(rtems_libio_semaphore); + return iop; +} + +static void +rtems_libio_free(rtems_libio_t *iop) +{ + rtems_semaphore_obtain(rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + + if (iop->sem) + rtems_semaphore_delete(iop->sem); + (void) memset(iop, 0, sizeof(*iop)); + + rtems_semaphore_release(rtems_libio_semaphore); +} + +int +__open( + const char *pathname, + unsigned32 flag, + unsigned32 mode) +{ + rtems_status_code rc; + rtems_libio_t *iop = 0; + rtems_driver_name_t *np; + rtems_libio_open_close_args_t args; + + if ((rc = rtems_io_lookup_name(pathname, &np)) != RTEMS_SUCCESSFUL) + goto done; + + iop = rtems_libio_allocate(); + if (iop == 0) + { + rc = RTEMS_TOO_MANY; + goto done; + } + + iop->driver = np; + iop->pathname = (char *) pathname; + iop->flags |= rtems_libio_fcntl_flags(flag); + + args.iop = iop; + args.flags = iop->flags; + args.mode = mode; + + rc = rtems_io_open(np->major, np->minor, (void *) &args); + +done: + if (rc != RTEMS_SUCCESSFUL) + { + if (iop) + rtems_libio_free(iop); + return rtems_libio_errno(rc); + } + + return iop - rtems_libio_iops; +} + +int +__close( + int fd + ) +{ + rtems_status_code rc; + rtems_driver_name_t *np; + rtems_libio_t *iop = rtems_libio_iop(fd); + rtems_libio_open_close_args_t args; + + rtems_libio_check_fd(fd); + + np = iop->driver; + + args.iop = iop; + args.flags = 0; + args.mode = 0; + + rc = rtems_io_close(np->major, np->minor, (void *) &args); + + if (rc != RTEMS_SUCCESSFUL) + return rtems_libio_errno(rc); + return 0; +} + +int +__read( + int fd, + void * buffer, + unsigned32 count + ) +{ + rtems_status_code rc; + rtems_driver_name_t *np; + rtems_libio_t *iop = rtems_libio_iop(fd); + rtems_libio_rw_args_t args; + + rtems_libio_check_fd(fd); + rtems_libio_check_buffer(buffer); + rtems_libio_check_count(count); + rtems_libio_check_permissions(iop, LIBIO_FLAGS_READ); + + np = iop->driver; + + args.iop = iop; + args.offset = iop->offset; + args.buffer = buffer; + args.count = count; + args.flags = iop->flags; + args.bytes_moved = 0; + + rc = rtems_io_read(np->major, np->minor, (void *) &args); + + iop->offset += args.bytes_moved; + + if (rc != RTEMS_SUCCESSFUL) + return rtems_libio_errno(rc); + + return args.bytes_moved; +} + +int +__write( + int fd, + const void *buffer, + unsigned32 count + ) +{ + rtems_status_code rc; + rtems_driver_name_t *np; + rtems_libio_t *iop = rtems_libio_iop(fd); + rtems_libio_rw_args_t args; + + rtems_libio_check_fd(fd); + rtems_libio_check_buffer(buffer); + rtems_libio_check_count(count); + rtems_libio_check_permissions(iop, LIBIO_FLAGS_WRITE); + + np = iop->driver; + + args.iop = iop; + args.offset = iop->offset; + args.buffer = (void *) buffer; + args.count = count; + args.flags = iop->flags; + args.bytes_moved = 0; + + rc = rtems_io_write(np->major, np->minor, (void *) &args); + + iop->offset += args.bytes_moved; + + if (rc != RTEMS_SUCCESSFUL) + return rtems_libio_errno(rc); + + return args.bytes_moved; +} + +int +__ioctl( + int fd, + unsigned32 command, + void * buffer) +{ + rtems_status_code rc; + rtems_driver_name_t *np; + rtems_libio_t *iop = rtems_libio_iop(fd); + rtems_libio_ioctl_args_t args; + + rtems_libio_check_fd(fd); + + np = iop->driver; + + args.iop = iop; + args.command = command; + args.buffer = buffer; + + rc = rtems_io_control(np->major, np->minor, (void *) &args); + + if (rc != RTEMS_SUCCESSFUL) + return rtems_libio_errno(rc); + + return args.ioctl_return; +} + +/* + * internal only?? + */ + + +int +__lseek( + int fd, + rtems_libio_offset_t offset, + int whence + ) +{ + rtems_libio_t *iop = rtems_libio_iop(fd); + + rtems_libio_check_fd(fd); + + switch (whence) + { + case SEEK_SET: + iop->offset = offset; + break; + + case SEEK_CUR: + iop->offset += offset; + break; + + case SEEK_END: + iop->offset = iop->size - offset; + break; + + default: + errno = EINVAL; + return -1; + } + return 0; +} diff --git a/cpukit/libmisc/monitor/README b/cpukit/libmisc/monitor/README index cae39d593c..d5a73da140 100644 --- a/cpukit/libmisc/monitor/README +++ b/cpukit/libmisc/monitor/README @@ -2,6 +2,96 @@ # $Id$ # -This is a snapshot of a work in process. It is the beginnings of a -debug monitor task and trap handler which is tasking aware. +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_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) diff --git a/cpukit/libmisc/monitor/mon-command.c b/cpukit/libmisc/monitor/mon-command.c new file mode 100644 index 0000000000..d231b3197a --- /dev/null +++ b/cpukit/libmisc/monitor/mon-command.c @@ -0,0 +1,190 @@ +/* + * @(#)command.c 1.5 - 95/08/02 + * + * + * Command parsing routines for RTEMS monitor + * + * TODO: + * + * $Id$ + */ + +#include + +#include "monitor.h" + +#include +#include + +/* + * 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]); + } +} diff --git a/cpukit/libmisc/monitor/mon-config.c b/cpukit/libmisc/monitor/mon-config.c new file mode 100644 index 0000000000..1c3ece086f --- /dev/null +++ b/cpukit/libmisc/monitor/mon-config.c @@ -0,0 +1,132 @@ +/* + * @(#)config.c 1.5 - 95/08/02 + * + * + * RTEMS Config display support + * + * TODO + * + * $Id$ + */ + + +#include +#include "monitor.h" + +#include +#include /* 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; + + canonical_config->work_space_start = c->work_space_start; + canonical_config->work_space_size = c->work_space_size; + canonical_config->maximum_tasks = c->maximum_tasks; + canonical_config->maximum_timers = c->maximum_timers; + canonical_config->maximum_semaphores = c->maximum_semaphores; + canonical_config->maximum_message_queues = c->maximum_message_queues; + canonical_config->maximum_partitions = c->maximum_partitions; + canonical_config->maximum_regions = c->maximum_regions; + canonical_config->maximum_ports = c->maximum_ports; + canonical_config->maximum_periods = c->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 = c->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); +} diff --git a/cpukit/libmisc/monitor/mon-dname.c b/cpukit/libmisc/monitor/mon-dname.c new file mode 100644 index 0000000000..fd10f3e333 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-dname.c @@ -0,0 +1,113 @@ +/* + * @(#)dname.c 1.3 - 95/07/31 + * + * + * 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$ + */ + +#include + +#include "monitor.h" + +#include +#include /* strtoul() */ +#include /* 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 +) +{ + int n = rtems_get_index(*next_id); + rtems_driver_name_t *table = object_information; + rtems_driver_name_t *np = 0; + + for (np = table + n ; ndevice_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; +} diff --git a/cpukit/libmisc/monitor/mon-driver.c b/cpukit/libmisc/monitor/mon-driver.c new file mode 100644 index 0000000000..44d94f945c --- /dev/null +++ b/cpukit/libmisc/monitor/mon-driver.c @@ -0,0 +1,138 @@ +/* + * @(#)driver.c 1.4 - 95/08/02 + * + * + * 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$ + */ + +#include + +#include "monitor.h" + +#include +#include /* 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, + d->initialization); + + rtems_monitor_symbol_canonical_by_value(&canonical_driver->open, + d->open); + rtems_monitor_symbol_canonical_by_value(&canonical_driver->close, + d->close); + rtems_monitor_symbol_canonical_by_value(&canonical_driver->read, + d->read); + rtems_monitor_symbol_canonical_by_value(&canonical_driver->write, + d->write); + rtems_monitor_symbol_canonical_by_value(&canonical_driver->control, + 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; + int 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; +} diff --git a/cpukit/libmisc/monitor/mon-extension.c b/cpukit/libmisc/monitor/mon-extension.c new file mode 100644 index 0000000000..48dfb96a2d --- /dev/null +++ b/cpukit/libmisc/monitor/mon-extension.c @@ -0,0 +1,101 @@ +/* + * @(#)extension.c 1.3 - 95/07/31 + * + * + * RTEMS Monitor extension support + * + * $Id$ + */ + +#include +#include "monitor.h" + +#include + +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->create, + e->rtems_task_create); + + rtems_monitor_symbol_canonical_by_value(&canonical_extension->start, + e->rtems_task_start); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->restart, + e->rtems_task_restart); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->delete, + e->rtems_task_delete); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->tswitch, + e->task_switch); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->begin, + e->task_begin); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->exitted, + e->task_exitted); + rtems_monitor_symbol_canonical_by_value(&canonical_extension->fatal, + 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->create, verbose); + length += printf("; start: "); + length += rtems_monitor_symbol_dump(&monitor_extension->start, verbose); + length += printf("; restart: "); + length += rtems_monitor_symbol_dump(&monitor_extension->restart, verbose); + length += printf("\n"); + length = 0; + + length += rtems_monitor_pad(18, length); + length += printf("delete: "); + length += rtems_monitor_symbol_dump(&monitor_extension->delete, verbose); + length += printf("; switch: "); + length += rtems_monitor_symbol_dump(&monitor_extension->tswitch, verbose); + length += printf("; begin: "); + length += rtems_monitor_symbol_dump(&monitor_extension->begin, verbose); + length += printf("\n"); + length = 0; + + length += rtems_monitor_pad(18, length); + length += printf("exitted: "); + length += rtems_monitor_symbol_dump(&monitor_extension->exitted, verbose); + length += printf("; fatal: "); + length += rtems_monitor_symbol_dump(&monitor_extension->fatal, verbose); + length += printf("\n"); + length = 0; + printf("\n"); +} diff --git a/cpukit/libmisc/monitor/mon-itask.c b/cpukit/libmisc/monitor/mon-itask.c new file mode 100644 index 0000000000..451f642037 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-itask.c @@ -0,0 +1,117 @@ +/* + * @(#)itask.c 1.4 - 95/08/02 + * + * + * RTEMS Monitor init task support + * + * $Id$ + */ + +#include +#include "monitor.h" + +#include + +/* + * 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, + 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; + int n = rtems_get_index(*next_id); + + if (n >= c->number_of_initialization_tasks) + goto failed; + + _Thread_Disable_dispatch(); + + itask = c->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"); +} diff --git a/cpukit/libmisc/monitor/mon-manager.c b/cpukit/libmisc/monitor/mon-manager.c new file mode 100644 index 0000000000..955eaa3b56 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-manager.c @@ -0,0 +1,52 @@ +/* + * @(#)manager.c 1.2 - 95/07/31 + * + * + * RTEMS Monitor "manager" support. + * Used to traverse object (chain) lists and print them out. + * $Id$ + */ + +#include +#include "monitor.h" + +#include + +#include + +/* + * "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; + unsigned32 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; + copy->name = table->name_table[rtems_get_index(copy->id)]; + } + +done: + return object; +} + diff --git a/cpukit/libmisc/monitor/mon-monitor.c b/cpukit/libmisc/monitor/mon-monitor.c index aa466143f9..5cf80d3ad6 100644 --- a/cpukit/libmisc/monitor/mon-monitor.c +++ b/cpukit/libmisc/monitor/mon-monitor.c @@ -1,125 +1,239 @@ /* - * @(#)monitor.c 1.6 - 95/04/24 + * @(#)monitor.c 1.18 - 95/08/02 * - */ - -/* - * mon-task.c * - * Description: - * RTEMS monitor task - * - * + * RTEMS monitor main body * * TODO: - * add pause command (monitor sleeps for 'n' ticks, then wakes up) - * + * 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?? + * + * $Id$ */ #include -/* #include */ - -#include "symbols.h" -#include "monitor.h" #include #include #include #include -#define STREQ(a,b) (strcmp(a,b) == 0) +#include "monitor.h" /* set by trap handler */ extern rtems_tcb *debugger_interrupted_task; extern rtems_context *debugger_interrupted_task_context; extern rtems_unsigned32 debugger_trap; -/* our task id needs to be public so any debugger can resume us */ -rtems_unsigned32 rtems_monitor_task_id; - - -rtems_symbol_table_t *rtems_monitor_symbols; - +/* + * Various id's for the monitor + * They need to be public variables for access by other agencies + * such as debugger and remote servers' + */ -#ifndef MONITOR_PROMPT -#define MONITOR_PROMPT "rtems> " -#endif +rtems_id rtems_monitor_task_id; -#define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0 +unsigned32 rtems_monitor_node; /* our node number */ +unsigned32 rtems_monitor_default_node; /* current default for commands */ /* - * Function: rtems_monitor_init - * - * Description: - * Create the RTEMS monitor task - * - * Parameters: - * 'monitor_suspend' arg is passed as initial arg to monitor task - * If TRUE, monitor will suspend itself as it starts up. Otherwise - * it will begin its command loop. - * - * Returns: - * - * - * Side Effects: - * - * - * Notes: - * - * - * Deficiencies/ToDo: - * - * + * The rtems symbol table */ +rtems_symbol_table_t *rtems_monitor_symbols; + /* - * make_argv(cp): token-count - * Break up the command line in 'cp' into global argv[] and argc (return - * value). + * The top-level commands */ -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; -} - -void -rtems_monitor_init(rtems_boolean monitor_suspend) -{ - rtems_status_code status; - - status = rtems_task_create(rtems_build_name('R', 'M', 'O', 'N'), - 1, 0/*stack*/, RTEMS_NO_PREEMPT | RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &rtems_monitor_task_id); - if (status != RTEMS_SUCCESSFUL) - { - printf("could not create monitor task\n"); - goto done; - } - - rtems_monitor_symbols_loadup(); +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" + " 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_OBJECT_CONFIG, + }, + { "itask", + "itask\n" + " List init tasks for the system\n", + 0, + rtems_monitor_object_cmd, + RTEMS_OBJECT_INIT_TASK, + }, + { "mpci", + "mpci\n" + " Show the MPCI system configuration, if configured.\n", + 0, + rtems_monitor_object_cmd, + RTEMS_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_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_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_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_OBJECT_INVALID, + }, + { "driver", + "driver [ major [ major ... ] ]\n" + " Display the RTEMS device driver table.\n", + 0, + rtems_monitor_object_cmd, + RTEMS_OBJECT_DRIVER, + }, + { "dname", + "dname\n" + " Displays information about named drivers.\n", + 0, + rtems_monitor_object_cmd, + RTEMS_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, + CPU_INVOKE_DEBUGGER, + 0, + }, +#endif + { 0, 0, 0, 0, 0 }, +}; - status = rtems_task_start(rtems_monitor_task_id, rtems_monitor_task, monitor_suspend); - if (status != RTEMS_SUCCESSFUL) - { - printf("could not start monitor!\n"); - goto done; - } - -done: -} rtems_status_code rtems_monitor_suspend(rtems_interval timeout) @@ -127,7 +241,10 @@ 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); + status = rtems_event_receive(MONITOR_WAKEUP_EVENT, + RTEMS_DEFAULT_OPTIONS, + timeout, + &event_set); return status; } @@ -140,93 +257,76 @@ rtems_monitor_wakeup(void) } -/* - * 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). - */ +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)); +} -int -rtems_monitor_read_command(char *command, - int *argc, - char **argv) +void +rtems_monitor_fatal_cmd( + int argc, + char **argv, + unsigned32 command_arg, + boolean verbose +) { - printf("%s", MONITOR_PROMPT); fflush(stdout); - while (gets(command) == (char *) 0) - ; - return rtems_monitor_make_argv(command, argc, argv); + if (argc == 1) + rtems_fatal_error_occurred(command_arg); + else + rtems_fatal_error_occurred(strtoul(argv[1], 0, 0)); } void -rtems_monitor_task(rtems_task_argument monitor_suspend) +rtems_monitor_continue_cmd( + int argc, + char **argv, + unsigned32 command_arg, + boolean verbose +) { - rtems_tcb *debugee = 0; - char command[513]; - rtems_context *rp; - rtems_context_fp *fp; - char *cp; - int argc; - char *argv[64]; + rtems_monitor_suspend(RTEMS_NO_TIMEOUT); +} - if ((rtems_boolean) monitor_suspend) - (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT); - for (;;) +void +rtems_monitor_node_cmd( + int argc, + char **argv, + unsigned32 command_arg, + boolean verbose +) +{ + unsigned32 new_node = rtems_monitor_default_node; + + switch (argc) { - extern rtems_tcb * _Thread_Executing; - debugee = _Thread_Executing; - rp = &debugee->Registers; - fp = (rtems_context_fp *) debugee->fp_context; /* possibly 0 */ - - if (0 == rtems_monitor_read_command(command, &argc, argv)) - continue; - - if (STREQ(argv[0], "quit")) - rtems_monitor_suspend(RTEMS_NO_TIMEOUT); - else if (STREQ(argv[0], "pause")) - rtems_monitor_suspend(1); + case 1: /* no node, just set back to ours */ + new_node = rtems_monitor_node; + break; -#ifdef CPU_INVOKE_DEBUGGER - else if (STREQ(argv[0], "debug")) - { - CPU_INVOKE_DEBUGGER; - } -#endif - else if (STREQ(argv[0], "symbol")) - { - char *symbol; - char *value; + case 2: + new_node = strtoul(argv[1], 0, 0); + break; - if (argc != 3) - { - printf("usage: symbol symname symvalue\n"); - continue; - } - - symbol = argv[1]; - value = argv[2]; - if (symbol && value) - { - rtems_symbol_t *sp; - sp = rtems_symbol_create(rtems_monitor_symbols, - symbol, - (rtems_unsigned32) strtoul(value, 0, 16)); - if (sp) - printf("symbol defined is at %p\n", sp); - else - printf("could not define symbol\n"); - } - else - printf("parsing error\n"); - } - else - { - printf("Unrecognized command: '%s'\n", argv[0]); - } + default: + printf("invalid syntax, try 'help node'\n"); + break; } + + if ((new_node >= 1) && (new_node <= _Configuration_MP_table->maximum_nodes)) + rtems_monitor_default_node = new_node; } + /* * Function: rtems_monitor_symbols_loadup * @@ -266,11 +366,19 @@ 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 = fdopen(8, "r"); +#ifdef simhppa + fp = fdopen(8, "r"); /* don't ask; don't tell */ +#else + fp = fopen("symbols", "r"); +#endif + if (fp == 0) return; @@ -292,16 +400,115 @@ rtems_monitor_symbols_loadup(void) (rtems_unsigned32) strtoul(value, 0, 16)); if (sp == 0) { - printf("could not define symbol\n"); + printf("could not define symbol '%s'\n", symbol); goto done; } } else { - printf("parsing error\n"); + printf("parsing error on '%s'\n", buffer); goto done; } } done: } + + +/* + * 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, + 0 /* default stack */, + 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: +} diff --git a/cpukit/libmisc/monitor/mon-mpci.c b/cpukit/libmisc/monitor/mon-mpci.c new file mode 100644 index 0000000000..99dcea3bf8 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-mpci.c @@ -0,0 +1,161 @@ +/* + * @(#)mpci.c 1.6 - 95/08/02 + * + * + * RTEMS MPCI Config display support + * + * TODO + * + * $Id$ + */ + + +#include +#include "monitor.h" + +#include +#include /* 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, + mt->initialization); + + rtems_monitor_symbol_canonical_by_value(&canonical_mpci->get_packet, + mt->get_packet); + rtems_monitor_symbol_canonical_by_value(&canonical_mpci->return_packet, + mt->return_packet); + rtems_monitor_symbol_canonical_by_value(&canonical_mpci->send_packet, + mt->send_packet); + rtems_monitor_symbol_canonical_by_value(&canonical_mpci->receive_packet, + 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; +} diff --git a/cpukit/libmisc/monitor/mon-object.c b/cpukit/libmisc/monitor/mon-object.c new file mode 100644 index 0000000000..5add90763e --- /dev/null +++ b/cpukit/libmisc/monitor/mon-object.c @@ -0,0 +1,376 @@ +/* + * @(#)object.c 1.7 - 95/08/02 + * + * + * 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$ + */ + +#include +#include "monitor.h" + +#include +#include /* strtoul() */ + +#include + +#define NUMELEMS(arr) (sizeof(arr) / sizeof(arr[0])) + +/* + * add: + * next + */ + +rtems_monitor_object_info_t rtems_monitor_object_info[] = +{ + { RTEMS_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_OBJECT_MPCI, + (void *) 0, + 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, + }, + { RTEMS_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_OBJECT_TASK, + (void *) &_Thread_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_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_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_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_OBJECT_DNAME, + (void *) &rtems_driver_name_table[0], + 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_object_type_t type +) +{ + unsigned32 node; + + node = rtems_get_node(id); + if (node == 0) + { +#if 0 + /* XXX Uncomment this when types are added to id's */ + if (rtems_get_type(id) != RTEMS_OBJECT_INVALID) + type = rtems_get_type(id); + + id = _Objects_Build_id(type, default_node, rtems_get_index(id)); +#else + id = _Objects_Build_id(default_node, rtems_get_index(id)); +#endif + } + return id; +} + + +rtems_monitor_object_info_t * +rtems_monitor_object_lookup( + rtems_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_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_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(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_object_type_t type = (rtems_object_type_t) command_arg; + + /* what is the default type? */ + type = (rtems_object_type_t) command_arg; + + if (argc == 1) + { + if (type == RTEMS_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_object_type_t last_type = RTEMS_OBJECT_INVALID; + rtems_id id; + + for (arg=1; argv[arg]; arg++) + { + id = (rtems_id) strtoul(argv[arg], 0, 0); + id = rtems_monitor_id_fixup(id, default_node, type); +#if 0 + type = rtems_get_type(id); +#endif + /* + * 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) + { +not_found: printf("Invalid or unsupported type %d\n", type); + goto done; + } + + if (info->dump_header) + info->dump_header(verbose); + } + + rtems_monitor_object_dump_1(info, id, verbose); + + default_node = rtems_get_node(id); + + last_type = type; + } + } +done: +} diff --git a/cpukit/libmisc/monitor/mon-prmisc.c b/cpukit/libmisc/monitor/mon-prmisc.c new file mode 100644 index 0000000000..0a9f9bdf2e --- /dev/null +++ b/cpukit/libmisc/monitor/mon-prmisc.c @@ -0,0 +1,257 @@ +/* + * @(#)prmisc.c 1.9 - 95/08/02 + * + * + * Print misc stuff for the monitor dump routines + * Each routine returns the number of characters it output. + * + * TODO: + * + * $Id$ + */ + +#include +#include "monitor.h" + +#include + +#include +#include + +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; + 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) +{ + int i; + unsigned32 length = 0; + union { + unsigned32 ui; + char c[4]; + } u; + + u.ui = (rtems_unsigned32) name; + + for (i=0; i +#include "monitor.h" + +#include + +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->maximum_message_size; + canonical_queue->maximum_pending_messages = rtems_queue->maximum_pending_messages; + canonical_queue->number_of_pending_messages = rtems_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"); +} diff --git a/cpukit/libmisc/monitor/mon-server.c b/cpukit/libmisc/monitor/mon-server.c new file mode 100644 index 0000000000..e3e2da5069 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-server.c @@ -0,0 +1,305 @@ +/* + * @(#)server.c 1.3 - 95/08/02 + * + * + * RTEMS monitor server (handles requests for info from RTEMS monitors + * running on other nodes) + * + * $Id$ + */ + +#include + +#include +#include +#include +#include + +#include "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_object_type_t object_type; + rtems_id id; + rtems_id next_id; + + object_type = (rtems_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 (_Configuration_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: +} diff --git a/cpukit/libmisc/monitor/mon-symbols.c b/cpukit/libmisc/monitor/mon-symbols.c index 666860bdab..f0e3ed3bc2 100644 --- a/cpukit/libmisc/monitor/mon-symbols.c +++ b/cpukit/libmisc/monitor/mon-symbols.c @@ -1,6 +1,7 @@ /* - * @(#)symbols.c 1.3 - 95/04/24 + * @(#)symbols.c 1.10 - 95/08/02 * + * $Id$ */ /* #define qsort _quicksort */ @@ -21,34 +22,9 @@ #include #include +#include "monitor.h" #include "symbols.h" -extern rtems_symbol_table_t *rtems_monitor_symbols; - -#ifdef RTEMS_DEBUG -#define CHK_ADR_PTR(p) \ -do { \ - if (((p) < rtems_monitor_symbols->addresses) || \ - ((p) >= (rtems_monitor_symbols->addresses + rtems_monitor_symbols->next))) \ - { \ - printf("bad address pointer %p\n", (p)); \ - rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \ - } \ -} while (0) - -#define CHK_NAME_PTR(p) \ -do { \ - if (((p) < rtems_monitor_symbols->symbols) || \ - ((p) >= (rtems_monitor_symbols->symbols + rtems_monitor_symbols->next))) \ - { \ - printf("bad symbol pointer %p\n", (p)); \ - rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \ - } \ -} while (0) -#else -#define CHK_ADR_PTR(p) -#define CHK_NAME_PTR(p) -#endif rtems_symbol_table_t * rtems_symbol_table_create() @@ -178,9 +154,6 @@ rtems_symbol_compare(const void *e1, s1 = (rtems_symbol_t *) e1; s2 = (rtems_symbol_t *) e2; - CHK_ADR_PTR(s1); - CHK_ADR_PTR(s2); - if (s1->value < s2->value) return -1; if (s1->value > s2->value) @@ -200,9 +173,6 @@ rtems_symbol_string_compare(const void *e1, s1 = (rtems_symbol_t *) e1; s2 = (rtems_symbol_t *) e2; - CHK_NAME_PTR(s1); - CHK_NAME_PTR(s2); - return strcasecmp(s1->name, s2->name); } @@ -252,6 +222,9 @@ rtems_symbol_value_lookup( rtems_unsigned32 best_distance = ~0; rtems_unsigned32 elements; + if (table == 0) + table = rtems_monitor_symbols; + if ((table == 0) || (table->size == 0)) return 0; @@ -300,13 +273,14 @@ rtems_symbol_name_lookup( rtems_symbol_t *sp = 0; rtems_symbol_t key; + if (table == 0) + table = rtems_monitor_symbols; + if ((table == 0) || (name == 0)) goto done; if (table->sorted == 0) - { rtems_symbol_sort(table); - } /* * dummy up one for bsearch() @@ -325,3 +299,192 @@ done: return sp; } +void * +rtems_monitor_symbol_next( + void *object_info, + rtems_monitor_symbol_t *canonical, + rtems_id *next_id +) +{ + rtems_symbol_table_t *table; + int 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->symbols + 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", + sizeof(canonical_symbol->name), + canonical_symbol->name); + else + length += printf("<%.*s+0x%x>", + 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 +) +{ + int 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->symbols; 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"); + } + } +} diff --git a/cpukit/libmisc/monitor/mon-task.c b/cpukit/libmisc/monitor/mon-task.c new file mode 100644 index 0000000000..4e5b80aed6 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-task.c @@ -0,0 +1,85 @@ +/* + * @(#)task.c 1.9 - 95/08/01 + * + * + * RTEMS Monitor task support + * + * $Id$ + */ + +#include +#include "monitor.h" + +#include + +void +rtems_monitor_task_canonical( + rtems_monitor_task_t *canonical_task, + void *thread_void +) +{ + Thread_Control *rtems_thread = (Thread_Control *) thread_void; + + canonical_task->entry = rtems_thread->Start.entry_point; + canonical_task->argument = rtems_thread->Start.initial_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 = rtems_thread->pending_events; + canonical_task->modes = rtems_thread->current_modes; + canonical_task->attributes = rtems_thread->attribute_set; + (void) memcpy(canonical_task->notepad, rtems_thread->Notepads, sizeof(canonical_task->notepad)); + (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"); +} + diff --git a/cpukit/libmisc/monitor/monitor.h b/cpukit/libmisc/monitor/monitor.h index 195aa73695..c9df923928 100644 --- a/cpukit/libmisc/monitor/monitor.h +++ b/cpukit/libmisc/monitor/monitor.h @@ -1,6 +1,7 @@ /* - * @(#)monitor.h 1.2 - 95/04/24 + * @(#)monitor.h 1.14 - 95/08/02 * + * $Id$ */ /* @@ -9,28 +10,430 @@ * Description: * The RTEMS monitor task include file. * - * - * * TODO: - * */ #ifndef __MONITOR_H #define __MONITOR_H +#include "symbols.h" +#include /* rtems_error() */ + #ifdef __cplusplus extern "C" { #endif -void rtems_monitor_init(rtems_boolean monitor_suspend); +/* + * XXX this should be in rtems proper when type becomes part of id + */ + +typedef enum { + RTEMS_OBJECT_INVALID = 0, + RTEMS_OBJECT_TASK = 1, + RTEMS_OBJECT_EXTENSION = 2, + RTEMS_OBJECT_QUEUE = 3, + RTEMS_OBJECT_SEMAPHORE = 4, + RTEMS_OBJECT_DRIVER = 5, + RTEMS_OBJECT_DNAME = 6, + RTEMS_OBJECT_CONFIG = 7, + RTEMS_OBJECT_INIT_TASK = 8, + RTEMS_OBJECT_MPCI = 9, + RTEMS_OBJECT_PARTITION = 10, + RTEMS_OBJECT_REGION = 11, + RTEMS_OBJECT_PORT = 12, + RTEMS_OBJECT_SYMBOL = 13, +} rtems_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 create; + rtems_monitor_symbol_t start; + rtems_monitor_symbol_t restart; + rtems_monitor_symbol_t delete; + rtems_monitor_symbol_t tswitch; + rtems_monitor_symbol_t begin; + rtems_monitor_symbol_t exitted; + rtems_monitor_symbol_t 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 + */ + +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; + +/* + * 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; + rtems_monitor_mpci_t mpci; + 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_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(rtems_boolean); void rtems_monitor_wakeup(void); -void rtems_monitor_task(rtems_task_argument monitor_suspend); +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_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_object_type_t); +rtems_id rtems_monitor_object_canonical_get(rtems_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 */ +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); + +/* 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); +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_unsigned32 rtems_monitor_task_id; 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 diff --git a/cpukit/libmisc/monitor/symbols.h b/cpukit/libmisc/monitor/symbols.h index 680ac6d2cf..736e7a074b 100644 --- a/cpukit/libmisc/monitor/symbols.h +++ b/cpukit/libmisc/monitor/symbols.h @@ -1,5 +1,8 @@ /* - * File: symbols.h + * @(#)symbols.h 1.3 - 95/06/09 + * + * + * RTEMS monitor symbol table functions * * Description: * Entry points for symbol table routines. @@ -8,6 +11,7 @@ * * TODO: * + * $Id$ */ #ifndef _INCLUDE_SYMBOLS_H @@ -61,15 +65,6 @@ typedef struct { } rtems_symbol_table_t; -void rtems_symbol_table_destroy(rtems_symbol_table_t *table); -rtems_symbol_table_t *rtems_symbol_table_create(); -rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, - char *, rtems_unsigned32); -rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, - rtems_unsigned32); -rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, - char *); - #define rtems_symbol_name(sp) ((sp)->name) #define rtems_symbol_value(sp) ((sp)->value) diff --git a/cpukit/rtems/include/rtems/rtems/message.h b/cpukit/rtems/include/rtems/rtems/message.h index aefcea3c36..04aa6dfb16 100644 --- a/cpukit/rtems/include/rtems/rtems/message.h +++ b/cpukit/rtems/include/rtems/rtems/message.h @@ -41,14 +41,22 @@ extern "C" { /* * The following defines the data types needed to manipulate * the contents of message buffers. + * Since msgs are variable length we just make a ptr to 1. */ typedef struct { - unsigned32 field1; - unsigned32 field2; - unsigned32 field3; - unsigned32 field4; -} Message_queue_Buffer; + unsigned32 size; + +#ifndef __cplusplus + /* NOTE: [0] is gcc specific, + * but specifically disallowed by ANSI STD C++ + * g++ warns about it, so we #ifdef it out to + * get rid of warnings when compiled by g++. + */ + unsigned32 buffer[0]; +#endif + +} Message_queue_Buffer; /* * The following records define the organization of a message @@ -68,10 +76,13 @@ typedef struct { typedef struct { Objects_Control Object; Thread_queue_Control Wait_queue; - rtems_attribute attribute_set; + rtems_attribute attribute_set; unsigned32 maximum_pending_messages; unsigned32 number_of_pending_messages; + unsigned32 maximum_message_size; Chain_Control Pending_messages; + Message_queue_Buffer *message_buffers; + Chain_Control Inactive_messages; } Message_queue_Control; /* @@ -81,13 +92,6 @@ typedef struct { EXTERN Objects_Information _Message_queue_Information; -/* - * The following defines the data structures used to - * manage the pool of inactive message buffers. - */ - -EXTERN Chain_Control _Message_queue_Inactive_messages; - /* * The following enumerated type details the modes in which a message * may be submitted to a message queue. The message may be posted @@ -108,8 +112,7 @@ typedef enum { */ void _Message_queue_Manager_initialization( - unsigned32 maximum_message_queues, - unsigned32 maximum_messages + unsigned32 maximum_message_queues ); /* @@ -126,10 +129,11 @@ void _Message_queue_Manager_initialization( */ rtems_status_code rtems_message_queue_create( - Objects_Name name, - unsigned32 count, + Objects_Name name, + unsigned32 count, + unsigned32 max_message_size, rtems_attribute attribute_set, - Objects_Id *id + Objects_Id *id ); /* @@ -183,7 +187,8 @@ rtems_status_code rtems_message_queue_delete( rtems_status_code rtems_message_queue_send( Objects_Id id, - void *buffer + void *buffer, + unsigned32 size ); /* @@ -204,7 +209,8 @@ rtems_status_code rtems_message_queue_send( rtems_status_code rtems_message_queue_urgent( Objects_Id id, - void *buffer + void *buffer, + unsigned32 size ); /* @@ -226,6 +232,7 @@ rtems_status_code rtems_message_queue_urgent( rtems_status_code rtems_message_queue_broadcast( Objects_Id id, void *buffer, + unsigned32 size, unsigned32 *count ); @@ -246,8 +253,9 @@ rtems_status_code rtems_message_queue_broadcast( rtems_status_code rtems_message_queue_receive( Objects_Id id, void *buffer, + unsigned32 *size_p, unsigned32 option_set, - rtems_interval timeout + rtems_interval timeout ); /* @@ -276,8 +284,9 @@ rtems_status_code rtems_message_queue_flush( */ STATIC INLINE void _Message_queue_Copy_buffer ( - Message_queue_Buffer *source, - Message_queue_Buffer *destination + void *source, + void *destination, + unsigned32 size ); /* @@ -295,7 +304,8 @@ STATIC INLINE void _Message_queue_Copy_buffer ( boolean _Message_queue_Seize( Message_queue_Control *the_message_queue, unsigned32 option_set, - Message_queue_Buffer *buffer + void *buffer, + unsigned32 *size_p ); /* @@ -322,7 +332,8 @@ unsigned32 _Message_queue_Flush_support( rtems_status_code _Message_queue_Submit( Objects_Id id, - Message_queue_Buffer *buffer, + void *buffer, + unsigned32 size, Message_queue_Submit_types submit_type ); @@ -336,7 +347,9 @@ rtems_status_code _Message_queue_Submit( */ STATIC INLINE Message_queue_Buffer_control * - _Message_queue_Allocate_message_buffer ( void ); + _Message_queue_Allocate_message_buffer ( + Message_queue_Control *the_message_queue +); /* * _Message_queue_Free_message_buffer @@ -348,6 +361,7 @@ STATIC INLINE Message_queue_Buffer_control * */ STATIC INLINE void _Message_queue_Free_message_buffer ( + Message_queue_Control *the_message_queue, Message_queue_Buffer_control *the_message ); @@ -415,14 +429,17 @@ STATIC INLINE boolean _Message_queue_Is_null ( * the inactive chain of free message queue control blocks. */ -STATIC INLINE Message_queue_Control *_Message_queue_Allocate ( void ); +Message_queue_Control *_Message_queue_Allocate ( + unsigned32 count, + unsigned32 max_message_size +); /* * _Message_queue_Free * * DESCRIPTION: * - * This routine allocates a message queue control block from + * This routine deallocates a message queue control block into * the inactive chain of free message queue control blocks. */ diff --git a/cpukit/rtems/include/rtems/rtems/msgmp.h b/cpukit/rtems/include/rtems/rtems/msgmp.h index 486bf00002..d3e40fe123 100644 --- a/cpukit/rtems/include/rtems/rtems/msgmp.h +++ b/cpukit/rtems/include/rtems/rtems/msgmp.h @@ -55,15 +55,14 @@ typedef enum { */ typedef struct { - rtems_packet_prefix Prefix; + rtems_packet_prefix Prefix; Message_queue_MP_Remote_operations operation; Objects_Name name; - rtems_option option_set; + rtems_option option_set; Objects_Id proxy_id; unsigned32 count; + unsigned32 size; unsigned32 pad0; - unsigned32 pad1; - unsigned32 pad2; Message_queue_Buffer Buffer; } Message_queue_MP_Packet; @@ -95,9 +94,10 @@ void _Message_queue_MP_Send_process_packet ( rtems_status_code _Message_queue_MP_Send_request_packet ( Message_queue_MP_Remote_operations operation, Objects_Id message_queue_id, - Message_queue_Buffer *buffer, - rtems_option option_set, - rtems_interval timeout + void *buffer, + unsigned32 *size_p, + rtems_option option_set, + rtems_interval timeout ); /* diff --git a/cpukit/rtems/inline/rtems/rtems/attr.inl b/cpukit/rtems/inline/rtems/rtems/attr.inl index c657a08211..15a9296b7e 100644 --- a/cpukit/rtems/inline/rtems/rtems/attr.inl +++ b/cpukit/rtems/inline/rtems/rtems/attr.inl @@ -82,19 +82,6 @@ STATIC INLINE boolean _Attributes_Is_priority( return ( attribute_set & RTEMS_PRIORITY ); } -/*PAGE - * - * _Attributes_Is_limit - * - */ - -STATIC INLINE boolean _Attributes_Is_limit( - rtems_attribute attribute_set -) -{ - return ( attribute_set & RTEMS_LIMIT ); -} - /*PAGE * * _Attributes_Is_binary_semaphore diff --git a/cpukit/rtems/inline/rtems/rtems/message.inl b/cpukit/rtems/inline/rtems/rtems/message.inl index ee8d5f6cb1..18d793d2fe 100644 --- a/cpukit/rtems/inline/rtems/rtems/message.inl +++ b/cpukit/rtems/inline/rtems/rtems/message.inl @@ -17,6 +17,8 @@ #ifndef __MESSAGE_QUEUE_inl #define __MESSAGE_QUEUE_inl +#include + /*PAGE * * _Message_queue_Copy_buffer @@ -24,11 +26,12 @@ */ STATIC INLINE void _Message_queue_Copy_buffer ( - Message_queue_Buffer *source, - Message_queue_Buffer *destination + void *source, + void *destination, + unsigned32 size ) { - *destination = *source; + memcpy(destination, source, size); } /*PAGE @@ -38,10 +41,12 @@ STATIC INLINE void _Message_queue_Copy_buffer ( */ STATIC INLINE Message_queue_Buffer_control * - _Message_queue_Allocate_message_buffer ( void ) +_Message_queue_Allocate_message_buffer ( + Message_queue_Control *the_message_queue +) { return (Message_queue_Buffer_control *) - _Chain_Get( &_Message_queue_Inactive_messages ); + _Chain_Get( &the_message_queue->Inactive_messages ); } /*PAGE @@ -51,10 +56,11 @@ STATIC INLINE Message_queue_Buffer_control * */ STATIC INLINE void _Message_queue_Free_message_buffer ( - Message_queue_Buffer_control *the_message + Message_queue_Control *the_message_queue, + Message_queue_Buffer_control *the_message ) { - _Chain_Append( &_Message_queue_Inactive_messages, &the_message->Node ); + _Chain_Append( &the_message_queue->Inactive_messages, &the_message->Node ); } /*PAGE @@ -116,17 +122,6 @@ STATIC INLINE boolean _Message_queue_Is_null ( return ( the_message_queue == NULL ); } -/*PAGE - * - * _Message_queue_Allocate - * - */ - -STATIC INLINE Message_queue_Control *_Message_queue_Allocate ( void ) -{ - return (Message_queue_Control *) - _Objects_Allocate( &_Message_queue_Information ); -} /*PAGE * @@ -138,6 +133,12 @@ STATIC INLINE void _Message_queue_Free ( Message_queue_Control *the_message_queue ) { + if (the_message_queue->message_buffers) + { + _Workspace_Free((void *) the_message_queue->message_buffers); + the_message_queue->message_buffers = 0; + } + _Objects_Free( &_Message_queue_Information, &the_message_queue->Object ); } diff --git a/cpukit/rtems/macros/rtems/rtems/attr.inl b/cpukit/rtems/macros/rtems/rtems/attr.inl index 602622ca35..97d3463d53 100644 --- a/cpukit/rtems/macros/rtems/rtems/attr.inl +++ b/cpukit/rtems/macros/rtems/rtems/attr.inl @@ -60,15 +60,6 @@ #define _Attributes_Is_priority( _attribute_set ) \ ( (_attribute_set) & RTEMS_PRIORITY ) -/*PAGE - * - * _Attributes_Is_limit - * - */ - -#define _Attributes_Is_limit( _attribute_set ) \ - ( (_attribute_set) & RTEMS_LIMIT ) - /*PAGE * * _Attributes_Is_binary_semaphore diff --git a/cpukit/sapi/include/rtems/config.h b/cpukit/sapi/include/rtems/config.h index b5080b6133..c2001c8074 100644 --- a/cpukit/sapi/include/rtems/config.h +++ b/cpukit/sapi/include/rtems/config.h @@ -32,14 +32,14 @@ extern "C" { */ typedef struct { - Objects_Name name; /* task name */ - unsigned32 stack_size; /* task stack size */ + Objects_Name name; /* task name */ + unsigned32 stack_size; /* task stack size */ rtems_task_priority initial_priority; /* task priority */ - rtems_attribute attribute_set; /* task attributes */ - rtems_task_entry entry_point; /* task entry point */ - rtems_mode mode_set; /* task initial mode */ - unsigned32 argument; /* task argument */ -} rtems_initialization_tasks_table; + rtems_attribute attribute_set; /* task attributes */ + rtems_task_entry entry_point; /* task entry point */ + rtems_mode mode_set; /* task initial mode */ + unsigned32 argument; /* task argument */ +} rtems_initialization_tasks_table; /* * @@ -56,14 +56,12 @@ typedef struct { typedef unsigned32 rtems_device_major_number; typedef unsigned32 rtems_device_minor_number; -typedef void rtems_device_driver; +typedef rtems_status_code rtems_device_driver; typedef rtems_device_driver ( *rtems_device_driver_entry )( rtems_device_major_number, rtems_device_minor_number, - void *, - Objects_Id, - unsigned32 * + void * ); typedef struct { @@ -173,12 +171,13 @@ typedef rtems_mpci_entry ( *rtems_mpci_receive_entry )( typedef struct { unsigned32 default_timeout; /* in ticks */ + unsigned32 maximum_packet_size; rtems_mpci_initialization_entry initialization; rtems_mpci_get_packet_entry get_packet; rtems_mpci_return_packet_entry return_packet; rtems_mpci_send_entry send_packet; rtems_mpci_receive_entry receive_packet; -} rtems_mpci_table; +} rtems_mpci_table; /* * The following records define the Multiprocessor Configuration @@ -192,8 +191,7 @@ struct Configuration_Table_MP { unsigned32 maximum_nodes; /* maximum # nodes in system */ unsigned32 maximum_global_objects; /* maximum # global objects */ unsigned32 maximum_proxies; /* maximum # proxies */ - rtems_mpci_table *User_mpci_table; - /* pointer to MPCI table */ + rtems_mpci_table *User_mpci_table; /* pointer to MPCI table */ }; /* @@ -209,25 +207,24 @@ struct Configuration_Table_MP { */ struct Configuration_Table { - void *work_space_start; - unsigned32 work_space_size; - unsigned32 maximum_tasks; - unsigned32 maximum_timers; - unsigned32 maximum_semaphores; - unsigned32 maximum_message_queues; - unsigned32 maximum_messages; - 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; + 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_initialization_tasks_table *User_initialization_tasks_table; - unsigned32 number_of_device_drivers; + unsigned32 number_of_device_drivers; rtems_driver_address_table *Device_driver_table; - rtems_extensions_table *User_extension_table; + rtems_extensions_table *User_extension_table; rtems_multiprocessing_table *User_multiprocessing_table; }; @@ -244,7 +241,7 @@ extern const rtems_multiprocessing_table * configuration information. */ -EXTERN rtems_configuration_table *_Configuration_Table; +EXTERN rtems_configuration_table *_Configuration_Table; EXTERN rtems_multiprocessing_table *_Configuration_MP_table; EXTERN rtems_mpci_table *_Configuration_MPCI_table; @@ -258,7 +255,7 @@ EXTERN rtems_mpci_table *_Configuration_MPCI_table; */ STATIC INLINE void _Configuration_Handler_initialization( - rtems_configuration_table *configuration_table, + rtems_configuration_table *configuration_table, rtems_multiprocessing_table *multiprocessing_table, rtems_mpci_table *users_mpci_table ); diff --git a/cpukit/sapi/include/rtems/io.h b/cpukit/sapi/include/rtems/io.h index 43c52cd35d..ef9fc69d03 100644 --- a/cpukit/sapi/include/rtems/io.h +++ b/cpukit/sapi/include/rtems/io.h @@ -35,27 +35,30 @@ extern "C" { #include /* - * The following type defines the set of IO operations which are - * recognized by _IO_Handler and can be supported by a RTEMS - * device driver. + * The following declare the data required to manage the Device Driver + * Address Table. */ -typedef enum { - IO_INITIALIZE_OPERATION = 0, - IO_OPEN_OPERATION = 1, - IO_CLOSE_OPERATION = 2, - IO_READ_OPERATION = 3, - IO_WRITE_OPERATION = 4, - IO_CONTROL_OPERATION = 5 -} IO_operations; +EXTERN unsigned32 _IO_Number_of_drivers; +EXTERN rtems_driver_address_table *_IO_Driver_address_table; /* - * The following declare the data required to manage the Device Driver - * Address Table. + * Table for the io device names */ -EXTERN unsigned32 _IO_Number_of_drivers; -EXTERN rtems_driver_address_table *_IO_Driver_address_table; +typedef struct { + char *device_name; + unsigned32 device_name_length; + rtems_device_major_number major; + rtems_device_minor_number minor; +} rtems_driver_name_t; + +/*XXX this really should be allocated some better way... */ +/*XXX it should probably be a chain and use a 'maximum' drivers field + * in config table */ +#define RTEMS_MAX_DRIVER_NAMES 20 +EXTERN rtems_driver_name_t rtems_driver_name_table[RTEMS_MAX_DRIVER_NAMES]; + /* * _IO_Manager_initialization @@ -70,6 +73,36 @@ STATIC INLINE void _IO_Manager_initialization( unsigned32 number_of_drivers ); +/* + * rtems_io_register_name + * + * DESCRIPTION: + * + * Associate a name with a driver. + * + */ + +rtems_status_code rtems_io_register_name( + char *device_name, + rtems_device_major_number major, + rtems_device_minor_number minor +); + + +/* + * rtems_io_lookup_name + * + * DESCRIPTION: + * + * Find what driver "owns" this name + */ + +rtems_status_code rtems_io_lookup_name( + const char *pathname, + rtems_driver_name_t **rnp +); + + /* * rtems_io_initialize * @@ -82,8 +115,7 @@ STATIC INLINE void _IO_Manager_initialization( rtems_status_code rtems_io_initialize( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -98,8 +130,7 @@ rtems_status_code rtems_io_initialize( rtems_status_code rtems_io_open( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -114,8 +145,7 @@ rtems_status_code rtems_io_open( rtems_status_code rtems_io_close( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -130,8 +160,7 @@ rtems_status_code rtems_io_close( rtems_status_code rtems_io_read( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -146,8 +175,7 @@ rtems_status_code rtems_io_read( rtems_status_code rtems_io_write( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -162,8 +190,7 @@ rtems_status_code rtems_io_write( rtems_status_code rtems_io_control( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ); /* @@ -177,23 +204,6 @@ rtems_status_code rtems_io_control( void _IO_Initialize_all_drivers( void ); -/* - * _IO_Handler_routine - * - * DESCRIPTION: - * - * This routine provides the common foundation for all of the IO - * Manager's directives. - */ - -rtems_status_code _IO_Handler_routine( - IO_operations operation, - rtems_device_major_number major, - rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value -); - #include #ifdef __cplusplus diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c index 984dca68be..2d3261c256 100644 --- a/cpukit/sapi/src/exinit.c +++ b/cpukit/sapi/src/exinit.c @@ -177,8 +177,7 @@ rtems_interrupt_level rtems_initialize_executive_early( _Event_Manager_initialization(); _Message_queue_Manager_initialization( - configuration_table->maximum_message_queues, - configuration_table->maximum_messages + configuration_table->maximum_message_queues ); _Semaphore_Manager_initialization( diff --git a/cpukit/sapi/src/io.c b/cpukit/sapi/src/io.c index 916053da7e..4ab45b33f5 100644 --- a/cpukit/sapi/src/io.c +++ b/cpukit/sapi/src/io.c @@ -18,6 +18,9 @@ #include #include #include +#include + +#include /*PAGE * @@ -33,12 +36,82 @@ void _IO_Initialize_all_drivers( void ) { rtems_device_major_number major; - unsigned32 ignored; for ( major=0 ; major < _IO_Number_of_drivers ; major ++ ) - (void) rtems_io_initialize( major, 0, _Configuration_Table, &ignored ); + (void) rtems_io_initialize( major, 0, _Configuration_Table); +} + +/*PAGE + * + * rtems_io_register_name + * + * Associate a name with a driver + * + * Input Paramters: + * + * Output Parameters: + */ + +rtems_status_code rtems_io_register_name( + char *device_name, + rtems_device_major_number major, + rtems_device_minor_number minor + ) +{ + rtems_driver_name_t *np; + unsigned32 level; + + /* find an empty slot */ + for (np = rtems_driver_name_table; np < &rtems_driver_name_table[RTEMS_MAX_DRIVER_NAMES]; np++) + { + rtems_interrupt_disable(level); + if (np->device_name == 0) + { + np->device_name = device_name; + np->device_name_length = strlen(device_name); + np->major = major; + np->minor = minor; + rtems_interrupt_enable(level); + + return RTEMS_SUCCESSFUL; + } + rtems_interrupt_enable(level); + } + + return RTEMS_TOO_MANY; +} + +/*PAGE + * + * rtems_io_lookup_name + * + * Find what driver "owns" this name + * + * Input Paramters: + * + * Output Parameters: + */ + +rtems_status_code rtems_io_lookup_name( + const char *pathname, + rtems_driver_name_t **rnp + ) +{ + rtems_driver_name_t *np; + + for (np = rtems_driver_name_table; np < &rtems_driver_name_table[RTEMS_MAX_DRIVER_NAMES]; np++) + if (np->device_name) + if (strncmp(np->device_name, pathname, np->device_name_length) == 0) + { + *rnp = np; + return RTEMS_SUCCESSFUL; + } + + *rnp = 0; + return RTEMS_UNSATISFIED; } + /*PAGE * * rtems_io_initialize @@ -49,27 +122,24 @@ void _IO_Initialize_all_drivers( void ) * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_initialize( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_INITIALIZE_OPERATION, - major, - minor, - argument, - return_value - ); + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; + + callout = _IO_Driver_address_table[major].initialization; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } /*PAGE @@ -82,27 +152,24 @@ rtems_status_code rtems_io_initialize( * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_open( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_OPEN_OPERATION, - major, - minor, - argument, - return_value - ); + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; + + callout = _IO_Driver_address_table[major].open; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } /*PAGE @@ -115,27 +182,24 @@ rtems_status_code rtems_io_open( * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_close( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_CLOSE_OPERATION, - major, - minor, - argument, - return_value - ); + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; + + callout = _IO_Driver_address_table[major].close; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } /*PAGE @@ -148,27 +212,24 @@ rtems_status_code rtems_io_close( * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_read( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_READ_OPERATION, - major, - minor, - argument, - return_value - ); + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; + + callout = _IO_Driver_address_table[major].read; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } /*PAGE @@ -181,27 +242,24 @@ rtems_status_code rtems_io_read( * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_write( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_WRITE_OPERATION, - major, - minor, - argument, - return_value - ); + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; + + callout = _IO_Driver_address_table[major].write; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } /*PAGE @@ -214,103 +272,23 @@ rtems_status_code rtems_io_write( * major - device driver number * minor - device number * argument - pointer to argument(s) - * return_value - pointer to driver's return value * * Output Parameters: * returns - return code - * *return_value - driver's return code */ rtems_status_code rtems_io_control( rtems_device_major_number major, rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value + void *argument ) { - return _IO_Handler_routine( - IO_CONTROL_OPERATION, - major, - minor, - argument, - return_value - ); -} - -/*PAGE - * - * _IO_Handler_routine - * - * This routine implements all IO manager directives. - * - * Input Paramters: - * operation - I/O operation to be performed - * major - device driver number - * minor - device number - * argument - pointer to argument(s) - * return_value - pointer to driver's return value - * - * Output Parameters: - * returns - return code - * *return_value - driver's return code - */ + rtems_device_driver_entry callout; + + if ( major >= _IO_Number_of_drivers ) + return RTEMS_INVALID_NUMBER; -rtems_status_code _IO_Handler_routine( - IO_operations operation, - rtems_device_major_number major, - rtems_device_minor_number minor, - void *argument, - unsigned32 *return_value -) -{ - rtems_device_driver_entry io_callout; - - /* - * NOTE: There is no range checking as in Ada because: - * + arrays in Ada are not always zero based. - * + with zero based arrays, a comparison of an unsigned - * number being less than zero would be necessary to - * check it as a range. This would cause a warning for - * checking an unsigned number for being negative. - */ - - if ( major >= _IO_Number_of_drivers ) - return ( RTEMS_INVALID_NUMBER ); - - switch ( operation ) { - case IO_INITIALIZE_OPERATION: - io_callout = _IO_Driver_address_table[ major ].initialization; - break; - case IO_OPEN_OPERATION: - io_callout = _IO_Driver_address_table[ major ].open; - break; - case IO_CLOSE_OPERATION: - io_callout = _IO_Driver_address_table[ major ].close; - break; - case IO_READ_OPERATION: - io_callout = _IO_Driver_address_table[ major ].read; - break; - case IO_WRITE_OPERATION: - io_callout = _IO_Driver_address_table[ major ].write; - break; - case IO_CONTROL_OPERATION: - io_callout = _IO_Driver_address_table[ major ].control; - break; - default: /* unreached -- only to remove warnings */ - io_callout = NULL; - break; - } - - if ( io_callout != NULL ) - (*io_callout)( - major, - minor, - argument, - _Thread_Executing->Object.id, - return_value - ); - else - *return_value = 0; - - return( RTEMS_SUCCESSFUL ); + callout = _IO_Driver_address_table[major].control; + return callout ? callout(major, minor, argument) : RTEMS_SUCCESSFUL; } + diff --git a/cpukit/score/include/rtems/score/object.h b/cpukit/score/include/rtems/score/object.h index 50eede9fd7..0553fe901d 100644 --- a/cpukit/score/include/rtems/score/object.h +++ b/cpukit/score/include/rtems/score/object.h @@ -99,6 +99,18 @@ EXTERN unsigned32 _Objects_Local_node; #define RTEMS_SEARCH_LOCAL_NODE 0x7FFFFFFF #define RTEMS_WHO_AM_I 0 +/* + * Parameters and return id's for _Objects_Get_next + */ + +#define RTEMS_OBJECT_ID_INITIAL_INDEX (0) +#define RTEMS_OBJECT_ID_FINAL_INDEX (0xffff) + +#define RTEMS_OBJECT_ID_INITIAL(node) (_Objects_Build_id( \ + node, \ + RTEMS_OBJECT_ID_INITIAL_INDEX)) +#define RTEMS_OBJECT_ID_FINAL ((Objects_Id) ~0) + /* * _Objects_Handler_initialization * @@ -178,6 +190,22 @@ Objects_Control *_Objects_Get ( Objects_Locations *location ); +/* + * _Objects_Get_next + * + * DESCRIPTION: + * + * Like _Objects_Get, but is used to find "next" open object. + * + */ + +Objects_Control *_Objects_Get_next( + Objects_Information *information, + Objects_Id id, + unsigned32 *location_p, + Objects_Id *next_id_p +); + /* * _Objects_Is_name_valid * diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 4a417828a3..953e19ba95 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -115,6 +115,7 @@ typedef struct { union { unsigned32 segment_size; /* size of segment requested */ rtems_event_set event_condition; + unsigned32 *message_size_p; /* ptr for return size of message */ } Extra; void *return_argument; /* address of user return param */ rtems_status_code return_code; /* status for thread awakened */ diff --git a/cpukit/score/include/rtems/system.h b/cpukit/score/include/rtems/system.h index 3ff3772d11..96b0abfff8 100644 --- a/cpukit/score/include/rtems/system.h +++ b/cpukit/score/include/rtems/system.h @@ -78,6 +78,7 @@ typedef void * proc_ptr; #include /* processor specific information */ #include /* RTEMS status codes */ +#include /* * Define NULL @@ -103,6 +104,9 @@ typedef void * proc_ptr; #define stringify( _x ) # _x +#define RTEMS_offsetof(type, field) \ + ((unsigned32) &(((type *) 0)->field)) + /* * The following is the extern for the RTEMS version string. * The contents of this string are CPU specific. @@ -115,8 +119,7 @@ extern const char _Copyright_Notice[]; /* RTEMS copyright string */ * The jump table of entry points into RTEMS directives. */ -#define NUMBER_OF_ENTRY_POINTS 79 -extern const void * _Entry_points[ NUMBER_OF_ENTRY_POINTS + 1 ]; +extern const void * _Entry_points[ RTEMS_NUMBER_OF_ENTRY_POINTS ]; /* * The following defines the CPU dependent information table. diff --git a/cpukit/score/src/object.c b/cpukit/score/src/object.c index 71c365fa1e..29450d4171 100644 --- a/cpukit/score/src/object.c +++ b/cpukit/score/src/object.c @@ -12,6 +12,7 @@ * * $Id$ */ + #include #include #include @@ -226,3 +227,69 @@ Objects_Control *_Objects_Get( _Objects_MP_Is_remote( information, id, location, &the_object ); return the_object; } + + +/*PAGE + * + * _Objects_Get_next + * + * Like _Objects_Get, but considers the 'id' as a "hint" and + * finds next valid one after that point. + * Mostly used for monitor and debug traversal of an object. + * + * Input parameters: + * information - pointer to entry in table for this class + * id - object id to search for + * location - address of where to store the location + * next_id - address to store next id to try + * + * Output parameters: + * returns - address of object if local + * location - one of the following: + * OBJECTS_ERROR - invalid object ID + * OBJECTS_REMOTE - remote object + * OBJECTS_LOCAL - local object + * next_id - will contain a reasonable "next" id to continue traversal + * + * NOTE: + * assumes can add '1' to an id to get to next index. + */ + +Objects_Control * +_Objects_Get_next( + Objects_Information *information, + Objects_Id id, + unsigned32 *location_p, + Objects_Id *next_id_p +) +{ + Objects_Control *object; + Objects_Id next_id; + + if (rtems_get_index(id) == RTEMS_OBJECT_ID_INITIAL_INDEX) + next_id = information->minimum_id; + else + next_id = id; + + do { + /* walked off end of list? */ + if (next_id > information->maximum_id) + { + *location_p = OBJECTS_ERROR; + goto final; + } + + /* try to grab one */ + object = _Objects_Get(information, next_id, location_p); + + next_id++; + + } while (*location_p != OBJECTS_LOCAL); + + *next_id_p = next_id; + return object; + +final: + *next_id_p = RTEMS_OBJECT_ID_FINAL; + return 0; +} -- cgit v1.2.3