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

[Xen-devel] [PATCH v1 5/5] xentrace: Implement cpu mask range parsing of human values (-C).



Instead of just using -c 0x<some hex value> we can
also use -C <starting cpu>-<end cpu> or -C <cpu1>,<cpu2>
or a combination of them.

That should make it easier to trace the right CPU if
using this along with 'xl vcpu-list'.

The code has been lifted from the Linux kernel, see file
lib/bitmap.c, function __bitmap_parselist.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
 tools/xentrace/xentrace.8 |  19 ++++++++
 tools/xentrace/xentrace.c | 109 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/tools/xentrace/xentrace.8 b/tools/xentrace/xentrace.8
index c176a96..ebfb47e 100644
--- a/tools/xentrace/xentrace.8
+++ b/tools/xentrace/xentrace.8
@@ -42,6 +42,25 @@ If not specified, the cpu-mask of all of the available CPUs 
will be
 constructed.
 
 .TP
+.B -C, --cpu-range="CPU-LIST"
+List of which CPUs to trace. By default it will pick all (all CPUs on the
+machine). A "CPU-LIST" may be specified as follows:
+
+.RS 4
+.ie n .IP """0-3""" 4
+.el .IP "``0-3''" 4
+.IX Item "0-3"
+Trace only on CPUs 0 through 3
+.ie n .IP """0,2,5-7""" 4
+.el .IP "``0,2,5-7''" 4
+.IX Item "0,2,5-7"
+Trace only on CPUs 0, 2, and 5 through 7.
+.RE
+.Sp
+
+If this option is not specified, xentrace will trace all of the physical
+CPUs on the machine.
+.TP
 .B -e, --evt-mask=e
 set event capture mask. If not specified the TRC_ALL will be used.
 .TP
diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c
index 2063ae8..378a714 100644
--- a/tools/xentrace/xentrace.c
+++ b/tools/xentrace/xentrace.c
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <getopt.h>
 #include <assert.h>
+#include <ctype.h>
 #include <sys/poll.h>
 #include <sys/statvfs.h>
 
@@ -54,6 +55,7 @@ typedef struct settings_st {
     unsigned long poll_sleep; /* milliseconds to sleep between polls */
     uint32_t evt_mask;
     xc_cpumap_t cpu_mask;
+    char *cpu_mask_str;
     unsigned long tbuf_size;
     unsigned long disk_rsvd;
     unsigned long timeout;
@@ -819,6 +821,7 @@ static void usage(void)
 "Tool to capture Xen trace buffer data\n" \
 "\n" \
 "  -c, --cpu-mask=c        Set cpu-mask\n" \
+"  -C, --cpu-range=CPU-LIST Set cpu-mask using CPU ranges.\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" \
@@ -967,6 +970,98 @@ static int parse_cpumask(const char *arg)
     return 0;
 }
 
+static int parse_cpumask_range(const char *arg)
+{
+    xc_cpumap_t map;
+    unsigned int a, b, buflen = strlen(arg);
+    int c, c_old, totaldigits, nmaskbits;
+    int exp_digit, in_range;
+
+    if ( !buflen )
+    {
+        fprintf(stderr, "Invalid option argument: %s\n", arg);
+        usage(); /* does exit */
+    }
+    nmaskbits = xc_get_max_cpus(xc_handle);
+    if ( nmaskbits <= 0 )
+    {
+        fprintf(stderr, "Failed to get max number of CPUs! rc: %d\n", 
nmaskbits);
+        usage();
+    }
+    map = xc_cpumap_alloc(xc_handle);
+    if ( !map )
+    {
+        fprintf(stderr, "Out of memory!\n");
+        usage();
+    }
+    c = c_old = totaldigits = 0;
+    do {
+        exp_digit = 1;
+        in_range = 0;
+        a = b = 0;
+        while ( buflen )
+        {
+            c = *arg++;
+            buflen--;
+
+            if ( isspace(c) )
+                continue;
+
+            if ( totaldigits && c && isspace(c_old) )
+            {
+                fprintf(stderr, "No embedded whitespaces allowed in: %s\n", 
arg);
+                goto err_out;
+            }
+
+            /* A '\0' or a ',' signal the end of a cpu# or range */
+            if ( c == '\0' || c == ',' )
+                break;
+
+            if ( c == '-' )
+            {
+                if ( exp_digit || in_range )
+                        goto err_out;
+                b = 0;
+                in_range = 1;
+                exp_digit = 1;
+                continue;
+            }
+            if ( !isdigit(c) )
+            {
+                fprintf(stderr, "Only digits allowed in: %s\n", arg);
+                goto err_out;
+            }
+            b = b * 10 + (c - '0');
+            if ( !in_range )
+                a = b;
+            exp_digit = 0;
+            totaldigits++;
+        }
+        if ( !(a <= b) )
+        {
+            fprintf(stderr, "Wrong order of %d and %d\n", a, b);
+            goto err_out;
+        }
+        if ( b >= nmaskbits )
+        {
+            fprintf(stderr, "Specified higher value then there are CPUS!\n");
+            goto err_out;
+        }
+        while ( a <= b )
+        {
+            set_bit(a, (unsigned long *) map);
+            a++;
+        }
+    } while ( buflen && c == ',' );
+
+    opts.cpu_mask = map;
+    return 0;
+ err_out:
+    free(map);
+    usage();
+    return 0; /* Never reached */
+}
+
 /* parse command line arguments */
 static void parse_args(int argc, char **argv)
 {
@@ -975,6 +1070,7 @@ static void parse_args(int argc, char **argv)
         { "log-thresh",     required_argument, 0, 't' },
         { "poll-sleep",     required_argument, 0, 's' },
         { "cpu-mask",       required_argument, 0, 'c' },
+        { "cpu-range",      required_argument, 0, 'C' },
         { "evt-mask",       required_argument, 0, 'e' },
         { "trace-buf-size", required_argument, 0, 'S' },
         { "reserve-disk-space", required_argument, 0, 'r' },
@@ -988,7 +1084,7 @@ static void parse_args(int argc, char **argv)
         { 0, 0, 0, 0 }
     };
 
-    while ( (option = getopt_long(argc, argv, "t:s:c:e:S:r:T:M:DxX?V",
+    while ( (option = getopt_long(argc, argv, "t:s:c:C:e:S:r:T:M:DxX?V",
                     long_options, NULL)) != -1) 
     {
         switch ( option )
@@ -1005,7 +1101,9 @@ static void parse_args(int argc, char **argv)
                 exit(EXIT_FAILURE);
             }
             break;
-        
+        case 'C':
+            opts.cpu_mask_str = strdup(optarg);
+            break;
         case 'e': /* set new event mask for filtering*/
             parse_evtmask(optarg);
             break;
@@ -1069,6 +1167,7 @@ int main(int argc, char **argv)
     opts.poll_sleep = POLL_SLEEP_MILLIS;
     opts.evt_mask = 0;
     opts.cpu_mask = NULL;
+    opts.cpu_mask_str = NULL;
     opts.disk_rsvd = 0;
     opts.disable_tracing = 1;
     opts.start_disabled = 0;
@@ -1086,7 +1185,11 @@ int main(int argc, char **argv)
     if ( opts.evt_mask != 0 )
         set_evt_mask(opts.evt_mask);
 
-
+    if ( opts.cpu_mask_str )
+    {
+        parse_cpumask_range(opts.cpu_mask_str);
+        free(opts.cpu_mask_str);
+    }
     set_cpu_mask(opts.cpu_mask);
     /* We don't use it pass this point. */
     free(opts.cpu_mask);
-- 
1.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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