Module Name: src Committed By: ryo Date: Fri Dec 16 08:02:04 UTC 2022
Modified Files: src/usr.sbin/tprof: tprof.8 tprof.c tprof.h tprof_top.c Log Message: the "scale" option can be specified in the event name even in "tprof monitor" To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/usr.sbin/tprof/tprof.8 cvs rdiff -u -r1.17 -r1.18 src/usr.sbin/tprof/tprof.c cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/tprof/tprof.h cvs rdiff -u -r1.6 -r1.7 src/usr.sbin/tprof/tprof_top.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/tprof/tprof.8 diff -u src/usr.sbin/tprof/tprof.8:1.23 src/usr.sbin/tprof/tprof.8:1.24 --- src/usr.sbin/tprof/tprof.8:1.23 Fri Dec 16 08:00:47 2022 +++ src/usr.sbin/tprof/tprof.8 Fri Dec 16 08:02:04 2022 @@ -1,4 +1,4 @@ -.\" $NetBSD: tprof.8,v 1.23 2022/12/16 08:00:47 ryo Exp $ +.\" $NetBSD: tprof.8,v 1.24 2022/12/16 08:02:04 ryo Exp $ .\" .\" Copyright (c)2011 YAMAMOTO Takashi, .\" All rights reserved. @@ -66,7 +66,7 @@ Valid actions are: Display a list of performance counter events available on the system. .It monitor Xo .Fl e -.Ar name[:option] +.Ar name[:option][,scale] .Op Fl e Ar ... .Op Fl o Ar outfile .Ar command @@ -83,6 +83,18 @@ specifies the source of the event; it mu .Ar k (kernel). If omitted, it is assumed that both are specified. The collected samples are written into the file +.Ar scale +specifies the ratio of the speed to the cycle counter, or the counter until +overflow. +The counter reset value on overflow used for profiling is calculated from the +speed of the cycle counter by default, but for some events this value may be +too large (counter increasing too slowly) to be sufficient for profiling. +For example, to specify an event that increases about 1000 times slower than +the cycle counter, specify +.Dq Pa -e event,1000 . +Also, if +.Dq Pa -e event,=200 +is specified, profiling is performed every time the counter is increased by 200. .Ar outfile if specified. The default is @@ -133,7 +145,7 @@ Per symbol. .It top Xo .Oo .Fl e -.Ar name[,value] +.Ar name[,scale] .Op Fl e Ar ... .Oc .Op Fl i Ar interval @@ -142,18 +154,6 @@ Per symbol. Displays profiling results in real-time. .Ar name specifies the name of the event to count. -.Ar value -specifies the ratio of the speed to the cycle counter, or the counter until -overflow. -The counter reset value on overflow used for profiling is calculated from the -speed of the cycle counter by default, but for some events this value may be -too large (counter increasing too slowly) to be sufficient for profiling. -For example, to specify an event that increases about 1000 times slower than -the cycle counter, specify -.Dq Pa -e event,1000 . -Also, if -.Dq Pa -e event,=200 -is specified, profiling is performed every time the counter is increased by 200. .Bl -tag -width XXintervalX -offset indent .It Fl i Ar interval set the update interval in seconds. The default value is 1. Index: src/usr.sbin/tprof/tprof.c diff -u src/usr.sbin/tprof/tprof.c:1.17 src/usr.sbin/tprof/tprof.c:1.18 --- src/usr.sbin/tprof/tprof.c:1.17 Mon Dec 5 05:02:45 2022 +++ src/usr.sbin/tprof/tprof.c Fri Dec 16 08:02:04 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof.c,v 1.17 2022/12/05 05:02:45 ryo Exp $ */ +/* $NetBSD: tprof.c,v 1.18 2022/12/16 08:02:04 ryo Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: tprof.c,v 1.17 2022/12/05 05:02:45 ryo Exp $"); +__RCSID("$NetBSD: tprof.c,v 1.18 2022/12/16 08:02:04 ryo Exp $"); #endif /* not lint */ #include <sys/atomic.h> @@ -264,6 +264,97 @@ tprof_list(int argc, char **argv) tprof_event_list(); } +int +tprof_parse_event(tprof_param_t *param, const char *str, uint32_t flags, + const char **eventnamep, char **errmsgp) +{ + double d; + uint64_t n; + int error = 0; + char *p, *event = NULL, *opt = NULL, *scale = NULL; + bool allow_option, allow_scale; + static char errmsgbuf[128]; + + allow_option = flags & TPROF_PARSE_EVENT_F_ALLOWOPTION; + allow_scale = flags & TPROF_PARSE_EVENT_F_ALLOWSCALE; + + p = estrdup(str); + event = p; + if (allow_option) { + opt = strchr(p, ':'); + if (opt != NULL) { + *opt++ = '\0'; + p = opt; + } + } + if (allow_scale) { + scale = strchr(p, ','); + if (scale != NULL) + *scale++ = '\0'; + } + + tprof_event_lookup(event, param); + + if (opt != NULL) { + while (*opt != '\0') { + switch (*opt) { + case 'u': + param->p_flags |= TPROF_PARAM_USER; + break; + case 'k': + param->p_flags |= TPROF_PARAM_KERN; + break; + default: + error = -1; + snprintf(errmsgbuf, sizeof(errmsgbuf), + "invalid option: '%c'", *opt); + goto done; + } + } + } else if (allow_option) { + param->p_flags |= TPROF_PARAM_USER; + param->p_flags |= TPROF_PARAM_KERN; + } + + if (scale != NULL) { + if (*scale == '=') { + scale++; + n = strtoull(scale, &p, 0); + if (*p != '\0') { + error = -1; + } else { + param->p_value2 = n; + param->p_flags |= + TPROF_PARAM_VALUE2_TRIGGERCOUNT; + } + } else { + if (strncasecmp("0x", scale, 2) == 0) + d = strtol(scale, &p, 0); + else + d = strtod(scale, &p); + if (*p != '\0' || d <= 0) { + error = -1; + } else { + param->p_value2 = 0x100000000ULL / d; + param->p_flags |= TPROF_PARAM_VALUE2_SCALE; + } + } + + if (error != 0) { + snprintf(errmsgbuf, sizeof(errmsgbuf), + "invalid scale: %s", scale); + goto done; + } + } + + done: + if (eventnamep != NULL) + *eventnamep = event; + if (error != 0 && errmsgp != NULL) + *errmsgp = errmsgbuf; + return error; +} + static void tprof_monitor_common(bool do_profile, int argc, char **argv) { @@ -273,7 +364,7 @@ tprof_monitor_common(bool do_profile, in pid_t pid; pthread_t pt; int ret, ch, i; - char *tokens[2], *p; + char *p, *errmsg; tprof_countermask_t mask = TPROF_COUNTERMASK_ALL; memset(params, 0, sizeof(params)); @@ -290,23 +381,12 @@ tprof_monitor_common(bool do_profile, in optarg); break; case 'e': - p = estrdup(optarg); - tokens[0] = strtok(p, ":"); - tokens[1] = strtok(NULL, ":"); - tprof_event_lookup(tokens[0], ¶ms[nevent]); - - if (tokens[1] == NULL) { - params[nevent].p_flags |= - (TPROF_PARAM_USER | TPROF_PARAM_KERN); - } else { - if (strchr(tokens[1], 'u')) - params[nevent].p_flags |= - TPROF_PARAM_USER; - if (strchr(tokens[1], 'k')) - params[nevent].p_flags |= - TPROF_PARAM_KERN; + if (tprof_parse_event(¶ms[nevent], optarg, + TPROF_PARSE_EVENT_F_ALLOWOPTION | + (do_profile ? TPROF_PARSE_EVENT_F_ALLOWSCALE : 0), + &eventname[nevent], &errmsg) != 0) { + errx(EXIT_FAILURE, "%s", errmsg); } - eventname[nevent] = tokens[0]; eventnamewidth[nevent] = strlen(eventname[nevent]); if (eventnamewidth[nevent] < COUNTER_COLUMNS_WIDTH) eventnamewidth[nevent] = COUNTER_COLUMNS_WIDTH; Index: src/usr.sbin/tprof/tprof.h diff -u src/usr.sbin/tprof/tprof.h:1.3 src/usr.sbin/tprof/tprof.h:1.4 --- src/usr.sbin/tprof/tprof.h:1.3 Thu Dec 1 00:43:27 2022 +++ src/usr.sbin/tprof/tprof.h Fri Dec 16 08:02:04 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof.h,v 1.3 2022/12/01 00:43:27 ryo Exp $ */ +/* $NetBSD: tprof.h,v 1.4 2022/12/16 08:02:04 ryo Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -38,5 +38,10 @@ int tprof_event_init(uint32_t); void tprof_event_list(void); void tprof_event_lookup(const char *, struct tprof_param *); +int tprof_parse_event(tprof_param_t *, const char *, uint32_t, const char **, + char **); +#define TPROF_PARSE_EVENT_F_ALLOWOPTION 0x00000001 +#define TPROF_PARSE_EVENT_F_ALLOWSCALE 0x00000002 + void tprof_analyze(int, char **); void tprof_top(int, char **); Index: src/usr.sbin/tprof/tprof_top.c diff -u src/usr.sbin/tprof/tprof_top.c:1.6 src/usr.sbin/tprof/tprof_top.c:1.7 --- src/usr.sbin/tprof/tprof_top.c:1.6 Fri Dec 16 08:00:47 2022 +++ src/usr.sbin/tprof/tprof_top.c Fri Dec 16 08:02:04 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tprof_top.c,v 1.6 2022/12/16 08:00:47 ryo Exp $ */ +/* $NetBSD: tprof_top.c,v 1.7 2022/12/16 08:02:04 ryo Exp $ */ /*- * Copyright (c) 2022 Ryo Shimizu <r...@nerv.org> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: tprof_top.c,v 1.6 2022/12/16 08:00:47 ryo Exp $"); +__RCSID("$NetBSD: tprof_top.c,v 1.7 2022/12/16 08:02:04 ryo Exp $"); #endif /* not lint */ #include <sys/param.h> @@ -919,33 +919,6 @@ tprof_top_usage(void) exit(EXIT_FAILURE); } -static int -parse_event_scale(tprof_param_t *param, const char *str) -{ - double d; - uint64_t n; - char *p; - - if (str[0] == '=') { - str++; - n = strtoull(str, &p, 0); - if (*p != '\0') - return -1; - param->p_value2 = n; - param->p_flags |= TPROF_PARAM_VALUE2_TRIGGERCOUNT; - } else { - if (strncasecmp("0x", str, 2) == 0) - d = strtol(str, &p, 0); - else - d = strtod(str, &p); - if (*p != '\0') - return -1; - param->p_value2 = 0x100000000ULL / d; - param->p_flags |= TPROF_PARAM_VALUE2_SCALE; - } - return 0; -} - __dead void tprof_top(int argc, char **argv) { @@ -954,7 +927,7 @@ tprof_top(int argc, char **argv) ssize_t tprof_bufsize, len; u_int i; int ch, ret; - char *tprof_buf, *tokens[2], *p; + char *tprof_buf, *p, *errmsg; bool noinput = false; memset(params, 0, sizeof(params)); @@ -969,18 +942,11 @@ tprof_top(int argc, char **argv) opt_showcounter = 1; break; case 'e': - p = estrdup(optarg); - tokens[0] = strtok(p, ","); - tokens[1] = strtok(NULL, ","); - tprof_event_lookup(tokens[0], ¶ms[nevent]); - if (tokens[1] != NULL) { - if (parse_event_scale(¶ms[nevent], - tokens[1]) != 0) { - die_errc(EXIT_FAILURE, 0, - "invalid scale: %s", tokens[1]); - } + if (tprof_parse_event(¶ms[nevent], optarg, + TPROF_PARSE_EVENT_F_ALLOWSCALE, + &eventname[nevent], &errmsg) != 0) { + die_errc(EXIT_FAILURE, 0, "%s", errmsg); } - eventname[nevent] = tokens[0]; nevent++; if (nevent > __arraycount(params) || nevent > ncounters)