diff -r dfca1120813f tools/xenmon/xenbaked.c --- a/tools/xenmon/xenbaked.c Sun Nov 11 18:28:57 2007 +0000 +++ b/tools/xenmon/xenbaked.c Tue Nov 13 11:05:41 2007 +0100 @@ -37,12 +37,12 @@ #include #include #include -#include #include #include #include #include #include +#include #define PERROR(_m, _a...) \ do { \ @@ -58,7 +58,6 @@ typedef struct { int counter; } atomic_t #include #include "xenbaked.h" -extern FILE *stderr; /***** Compile time configuration of defaults ********************************/ @@ -78,7 +77,6 @@ extern FILE *stderr; /***** The code **************************************************************/ typedef struct settings_st { - char *outfile; struct timespec poll_sleep; unsigned long new_data_thresh; unsigned long ms_per_sample; @@ -230,10 +228,10 @@ void dump_stats(void) } printf("processed %d total records in %d seconds (%ld per second)\n", - rec_count, (int)run_time, rec_count/run_time); + rec_count, (int)run_time, (long)(rec_count/run_time)); printf("woke up %d times in %d seconds (%ld per second)\n", wakeups, - (int) run_time, wakeups/run_time); + (int) run_time, (long)(wakeups/run_time)); check_gotten_sum(); } @@ -535,58 +533,106 @@ int monitor_tbufs(void) /****************************************************************************** - * Various declarations / definitions GNU argp needs to do its work + * Command line handling *****************************************************************************/ - -/* command parser for GNU argp - see GNU docs for more info */ -error_t cmd_parser(int key, char *arg, struct argp_state *state) -{ - settings_t *setup = (settings_t *)state->input; - - switch ( key ) +const char *program_version = "xenbaked v1.4"; +const char *program_bug_address = ""; + +#define xstr(x) str(x) +#define str(x) #x + +void usage(void) +{ +#define USAGE_STR \ +"Usage: xenbaked [OPTION...]\n" \ +"Tool to capture and partially process Xen trace buffer data\n" \ +"\n" \ +" -m, --ms_per_sample=MS Specify the number of milliseconds per sample\n" \ +" (default " xstr(MS_PER_SAMPLE) ").\n" \ +" -s, --poll-sleep=p Set sleep time, p, in milliseconds between\n" \ +" polling the trace buffer for new data\n" \ +" (default " xstr(POLL_SLEEP_MILLIS) ").\n" \ +" -t, --log-thresh=l Set number, l, of new records required to\n" \ +" trigger a write to output (default " \ + xstr(NEW_DATA_THRESH) ").\n" \ +" -?, --help Show this message\n" \ +" -V, --version Print program version\n" \ +"\n" \ +"This tool is used to capture trace buffer data from Xen. The data is\n" \ +"saved in a shared memory structure to be further processed by xenmon.\n" + + printf(USAGE_STR); + printf("\nReport bugs to %s\n", program_bug_address); + + exit(EXIT_FAILURE); +} + +/* convert the argument string pointed to by arg to a long int representation */ +long argtol(const char *restrict arg, int base) +{ + char *endp; + long val; + + errno = 0; + val = strtol(arg, &endp, base); + + if (errno != 0) { + fprintf(stderr, "Invalid option argument: %s\n", arg); + fprintf(stderr, "Error: %s\n\n", strerror(errno)); + usage(); + } else if (endp == arg || *endp != '\0') { + fprintf(stderr, "Invalid option argument: %s\n\n", arg); + usage(); + } + + return val; +} + +/* parse command line arguments */ +void parse_args(int argc, char **argv) +{ + int option; + static struct option long_options[] = { + { "log-thresh", required_argument, 0, 't' }, + { "poll-sleep", required_argument, 0, 's' }, + { "ms_per_sample", required_argument, 0, 'm' }, + { "help", no_argument, 0, '?' }, + { "version", no_argument, 0, 'V' }, + { 0, 0, 0, 0 } + }; + + while ( (option = getopt_long(argc, argv, "m:s:t:?V", + long_options, NULL)) != -1) { - case 't': /* set new records threshold for logging */ - { - char *inval; - setup->new_data_thresh = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 's': /* set sleep time (given in milliseconds) */ - { - char *inval; - setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0)); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 'm': /* set ms_per_sample */ - { - char *inval; - setup->ms_per_sample = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); - } - break; - - case ARGP_KEY_ARG: - { - if ( state->arg_num == 0 ) - setup->outfile = arg; - else - argp_usage(state); - } - break; - - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; + switch ( option ) + { + case 't': /* set new records threshold for logging */ + opts.new_data_thresh = argtol(optarg, 0); + break; + + case 's': /* set sleep time (given in milliseconds) */ + opts.poll_sleep = millis_to_timespec(argtol(optarg, 0)); + break; + + case 'm': /* set ms_per_sample */ + opts.ms_per_sample = argtol(optarg, 0); + break; + + case 'V': /* print program version */ + printf("%s\n", program_version); + exit(EXIT_SUCCESS); + break; + + default: + usage(); + } + } + + /* all arguments should have been processed */ + if (optind != argc) { + usage(); + } } #define SHARED_MEM_FILE "/var/run/xenq-shm" @@ -637,59 +683,18 @@ void alloc_qos_data(int ncpu) } -#define xstr(x) str(x) -#define str(x) #x - -const struct argp_option cmd_opts[] = -{ - { .name = "log-thresh", .key='t', .arg="l", - .doc = - "Set number, l, of new records required to trigger a write to output " - "(default " xstr(NEW_DATA_THRESH) ")." }, - - { .name = "poll-sleep", .key='s', .arg="p", - .doc = - "Set sleep time, p, in milliseconds between polling the trace buffer " - "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." }, - - { .name = "ms_per_sample", .key='m', .arg="MS", - .doc = - "Specify the number of milliseconds per sample " - " (default " xstr(MS_PER_SAMPLE) ")." }, - - {0} -}; - -const struct argp parser_def = -{ - .options = cmd_opts, - .parser = cmd_parser, - // .args_doc = "[output file]", - .doc = - "Tool to capture and partially process Xen trace buffer data" - "\v" - "This tool is used to capture trace buffer data from Xen. The data is " - "saved in a shared memory structure to be further processed by xenmon." -}; - - -const char *argp_program_version = "xenbaked v1.4"; -const char *argp_program_bug_address = ""; - - int main(int argc, char **argv) { int ret; struct sigaction act; time(&start_time); - opts.outfile = 0; opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS); opts.new_data_thresh = NEW_DATA_THRESH; opts.ms_per_sample = MS_PER_SAMPLE; opts.cpu_freq = CPU_FREQ; - argp_parse(&parser_def, argc, argv, 0, 0, &opts); + parse_args(argc, argv); fprintf(stderr, "ms_per_sample = %ld\n", opts.ms_per_sample); diff -r dfca1120813f tools/xentrace/xenctx.c --- a/tools/xentrace/xenctx.c Sun Nov 11 18:28:57 2007 +0000 +++ b/tools/xentrace/xenctx.c Tue Nov 13 11:05:41 2007 +0100 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -32,10 +31,15 @@ int stack_trace = 0; int stack_trace = 0; #if defined (__i386__) +#if defined (__OpenBSD__) +#define FMT_SIZE_T "%08lx" +#define INSTR_POINTER(regs) (unsigned long)(regs->eip) +#else #define FMT_SIZE_T "%08x" +#define INSTR_POINTER(regs) (regs->eip) +#endif #define STACK_POINTER(regs) (regs->esp) #define FRAME_POINTER(regs) (regs->ebp) -#define INSTR_POINTER(regs) (regs->eip) #define STACK_ROWS 4 #define STACK_COLS 8 #elif defined (__x86_64__) @@ -622,7 +626,8 @@ void print_stack(vcpu_guest_context_t *c printf("Stack Trace:\n"); else printf("Call Trace:\n"); - printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs)); + printf("%c [<" FMT_SIZE_T ">] ", + stack_trace ? '*' : ' ', INSTR_POINTER(regs)); print_symbol(INSTR_POINTER(regs)); printf(" <--\n"); diff -r dfca1120813f tools/xentrace/xentrace.c --- a/tools/xentrace/xentrace.c Sun Nov 11 18:28:57 2007 +0000 +++ b/tools/xentrace/xentrace.c Tue Nov 13 11:05:41 2007 +0100 @@ -18,10 +18,10 @@ #include #include #include -#include #include #include #include +#include #include #include @@ -37,7 +37,6 @@ do { errno = __saved_errno; \ } while (0) -extern FILE *stderr; /***** Compile time configuration of defaults ********************************/ @@ -411,166 +410,155 @@ int monitor_tbufs(int outfd) /****************************************************************************** - * Various declarations / definitions GNU argp needs to do its work + * Command line handling *****************************************************************************/ -int parse_evtmask(char *arg, struct argp_state *state) -{ - settings_t *setup = (settings_t *)state->input; - char *inval; - +#define xstr(x) str(x) +#define str(x) #x + +const char *program_version = "xentrace v1.1"; +const char *program_bug_address = ""; + +void usage(void) +{ +#define USAGE_STR \ +"Usage: xentrace [OPTION...] [output file]\n" \ +"Tool to capture Xen trace buffer data\n" \ +"\n" \ +" -c, --cpu-mask=c Set cpu-mask\n" \ +" -e, --evt-mask=e Set evt-mask\n" \ +" -s, --poll-sleep=p Set sleep time, p, in milliseconds between\n" \ +" polling the trace buffer for new data\n" \ +" (default " xstr(POLL_SLEEP_MILLIS) ").\n" \ +" -S, --trace-buf-size=N Set trace buffer size in pages (default " \ + xstr(DEFAULT_TBUF_SIZE) ").\n" \ +" N.B. that the trace buffer cannot be resized.\n" \ +" if it has already been set this boot cycle,\n" \ +" this argument will be ignored.\n" \ +" -t, --log-thresh=l Set number, l, of new records required to\n" \ +" trigger a write to output (default " \ + xstr(NEW_DATA_THRESH) ").\n" \ +" -?, --help Show this message\n" \ +" -V, --version Print program version\n" \ +"\n" \ +"This tool is used to capture trace buffer data from Xen. The\n" \ +"data is output in a binary format, in the following order:\n" \ +"\n" \ +" CPU(uint) TSC(uint64_t) EVENT(uint32_t) D1 D2 D3 D4 D5 (all uint32_t)\n" \ +"\n" \ +"The output should be parsed using the tool xentrace_format,\n" \ +"which can produce human-readable output in ASCII format.\n" + + printf(USAGE_STR); + printf("\nReport bugs to %s\n", program_bug_address); + + exit(EXIT_FAILURE); +} + +/* convert the argument string pointed to by arg to a long int representation */ +long argtol(const char *restrict arg, int base) +{ + char *endp; + long val; + + errno = 0; + val = strtol(arg, &endp, base); + + if (errno != 0) { + fprintf(stderr, "Invalid option argument: %s\n", arg); + fprintf(stderr, "Error: %s\n\n", strerror(errno)); + usage(); + } else if (endp == arg || *endp != '\0') { + fprintf(stderr, "Invalid option argument: %s\n\n", arg); + usage(); + } + + return val; +} + +int parse_evtmask(char *arg) +{ /* search filtering class */ if (strcmp(arg, "gen") == 0){ - setup->evt_mask |= TRC_GEN; + opts.evt_mask |= TRC_GEN; } else if(strcmp(arg, "sched") == 0){ - setup->evt_mask |= TRC_SCHED; + opts.evt_mask |= TRC_SCHED; } else if(strcmp(arg, "dom0op") == 0){ - setup->evt_mask |= TRC_DOM0OP; + opts.evt_mask |= TRC_DOM0OP; } else if(strcmp(arg, "hvm") == 0){ - setup->evt_mask |= TRC_HVM; + opts.evt_mask |= TRC_HVM; } else if(strcmp(arg, "all") == 0){ - setup->evt_mask |= TRC_ALL; + opts.evt_mask |= TRC_ALL; } else { - setup->evt_mask = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); + opts.evt_mask = argtol(arg, 0); } return 0; - -} - -/* command parser for GNU argp - see GNU docs for more info */ -error_t cmd_parser(int key, char *arg, struct argp_state *state) -{ - settings_t *setup = (settings_t *)state->input; - - switch ( key ) - { - case 't': /* set new records threshold for logging */ - { - char *inval; - setup->new_data_thresh = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 's': /* set sleep time (given in milliseconds) */ - { - char *inval; - setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0)); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 'c': /* set new cpu mask for filtering*/ - { - char *inval; - setup->cpu_mask = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 'e': /* set new event mask for filtering*/ - { - parse_evtmask(arg, state); - } - break; - - case 'S': /* set tbuf size (given in pages) */ - { - char *inval; - setup->tbuf_size = strtol(arg, &inval, 0); - if ( inval == arg ) - argp_usage(state); - } - break; - - case 'D': /* Discard traces currently in the buffer before beginning */ - { - opts.discard = 1; - } - break; - - case ARGP_KEY_ARG: - { - if ( state->arg_num == 0 ) - setup->outfile = arg; - else - argp_usage(state); - } - break; +} + +/* parse command line arguments */ +void parse_args(int argc, char **argv) +{ + int option; + static struct option long_options[] = { + { "log-thresh", required_argument, 0, 't' }, + { "poll-sleep", required_argument, 0, 's' }, + { "cpu-mask", required_argument, 0, 'c' }, + { "evt-mask", required_argument, 0, 'e' }, + { "trace-buf-size", required_argument, 0, 'S' }, + { "help", no_argument, 0, '?' }, + { "version", no_argument, 0, 'V' }, + { 0, 0, 0, 0 } + }; + + while ( (option = getopt_long(argc, argv, "c:e:s:S:t:?V", + long_options, NULL)) != -1) + { + switch ( option ) + { + case 't': /* set new records threshold for logging */ + opts.new_data_thresh = argtol(optarg, 0); + break; + + case 's': /* set sleep time (given in milliseconds) */ + opts.poll_sleep = millis_to_timespec(argtol(optarg, 0)); + break; + + case 'c': /* set new cpu mask for filtering*/ + opts.cpu_mask = argtol(optarg, 0); + break; - default: - return ARGP_ERR_UNKNOWN; - } - - return 0; -} - -#define xstr(x) str(x) -#define str(x) #x - -const struct argp_option cmd_opts[] = -{ - { .name = "log-thresh", .key='t', .arg="l", - .doc = - "Set number, l, of new records required to trigger a write to output " - "(default " xstr(NEW_DATA_THRESH) ")." }, - - { .name = "poll-sleep", .key='s', .arg="p", - .doc = - "Set sleep time, p, in milliseconds between polling the trace buffer " - "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." }, - - { .name = "cpu-mask", .key='c', .arg="c", - .doc = - "Set cpu-mask." }, - - { .name = "evt-mask", .key='e', .arg="e", - .doc = - "Set trace event mask. This can accept a numerical (including hex) " - " argument or a symbolic name. Symbolic names include: gen, sched, " - "dom0op, hvm, and all." }, - - { .name = "trace-buf-size", .key='S', .arg="N", - .doc = - "Set trace buffer size in pages (default " xstr(DEFAULT_TBUF_SIZE) "). " - "N.B. that the trace buffer cannot be resized. If it has " - "already been set this boot cycle, this argument will be ignored." }, - - { .name = "discard-buffers", .key='D', .arg=NULL, - .flags=OPTION_ARG_OPTIONAL, - .doc = "Discard all records currently in the trace buffers before " - " beginning." }, - - {0} -}; - -const struct argp parser_def = -{ - .options = cmd_opts, - .parser = cmd_parser, - .args_doc = "[output file]", - .doc = - "Tool to capure Xen trace buffer data" - "\v" - "This tool is used to capture trace buffer data from Xen. The data is " - "output in a binary format, in the following order:\n\n" - " CPU(uint) TSC(uint64_t) EVENT(uint32_t) D1 D2 D3 D4 D5 " - "(all uint32_t)\n\n" - "The output should be parsed using the tool xentrace_format, which can " - "produce human-readable output in ASCII format." -}; - - -const char *argp_program_version = "xentrace v1.1"; -const char *argp_program_bug_address = ""; + case 'e': /* set new event mask for filtering*/ + parse_evtmask(optarg); + break; - + case 'S': /* set tbuf size (given in pages) */ + opts.tbuf_size = argtol(optarg, 0); + break; + + case 'V': /* print program version */ + printf("%s\n", program_version); + exit(EXIT_SUCCESS); + break; + + default: + usage(); + } + } + + /* get outfile (required last argument) */ + if (optind != (argc-1)) + usage(); + + opts.outfile = argv[optind]; +} + + +/* *BSD has no O_LARGEFILE */ +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + int main(int argc, char **argv) { int outfd = 1, ret; @@ -582,8 +570,8 @@ int main(int argc, char **argv) opts.evt_mask = 0; opts.cpu_mask = 0; - argp_parse(&parser_def, argc, argv, 0, 0, &opts); - + parse_args(argc, argv); + if (opts.evt_mask != 0) { set_mask(opts.evt_mask, 0); }