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 <[email protected]>
@@ -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)