[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 |