ia64/xen-unstable

changeset 16390:e2f5b5b24e07

xentrace: make xentrace and xenmon work on Solaris and *BSD.
- Use getopt() to get rid of argp dependency which does not exist
on Solaris and *BSD. Done by Tariq Magdon-Ismail.
- Minor modifications by me (Christoph) to make it also work on *BSD.
- Tested on Linux by me (Christoph). No functional change on Linux.
- Tariq ok'd BSD modifications for Solaris
- Tariq ok'd submission by me :)

Signed-off-by: Tariq Magdon-Ismail <tariqmi@sun.com>
Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Nov 16 17:08:05 2007 +0000 (2007-11-16)
parents 270bd0fc3669
children 5a72a99be911
files tools/xenmon/xenbaked.c tools/xentrace/xenctx.c tools/xentrace/xentrace.c
line diff
     1.1 --- a/tools/xenmon/xenbaked.c	Fri Nov 16 17:05:20 2007 +0000
     1.2 +++ b/tools/xenmon/xenbaked.c	Fri Nov 16 17:08:05 2007 +0000
     1.3 @@ -37,12 +37,12 @@
     1.4  #include <fcntl.h>
     1.5  #include <unistd.h>
     1.6  #include <errno.h>
     1.7 -#include <argp.h>
     1.8  #include <signal.h>
     1.9  #include <xenctrl.h>
    1.10  #include <xen/xen.h>
    1.11  #include <string.h>
    1.12  #include <sys/select.h>
    1.13 +#include <getopt.h>
    1.14  
    1.15  #define PERROR(_m, _a...)                                       \
    1.16  do {                                                            \
    1.17 @@ -58,7 +58,6 @@ typedef struct { int counter; } atomic_t
    1.18  #include <xen/trace.h>
    1.19  #include "xenbaked.h"
    1.20  
    1.21 -extern FILE *stderr;
    1.22  
    1.23  /***** Compile time configuration of defaults ********************************/
    1.24  
    1.25 @@ -78,7 +77,6 @@ extern FILE *stderr;
    1.26  /***** The code **************************************************************/
    1.27  
    1.28  typedef struct settings_st {
    1.29 -    char *outfile;
    1.30      struct timespec poll_sleep;
    1.31      unsigned long new_data_thresh;
    1.32      unsigned long ms_per_sample;
    1.33 @@ -230,10 +228,10 @@ void dump_stats(void)
    1.34      }
    1.35  
    1.36      printf("processed %d total records in %d seconds (%ld per second)\n",
    1.37 -           rec_count, (int)run_time, rec_count/run_time);
    1.38 +           rec_count, (int)run_time, (long)(rec_count/run_time));
    1.39  
    1.40      printf("woke up %d times in %d seconds (%ld per second)\n", wakeups,
    1.41 -	   (int) run_time, wakeups/run_time);
    1.42 +	   (int) run_time, (long)(wakeups/run_time));
    1.43  
    1.44      check_gotten_sum();
    1.45  }
    1.46 @@ -535,58 +533,106 @@ int monitor_tbufs(void)
    1.47  
    1.48  
    1.49  /******************************************************************************
    1.50 - * Various declarations / definitions GNU argp needs to do its work
    1.51 + * Command line handling
    1.52   *****************************************************************************/
    1.53  
    1.54 -
    1.55 -/* command parser for GNU argp - see GNU docs for more info */
    1.56 -error_t cmd_parser(int key, char *arg, struct argp_state *state)
    1.57 -{
    1.58 -    settings_t *setup = (settings_t *)state->input;
    1.59 -
    1.60 -    switch ( key )
    1.61 -    {
    1.62 -    case 't': /* set new records threshold for logging */
    1.63 -    {
    1.64 -        char *inval;
    1.65 -        setup->new_data_thresh = strtol(arg, &inval, 0);
    1.66 -        if ( inval == arg )
    1.67 -            argp_usage(state);
    1.68 -    }
    1.69 -    break;
    1.70 +const char *program_version     = "xenbaked v1.4";
    1.71 +const char *program_bug_address = "<rob.gardner@hp.com>";
    1.72  
    1.73 -    case 's': /* set sleep time (given in milliseconds) */
    1.74 -    {
    1.75 -        char *inval;
    1.76 -        setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
    1.77 -        if ( inval == arg )
    1.78 -            argp_usage(state);
    1.79 -    }
    1.80 -    break;
    1.81 +#define xstr(x) str(x)
    1.82 +#define str(x) #x
    1.83  
    1.84 -    case 'm': /* set ms_per_sample */
    1.85 -    {
    1.86 -        char *inval;
    1.87 -        setup->ms_per_sample = strtol(arg, &inval, 0);
    1.88 -        if ( inval == arg )
    1.89 -            argp_usage(state);
    1.90 -    }
    1.91 -    break;
    1.92 +void usage(void)
    1.93 +{
    1.94 +#define USAGE_STR \
    1.95 +"Usage: xenbaked [OPTION...]\n" \
    1.96 +"Tool to capture and partially process Xen trace buffer data\n" \
    1.97 +"\n" \
    1.98 +"  -m, --ms_per_sample=MS     Specify the number of milliseconds per sample\n" \
    1.99 +"                             (default " xstr(MS_PER_SAMPLE) ").\n" \
   1.100 +"  -s, --poll-sleep=p         Set sleep time, p, in milliseconds between\n" \
   1.101 +"                             polling the trace buffer for new data\n" \
   1.102 +"                             (default " xstr(POLL_SLEEP_MILLIS) ").\n" \
   1.103 +"  -t, --log-thresh=l         Set number, l, of new records required to\n" \
   1.104 +"                             trigger a write to output (default " \
   1.105 +                              xstr(NEW_DATA_THRESH) ").\n" \
   1.106 +"  -?, --help                 Show this message\n" \
   1.107 +" -V, --version              Print program version\n" \
   1.108 +"\n" \
   1.109 +"This tool is used to capture trace buffer data from Xen.  The data is\n" \
   1.110 +"saved in a shared memory structure to be further processed by xenmon.\n"
   1.111  
   1.112 -    case ARGP_KEY_ARG:
   1.113 -    {
   1.114 -        if ( state->arg_num == 0 )
   1.115 -            setup->outfile = arg;
   1.116 -        else
   1.117 -            argp_usage(state);
   1.118 -    }
   1.119 -    break;
   1.120 +    printf(USAGE_STR);
   1.121 +    printf("\nReport bugs to %s\n", program_bug_address);
   1.122  
   1.123 -    default:
   1.124 -        return ARGP_ERR_UNKNOWN;
   1.125 +    exit(EXIT_FAILURE);
   1.126 +}
   1.127 +
   1.128 +/* convert the argument string pointed to by arg to a long int representation */
   1.129 +long argtol(const char *restrict arg, int base)
   1.130 +{
   1.131 +    char *endp; 
   1.132 +    long val;
   1.133 +
   1.134 +    errno = 0;
   1.135 +    val = strtol(arg, &endp, base);
   1.136 +
   1.137 +    if (errno != 0) {
   1.138 +        fprintf(stderr, "Invalid option argument: %s\n", arg);
   1.139 +        fprintf(stderr, "Error: %s\n\n", strerror(errno));
   1.140 +        usage();
   1.141 +    } else if (endp == arg || *endp != '\0') {
   1.142 +        fprintf(stderr, "Invalid option argument: %s\n\n", arg);
   1.143 +        usage();
   1.144      }
   1.145  
   1.146 -    return 0;
   1.147 +    return val;
   1.148 +}
   1.149 +
   1.150 +/* parse command line arguments */
   1.151 +void parse_args(int argc, char **argv)
   1.152 +{
   1.153 +    int option;
   1.154 +    static struct option long_options[] = {
   1.155 +        { "log-thresh",    required_argument, 0, 't' },
   1.156 +        { "poll-sleep",    required_argument, 0, 's' },
   1.157 +        { "ms_per_sample", required_argument, 0, 'm' },
   1.158 +        { "help",          no_argument,       0, '?' },
   1.159 +        { "version",       no_argument,       0, 'V' },
   1.160 +        { 0, 0, 0, 0 }
   1.161 +    };
   1.162 +
   1.163 +    while ( (option = getopt_long(argc, argv, "m:s:t:?V",
   1.164 +                    long_options, NULL)) != -1)
   1.165 +    {
   1.166 +        switch ( option )
   1.167 +        {
   1.168 +            case 't': /* set new records threshold for logging */
   1.169 +                opts.new_data_thresh = argtol(optarg, 0);
   1.170 +                break;
   1.171 +
   1.172 +            case 's': /* set sleep time (given in milliseconds) */
   1.173 +                opts.poll_sleep = millis_to_timespec(argtol(optarg, 0));
   1.174 +                break;
   1.175 +
   1.176 +            case 'm': /* set ms_per_sample */
   1.177 +                opts.ms_per_sample = argtol(optarg, 0);
   1.178 +                break;
   1.179 +
   1.180 +            case 'V': /* print program version */
   1.181 +                printf("%s\n", program_version);
   1.182 +                exit(EXIT_SUCCESS);
   1.183 +                break;
   1.184 +
   1.185 +            default:
   1.186 +               usage(); 
   1.187 +        }
   1.188 +    }
   1.189 +
   1.190 +    /* all arguments should have been processed */
   1.191 +    if (optind != argc) {
   1.192 +        usage();
   1.193 +    }
   1.194  }
   1.195  
   1.196  #define SHARED_MEM_FILE "/var/run/xenq-shm"
   1.197 @@ -637,59 +683,18 @@ void alloc_qos_data(int ncpu)
   1.198  }
   1.199  
   1.200  
   1.201 -#define xstr(x) str(x)
   1.202 -#define str(x) #x
   1.203 -
   1.204 -const struct argp_option cmd_opts[] =
   1.205 -{
   1.206 -    { .name = "log-thresh", .key='t', .arg="l",
   1.207 -      .doc =
   1.208 -      "Set number, l, of new records required to trigger a write to output "
   1.209 -      "(default " xstr(NEW_DATA_THRESH) ")." },
   1.210 -
   1.211 -    { .name = "poll-sleep", .key='s', .arg="p",
   1.212 -      .doc = 
   1.213 -      "Set sleep time, p, in milliseconds between polling the trace buffer "
   1.214 -      "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
   1.215 -
   1.216 -    { .name = "ms_per_sample", .key='m', .arg="MS",
   1.217 -      .doc = 
   1.218 -      "Specify the number of milliseconds per sample "
   1.219 -      " (default " xstr(MS_PER_SAMPLE) ")." },
   1.220 -
   1.221 -    {0}
   1.222 -};
   1.223 -
   1.224 -const struct argp parser_def =
   1.225 -{
   1.226 -    .options = cmd_opts,
   1.227 -    .parser = cmd_parser,
   1.228 -    //    .args_doc = "[output file]",
   1.229 -    .doc =
   1.230 -    "Tool to capture and partially process Xen trace buffer data"
   1.231 -    "\v"
   1.232 -    "This tool is used to capture trace buffer data from Xen.  The data is "
   1.233 -    "saved in a shared memory structure to be further processed by xenmon."
   1.234 -};
   1.235 -
   1.236 -
   1.237 -const char *argp_program_version     = "xenbaked v1.4";
   1.238 -const char *argp_program_bug_address = "<rob.gardner@hp.com>";
   1.239 -
   1.240 -
   1.241  int main(int argc, char **argv)
   1.242  {
   1.243      int ret;
   1.244      struct sigaction act;
   1.245  
   1.246      time(&start_time);
   1.247 -    opts.outfile = 0;
   1.248      opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS);
   1.249      opts.new_data_thresh = NEW_DATA_THRESH;
   1.250      opts.ms_per_sample = MS_PER_SAMPLE;
   1.251      opts.cpu_freq = CPU_FREQ;
   1.252  
   1.253 -    argp_parse(&parser_def, argc, argv, 0, 0, &opts);
   1.254 +    parse_args(argc, argv);
   1.255      fprintf(stderr, "ms_per_sample = %ld\n", opts.ms_per_sample);
   1.256  
   1.257  
     2.1 --- a/tools/xentrace/xenctx.c	Fri Nov 16 17:05:20 2007 +0000
     2.2 +++ b/tools/xentrace/xenctx.c	Fri Nov 16 17:08:05 2007 +0000
     2.3 @@ -18,7 +18,6 @@
     2.4  #include <fcntl.h>
     2.5  #include <unistd.h>
     2.6  #include <errno.h>
     2.7 -#include <argp.h>
     2.8  #include <signal.h>
     2.9  #include <string.h>
    2.10  #include <inttypes.h>
    2.11 @@ -32,10 +31,15 @@ int frame_ptrs = 0;
    2.12  int stack_trace = 0;
    2.13  
    2.14  #if defined (__i386__)
    2.15 +#if defined (__OpenBSD__)
    2.16 +#define FMT_SIZE_T		"%08lx"
    2.17 +#define INSTR_POINTER(regs)	(unsigned long)(regs->eip)
    2.18 +#else
    2.19  #define FMT_SIZE_T		"%08x"
    2.20 +#define INSTR_POINTER(regs)	(regs->eip)
    2.21 +#endif
    2.22  #define STACK_POINTER(regs)	(regs->esp)
    2.23  #define FRAME_POINTER(regs)	(regs->ebp)
    2.24 -#define INSTR_POINTER(regs)	(regs->eip)
    2.25  #define STACK_ROWS		4
    2.26  #define STACK_COLS		8
    2.27  #elif defined (__x86_64__)
    2.28 @@ -622,7 +626,8 @@ void print_stack(vcpu_guest_context_t *c
    2.29          printf("Stack Trace:\n");
    2.30      else
    2.31          printf("Call Trace:\n");
    2.32 -    printf("%c [<" FMT_SIZE_T ">] ", stack_trace ? '*' : ' ', INSTR_POINTER(regs));
    2.33 +    printf("%c [<" FMT_SIZE_T ">] ",
    2.34 +        stack_trace ? '*' : ' ', INSTR_POINTER(regs));
    2.35  
    2.36      print_symbol(INSTR_POINTER(regs));
    2.37      printf(" <--\n");
     3.1 --- a/tools/xentrace/xentrace.c	Fri Nov 16 17:05:20 2007 +0000
     3.2 +++ b/tools/xentrace/xentrace.c	Fri Nov 16 17:08:05 2007 +0000
     3.3 @@ -18,10 +18,10 @@
     3.4  #include <fcntl.h>
     3.5  #include <unistd.h>
     3.6  #include <errno.h>
     3.7 -#include <argp.h>
     3.8  #include <signal.h>
     3.9  #include <inttypes.h>
    3.10  #include <string.h>
    3.11 +#include <getopt.h>
    3.12  #include <assert.h>
    3.13  
    3.14  #include <xen/xen.h>
    3.15 @@ -37,7 +37,6 @@ do {                                    
    3.16      errno = __saved_errno;                                      \
    3.17  } while (0)
    3.18  
    3.19 -extern FILE *stderr;
    3.20  
    3.21  /***** Compile time configuration of defaults ********************************/
    3.22  
    3.23 @@ -411,166 +410,155 @@ int monitor_tbufs(int outfd)
    3.24  
    3.25  
    3.26  /******************************************************************************
    3.27 - * Various declarations / definitions GNU argp needs to do its work
    3.28 + * Command line handling
    3.29   *****************************************************************************/
    3.30  
    3.31 -int parse_evtmask(char *arg, struct argp_state *state)
    3.32 -{
    3.33 -    settings_t *setup = (settings_t *)state->input;
    3.34 -    char *inval;
    3.35 +#define xstr(x) str(x)
    3.36 +#define str(x) #x
    3.37  
    3.38 -    /* search filtering class */
    3.39 -    if (strcmp(arg, "gen") == 0){ 
    3.40 -        setup->evt_mask |= TRC_GEN;
    3.41 -    } else if(strcmp(arg, "sched") == 0){ 
    3.42 -        setup->evt_mask |= TRC_SCHED;
    3.43 -    } else if(strcmp(arg, "dom0op") == 0){ 
    3.44 -        setup->evt_mask |= TRC_DOM0OP;
    3.45 -    } else if(strcmp(arg, "hvm") == 0){ 
    3.46 -        setup->evt_mask |= TRC_HVM;
    3.47 -    } else if(strcmp(arg, "all") == 0){ 
    3.48 -        setup->evt_mask |= TRC_ALL;
    3.49 -    } else {
    3.50 -        setup->evt_mask = strtol(arg, &inval, 0);
    3.51 -        if ( inval == arg )
    3.52 -            argp_usage(state);
    3.53 -    }
    3.54 +const char *program_version     = "xentrace v1.1";
    3.55 +const char *program_bug_address = "<mark.a.williamson@intel.com>";
    3.56  
    3.57 -    return 0;
    3.58 +void usage(void)
    3.59 +{
    3.60 +#define USAGE_STR \
    3.61 +"Usage: xentrace [OPTION...] [output file]\n" \
    3.62 +"Tool to capture Xen trace buffer data\n" \
    3.63 +"\n" \
    3.64 +"  -c, --cpu-mask=c        Set cpu-mask\n" \
    3.65 +"  -e, --evt-mask=e        Set evt-mask\n" \
    3.66 +"  -s, --poll-sleep=p      Set sleep time, p, in milliseconds between\n" \
    3.67 +"                          polling the trace buffer for new data\n" \
    3.68 +"                          (default " xstr(POLL_SLEEP_MILLIS) ").\n" \
    3.69 +"  -S, --trace-buf-size=N  Set trace buffer size in pages (default " \
    3.70 +                           xstr(DEFAULT_TBUF_SIZE) ").\n" \
    3.71 +"                          N.B. that the trace buffer cannot be resized.\n" \
    3.72 +"                          if it has already been set this boot cycle,\n" \
    3.73 +"                          this argument will be ignored.\n" \
    3.74 +"  -t, --log-thresh=l      Set number, l, of new records required to\n" \
    3.75 +"                          trigger a write to output (default " \
    3.76 +                           xstr(NEW_DATA_THRESH) ").\n" \
    3.77 +"  -?, --help              Show this message\n" \
    3.78 +"  -V, --version           Print program version\n" \
    3.79 +"\n" \
    3.80 +"This tool is used to capture trace buffer data from Xen. The\n" \
    3.81 +"data is output in a binary format, in the following order:\n" \
    3.82 +"\n" \
    3.83 +"  CPU(uint) TSC(uint64_t) EVENT(uint32_t) D1 D2 D3 D4 D5 (all uint32_t)\n" \
    3.84 +"\n" \
    3.85 +"The output should be parsed using the tool xentrace_format,\n" \
    3.86 +"which can produce human-readable output in ASCII format.\n" 
    3.87  
    3.88 +    printf(USAGE_STR);
    3.89 +    printf("\nReport bugs to %s\n", program_bug_address);
    3.90 +
    3.91 +    exit(EXIT_FAILURE);
    3.92  }
    3.93  
    3.94 -/* command parser for GNU argp - see GNU docs for more info */
    3.95 -error_t cmd_parser(int key, char *arg, struct argp_state *state)
    3.96 +/* convert the argument string pointed to by arg to a long int representation */
    3.97 +long argtol(const char *restrict arg, int base)
    3.98  {
    3.99 -    settings_t *setup = (settings_t *)state->input;
   3.100 +    char *endp;
   3.101 +    long val;
   3.102  
   3.103 -    switch ( key )
   3.104 -    {
   3.105 -    case 't': /* set new records threshold for logging */
   3.106 -    {
   3.107 -        char *inval;
   3.108 -        setup->new_data_thresh = strtol(arg, &inval, 0);
   3.109 -        if ( inval == arg )
   3.110 -            argp_usage(state);
   3.111 -    }
   3.112 -    break;
   3.113 -
   3.114 -    case 's': /* set sleep time (given in milliseconds) */
   3.115 -    {
   3.116 -        char *inval;
   3.117 -        setup->poll_sleep = millis_to_timespec(strtol(arg, &inval, 0));
   3.118 -        if ( inval == arg )
   3.119 -            argp_usage(state);
   3.120 -    }
   3.121 -    break;
   3.122 -
   3.123 -    case 'c': /* set new cpu mask for filtering*/
   3.124 -    {
   3.125 -        char *inval;
   3.126 -        setup->cpu_mask = strtol(arg, &inval, 0);
   3.127 -        if ( inval == arg )
   3.128 -            argp_usage(state);
   3.129 +    errno = 0;
   3.130 +    val = strtol(arg, &endp, base);
   3.131 +    
   3.132 +    if (errno != 0) {
   3.133 +        fprintf(stderr, "Invalid option argument: %s\n", arg);
   3.134 +        fprintf(stderr, "Error: %s\n\n", strerror(errno));
   3.135 +        usage();
   3.136 +    } else if (endp == arg || *endp != '\0') {
   3.137 +        fprintf(stderr, "Invalid option argument: %s\n\n", arg);
   3.138 +        usage();
   3.139      }
   3.140 -    break;
   3.141 -    
   3.142 -    case 'e': /* set new event mask for filtering*/
   3.143 -    {
   3.144 -        parse_evtmask(arg, state);
   3.145 -    }
   3.146 -    break;
   3.147 -    
   3.148 -    case 'S': /* set tbuf size (given in pages) */
   3.149 -    {
   3.150 -        char *inval;
   3.151 -        setup->tbuf_size = strtol(arg, &inval, 0);
   3.152 -        if ( inval == arg )
   3.153 -            argp_usage(state);
   3.154 -    }
   3.155 -    break;
   3.156  
   3.157 -    case 'D': /* Discard traces currently in the buffer before beginning */
   3.158 -    {
   3.159 -        opts.discard = 1;
   3.160 -    }
   3.161 -    break;
   3.162 +    return val;
   3.163 +}
   3.164  
   3.165 -    case ARGP_KEY_ARG:
   3.166 -    {
   3.167 -        if ( state->arg_num == 0 )
   3.168 -            setup->outfile = arg;
   3.169 -        else
   3.170 -            argp_usage(state);
   3.171 -    }
   3.172 -    break;
   3.173 -        
   3.174 -    default:
   3.175 -        return ARGP_ERR_UNKNOWN;
   3.176 +int parse_evtmask(char *arg)
   3.177 +{
   3.178 +    /* search filtering class */
   3.179 +    if (strcmp(arg, "gen") == 0){ 
   3.180 +        opts.evt_mask |= TRC_GEN;
   3.181 +    } else if(strcmp(arg, "sched") == 0){ 
   3.182 +        opts.evt_mask |= TRC_SCHED;
   3.183 +    } else if(strcmp(arg, "dom0op") == 0){ 
   3.184 +        opts.evt_mask |= TRC_DOM0OP;
   3.185 +    } else if(strcmp(arg, "hvm") == 0){ 
   3.186 +        opts.evt_mask |= TRC_HVM;
   3.187 +    } else if(strcmp(arg, "all") == 0){ 
   3.188 +        opts.evt_mask |= TRC_ALL;
   3.189 +    } else {
   3.190 +        opts.evt_mask = argtol(arg, 0);
   3.191      }
   3.192  
   3.193      return 0;
   3.194  }
   3.195  
   3.196 -#define xstr(x) str(x)
   3.197 -#define str(x) #x
   3.198 -
   3.199 -const struct argp_option cmd_opts[] =
   3.200 +/* parse command line arguments */
   3.201 +void parse_args(int argc, char **argv)
   3.202  {
   3.203 -    { .name = "log-thresh", .key='t', .arg="l",
   3.204 -      .doc =
   3.205 -      "Set number, l, of new records required to trigger a write to output "
   3.206 -      "(default " xstr(NEW_DATA_THRESH) ")." },
   3.207 -
   3.208 -    { .name = "poll-sleep", .key='s', .arg="p",
   3.209 -      .doc = 
   3.210 -      "Set sleep time, p, in milliseconds between polling the trace buffer "
   3.211 -      "for new data (default " xstr(POLL_SLEEP_MILLIS) ")." },
   3.212 -
   3.213 -    { .name = "cpu-mask", .key='c', .arg="c",
   3.214 -      .doc = 
   3.215 -      "Set cpu-mask." },
   3.216 -
   3.217 -    { .name = "evt-mask", .key='e', .arg="e",
   3.218 -      .doc = 
   3.219 -      "Set trace event mask.  This can accept a numerical (including hex) "
   3.220 -      " argument or a symbolic name.  Symbolic names include: gen, sched, "
   3.221 -      "dom0op, hvm, and all." },
   3.222 +    int option;
   3.223 +    static struct option long_options[] = {
   3.224 +        { "log-thresh",     required_argument, 0, 't' },
   3.225 +        { "poll-sleep",     required_argument, 0, 's' },
   3.226 +        { "cpu-mask",       required_argument, 0, 'c' },
   3.227 +        { "evt-mask",       required_argument, 0, 'e' },
   3.228 +        { "trace-buf-size", required_argument, 0, 'S' },
   3.229 +        { "help",           no_argument,       0, '?' },
   3.230 +        { "version",        no_argument,       0, 'V' },
   3.231 +        { 0, 0, 0, 0 }
   3.232 +    };
   3.233  
   3.234 -    { .name = "trace-buf-size", .key='S', .arg="N",
   3.235 -      .doc =
   3.236 -      "Set trace buffer size in pages (default " xstr(DEFAULT_TBUF_SIZE) "). "
   3.237 -      "N.B. that the trace buffer cannot be resized.  If it has "
   3.238 -      "already been set this boot cycle, this argument will be ignored." },
   3.239 -
   3.240 -    { .name = "discard-buffers", .key='D', .arg=NULL,
   3.241 -      .flags=OPTION_ARG_OPTIONAL,
   3.242 -      .doc = "Discard all records currently in the trace buffers before "
   3.243 -      " beginning." },
   3.244 -
   3.245 -    {0}
   3.246 -};
   3.247 +    while ( (option = getopt_long(argc, argv, "c:e:s:S:t:?V",
   3.248 +                    long_options, NULL)) != -1) 
   3.249 +    {
   3.250 +        switch ( option )
   3.251 +        {
   3.252 +        case 't': /* set new records threshold for logging */
   3.253 +            opts.new_data_thresh = argtol(optarg, 0);
   3.254 +            break;
   3.255  
   3.256 -const struct argp parser_def =
   3.257 -{
   3.258 -    .options = cmd_opts,
   3.259 -    .parser = cmd_parser,
   3.260 -    .args_doc = "[output file]",
   3.261 -    .doc =
   3.262 -    "Tool to capure Xen trace buffer data"
   3.263 -    "\v"
   3.264 -    "This tool is used to capture trace buffer data from Xen.  The data is "
   3.265 -    "output in a binary format, in the following order:\n\n"
   3.266 -    "  CPU(uint) TSC(uint64_t) EVENT(uint32_t) D1 D2 D3 D4 D5 "
   3.267 -    "(all uint32_t)\n\n"
   3.268 -    "The output should be parsed using the tool xentrace_format, which can "
   3.269 -    "produce human-readable output in ASCII format."
   3.270 -};
   3.271 +        case 's': /* set sleep time (given in milliseconds) */
   3.272 +            opts.poll_sleep = millis_to_timespec(argtol(optarg, 0));
   3.273 +            break;
   3.274 +
   3.275 +        case 'c': /* set new cpu mask for filtering*/
   3.276 +            opts.cpu_mask = argtol(optarg, 0);
   3.277 +            break;
   3.278 +        
   3.279 +        case 'e': /* set new event mask for filtering*/
   3.280 +            parse_evtmask(optarg);
   3.281 +            break;
   3.282 +        
   3.283 +        case 'S': /* set tbuf size (given in pages) */
   3.284 +            opts.tbuf_size = argtol(optarg, 0);
   3.285 +            break;
   3.286 +
   3.287 +        case 'V': /* print program version */
   3.288 +            printf("%s\n", program_version);
   3.289 +            exit(EXIT_SUCCESS);
   3.290 +            break;
   3.291 +            
   3.292 +        default:
   3.293 +            usage();
   3.294 +        }
   3.295 +    }
   3.296 +
   3.297 +    /* get outfile (required last argument) */
   3.298 +    if (optind != (argc-1))
   3.299 +        usage();
   3.300 +
   3.301 +    opts.outfile = argv[optind];
   3.302 +}
   3.303  
   3.304  
   3.305 -const char *argp_program_version     = "xentrace v1.1";
   3.306 -const char *argp_program_bug_address = "<mark.a.williamson@intel.com>";
   3.307 -        
   3.308 -    
   3.309 +/* *BSD has no O_LARGEFILE */
   3.310 +#ifndef O_LARGEFILE
   3.311 +#define O_LARGEFILE	0
   3.312 +#endif
   3.313 +
   3.314  int main(int argc, char **argv)
   3.315  {
   3.316      int outfd = 1, ret;
   3.317 @@ -582,8 +570,8 @@ int main(int argc, char **argv)
   3.318      opts.evt_mask = 0;
   3.319      opts.cpu_mask = 0;
   3.320  
   3.321 -    argp_parse(&parser_def, argc, argv, 0, 0, &opts);
   3.322 -
   3.323 +    parse_args(argc, argv);
   3.324 +    
   3.325      if (opts.evt_mask != 0) { 
   3.326          set_mask(opts.evt_mask, 0);
   3.327      }