[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xentrace: make xentrace and xenmon work on Solaris and *BSD.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1195232885 0
# Node ID e2f5b5b24e07348d0f5e3d68569e00a978a251e8
# Parent  270bd0fc3669413bd22d9aca9b6735486642aeeb
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@xxxxxxx>
Signed-off-by: Christoph Egger <Christoph.Egger@xxxxxxx>
---
 tools/xenmon/xenbaked.c   |  197 ++++++++++++++++---------------
 tools/xentrace/xenctx.c   |   11 +
 tools/xentrace/xentrace.c |  288 ++++++++++++++++++++++------------------------
 3 files changed, 247 insertions(+), 249 deletions(-)

diff -r 270bd0fc3669 -r e2f5b5b24e07 tools/xenmon/xenbaked.c
--- a/tools/xenmon/xenbaked.c   Fri Nov 16 17:05:20 2007 +0000
+++ b/tools/xenmon/xenbaked.c   Fri Nov 16 17:08:05 2007 +0000
@@ -37,12 +37,12 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <argp.h>
 #include <signal.h>
 #include <xenctrl.h>
 #include <xen/xen.h>
 #include <string.h>
 #include <sys/select.h>
+#include <getopt.h>
 
 #define PERROR(_m, _a...)                                       \
 do {                                                            \
@@ -58,7 +58,6 @@ typedef struct { int counter; } atomic_t
 #include <xen/trace.h>
 #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 = "<rob.gardner@xxxxxx>";
+
+#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 = "<rob.gardner@xxxxxx>";
-
-
 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 270bd0fc3669 -r e2f5b5b24e07 tools/xentrace/xenctx.c
--- a/tools/xentrace/xenctx.c   Fri Nov 16 17:05:20 2007 +0000
+++ b/tools/xentrace/xenctx.c   Fri Nov 16 17:08:05 2007 +0000
@@ -18,7 +18,6 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <argp.h>
 #include <signal.h>
 #include <string.h>
 #include <inttypes.h>
@@ -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 270bd0fc3669 -r e2f5b5b24e07 tools/xentrace/xentrace.c
--- a/tools/xentrace/xentrace.c Fri Nov 16 17:05:20 2007 +0000
+++ b/tools/xentrace/xentrace.c Fri Nov 16 17:08:05 2007 +0000
@@ -18,10 +18,10 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <argp.h>
 #include <signal.h>
 #include <inttypes.h>
 #include <string.h>
+#include <getopt.h>
 #include <assert.h>
 
 #include <xen/xen.h>
@@ -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 = "<mark.a.williamson@xxxxxxxxx>";
+
+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 = "<mark.a.williamson@xxxxxxxxx>";
+        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);
     }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.