[DTrace-devel] [PATCH 4/6] Implement switchrate-based consumer loop

Kris Van Hees kris.van.hees at oracle.com
Wed Feb 22 15:17:20 UTC 2023


The switchrate option was not implemented in the BPF-based DTrace
implementation.  And commit 96d4dfeb (" Eliminate obsolete dt_last*")
removed the dtp->dt_lastswitch member from struct dtrace_hdl.  This
patch brings dt_lastswitch back and implements the switchrate option
as a way to limit the frequency of buffer polls.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_consume.c | 30 +++++++++++++++++++++---------
 libdtrace/dt_impl.h    |  1 +
 libdtrace/dt_open.c    |  5 +++++
 libdtrace/dt_work.c    |  1 +
 4 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/libdtrace/dt_consume.c b/libdtrace/dt_consume.c
index bc2c6285..1c2223be 100644
--- a/libdtrace/dt_consume.c
+++ b/libdtrace/dt_consume.c
@@ -2986,20 +2986,28 @@ dtrace_workstatus_t
 dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pf,
 	       dtrace_consume_rec_f *rf, void *arg)
 {
-	dtrace_optval_t		timeout = dtp->dt_options[DTRACEOPT_SWITCHRATE];
+	dtrace_optval_t		interval = dtp->dt_options[DTRACEOPT_SWITCHRATE];
+	hrtime_t		now = gethrtime();
 	struct epoll_event	events[dtp->dt_conf.num_online_cpus];
 	int			drained = 0;
 	int			i, cnt;
 	dtrace_workstatus_t	rval;
 
-	/*
-	 * Don't try to consume trace data when tracing hasn't even been
-	 * started yet.  This usually means that the consumer didn't call
-	 * dtrace_go() yet.
-	 */
+	/* Has tracing started yet? */
 	if (!dtp->dt_active)
 		return dt_set_errno(dtp, EINVAL);
 
+	if (interval > 0) {
+		if (dtp->dt_lastswitch != 0) {
+			if (now - dtp->dt_lastswitch < interval)
+				return DTRACE_WORKSTATUS_OKAY;
+
+			dtp->dt_lastswitch += interval;
+		} else
+			dtp->dt_lastswitch = now;
+	} else
+		interval = NANOSEC;
+
 	/*
 	 * Ensure that we have callback functions to use (if none we provided,
 	 * we use the default no-op ones).
@@ -3011,13 +3019,13 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pf,
 		rf = (dtrace_consume_rec_f *)dt_nullrec;
 
 	/*
-	 * The epoll_wait() function expects the timeout to be expressed in
+	 * The epoll_wait() function expects the interval to be expressed in
 	 * milliseconds whereas the switch rate is expressed in nanoseconds.
 	 * We therefore need to convert the value.
 	 */
-	timeout /= NANOSEC / MILLISEC;
+	interval /= NANOSEC / MILLISEC;
 	cnt = epoll_wait(dtp->dt_poll_fd, events, dtp->dt_conf.num_online_cpus,
-			 timeout);
+			 interval);
 	if (cnt < 0) {
 		dt_set_errno(dtp, errno);
 		return DTRACE_WORKSTATUS_ERROR;
@@ -3037,6 +3045,7 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pf,
 		}
 	}
 
+
 	/*
 	 * If dtp->dt_beganon is not -1, we did not process the BEGIN probe
 	 * data (if any) yet.  We do know (since dtp->dt_active is TRUE) that
@@ -3047,6 +3056,9 @@ dtrace_consume(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pf,
 		rval = dt_consume_begin(dtp, fp, events, cnt, pf, rf, arg);
 		if (rval != 0)
 			return rval;
+
+		/* Force data retrieval since BEGIN was processed. */
+		dtp->dt_lastswitch = 0;
 	}
 
 	/*
diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
index 5d09c6e0..e9e4bbcf 100644
--- a/libdtrace/dt_impl.h
+++ b/libdtrace/dt_impl.h
@@ -391,6 +391,7 @@ struct dtrace_hdl {
 	void *dt_setoptarg;	/* setopt handler argument */
 	dtrace_status_t dt_status[2]; /* status cache */
 	int dt_statusgen;	/* current status generation */
+	hrtime_t dt_lastswitch;	/* last switch of buffer data */
 	dt_list_t dt_spec_bufs_draining; /* List of spec bufs being drained */
 	dt_htab_t *dt_spec_bufs;/* spec ID -> list of dt_spec_bufs_head_t */
 	char *dt_sprintf_buf;	/* buffer for dtrace_sprintf() */
diff --git a/libdtrace/dt_open.c b/libdtrace/dt_open.c
index 087af51a..f282c900 100644
--- a/libdtrace/dt_open.c
+++ b/libdtrace/dt_open.c
@@ -796,6 +796,11 @@ dt_vopen(int version, int flags, int *errp,
 		return set_open_errno(dtp, errp, EDT_READMAXSTACK);
 	fclose(fd);
 
+	/*
+	 * Set the default data rates.
+	 */
+	dtp->dt_options[DTRACEOPT_SWITCHRATE] = NANOSEC;
+
 	dtp->dt_cpp_argv[0] = (char *)strbasename(dtp->dt_cpp_path);
 
 	snprintf(isadef, sizeof(isadef), "-D__SUNW_D_%u",
diff --git a/libdtrace/dt_work.c b/libdtrace/dt_work.c
index 145ce47b..f1292761 100644
--- a/libdtrace/dt_work.c
+++ b/libdtrace/dt_work.c
@@ -173,6 +173,7 @@ dtrace_work(dtrace_hdl_t *dtp, FILE *fp, dtrace_consume_probe_f *pfunc,
 	switch (dtrace_status(dtp)) {
 	case DTRACE_STATUS_EXITED:
 	case DTRACE_STATUS_STOPPED:
+		dtp->dt_lastswitch = 0;
 		rval = DTRACE_WORKSTATUS_DONE;
 		break;
 	case DTRACE_STATUS_NONE:
-- 
2.39.1




More information about the DTrace-devel mailing list