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], &params[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(&params[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], &params[nevent]);
-			if (tokens[1] != NULL) {
-				if (parse_event_scale(&params[nevent],
-				    tokens[1]) != 0) {
-					die_errc(EXIT_FAILURE, 0,
-					    "invalid scale: %s", tokens[1]);
-				}
+			if (tprof_parse_event(&params[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)

Reply via email to