|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |