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/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 +- 18 files changed, 3174 insertions(+), 223 deletions(-) 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/libmisc/monitor') 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) -- cgit v1.2.3