[DTrace-devel] [PATCH 5/7] Consolidate like keys for @[mod()], @[sym()], etc.

eugene.loh at oracle.com eugene.loh at oracle.com
Tue Mar 12 01:00:55 UTC 2024


From: Eugene Loh <eugene.loh at oracle.com>

Certain actions like mod() and sym() take address arguments and
report string values.  These values can be used as aggregation
keys.

DTrace happens to pass the raw addresses from producer to consumer,
for the consumer to convert to strings and combine like keys for
aggregation.  The reduction of common values had been omitted in the
DTrace-to-Linux port.

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_aggregate.c              | 38 ++++++++++++++++++++-------
 test/unittest/aggs/tst.aggmod_full.sh |  4 +--
 test/unittest/profile-n/tst.ufunc.sh  | 29 ++++++++++++++------
 test/unittest/profile-n/tst.umod.sh   | 26 +++++++++++++-----
 test/unittest/profile-n/tst.usym.sh   | 27 ++++++++++++++-----
 5 files changed, 91 insertions(+), 33 deletions(-)

diff --git a/libdtrace/dt_aggregate.c b/libdtrace/dt_aggregate.c
index b0642e65..6472360b 100644
--- a/libdtrace/dt_aggregate.c
+++ b/libdtrace/dt_aggregate.c
@@ -278,12 +278,11 @@ dt_aggregate_quantizedcmp(int64_t *lhs, int64_t *rhs)
 	return 0;
 }
 
-#ifdef FIXME
 static void
 dt_aggregate_usym(dtrace_hdl_t *dtp, uint64_t *data)
 {
-	uint64_t tgid = data[1];
-	uint64_t *pc = &data[2];
+	uint64_t tgid = data[0];
+	uint64_t *pc = &data[1];
 	pid_t pid;
 	GElf_Sym sym;
 
@@ -304,8 +303,8 @@ dt_aggregate_usym(dtrace_hdl_t *dtp, uint64_t *data)
 static void
 dt_aggregate_umod(dtrace_hdl_t *dtp, uint64_t *data)
 {
-	uint64_t tgid = data[1];
-	uint64_t *pc = &data[2];
+	uint64_t tgid = data[0];
+	uint64_t *pc = &data[1];
 	pid_t pid;
 	const prmap_t *map;
 
@@ -379,7 +378,6 @@ dt_aggregate_mod(dtrace_hdl_t *dtp, uint64_t *addr)
 		}
 	}
 }
-#endif
 
 static dtrace_aggid_t
 dt_aggregate_aggid(dt_ahashent_t *ent)
@@ -514,7 +512,7 @@ dt_aggregate_snap_one(dtrace_hdl_t *dtp, int aggid, int cpu, const char *key,
 	uint64_t		dgen;
 	size_t			ndx = hval % agh->dtah_size;
 	size_t			size;
-	int			rval;
+	int			rval, i;
 
 	/* Data generation: skip if 0 */
 	dgen = *(uint64_t *)data;
@@ -526,6 +524,28 @@ dt_aggregate_snap_one(dtrace_hdl_t *dtp, int aggid, int cpu, const char *key,
 	if (rval != 0)
 		return rval;
 
+	/* Reduce addresses. */
+	for (i = 0; i < agg->dtagd_nkrecs; i++) {
+		uint64_t *p = (uint64_t *)&key[agg->dtagd_krecs[i].dtrd_offset];
+
+		switch(agg->dtagd_krecs[i].dtrd_action) {
+		case DTRACEACT_USYM:
+			dt_aggregate_usym(dtp, p);
+			break;
+		case DTRACEACT_UMOD:
+			dt_aggregate_umod(dtp, p);
+			break;
+		case DTRACEACT_SYM:
+			dt_aggregate_sym(dtp, p);
+			break;
+		case DTRACEACT_MOD:
+			dt_aggregate_mod(dtp, p);
+			break;
+		default:
+			break;
+		}
+	}
+
 	/* See if we already have an entry for this aggregation. */
 	for (h = agh->dtah_hash[ndx]; h != NULL; h = h->dtahe_next) {
 		dt_ident_t	*aid;
@@ -654,10 +674,10 @@ dt_aggregate_snap_cpu(dtrace_hdl_t *dtp, processorid_t cpu, int fd)
 
 		memcpy(key, nxt, ksize);
 
-		if (dt_bpf_map_lookup(fd, key, data) == -1)
+		if (dt_bpf_map_lookup(fd, nxt, data) == -1)
 			return dt_set_errno(dtp, EDT_BPF);
 
-		rval = dt_aggregate_snap_one(dtp, *aggidp, cpu, key, data);
+		rval = dt_aggregate_snap_one(dtp, *aggidp, cpu, nxt, data);
 		if (rval != 0)
 			return rval;
 	}
diff --git a/test/unittest/aggs/tst.aggmod_full.sh b/test/unittest/aggs/tst.aggmod_full.sh
index 9707340d..5a9286cf 100755
--- a/test/unittest/aggs/tst.aggmod_full.sh
+++ b/test/unittest/aggs/tst.aggmod_full.sh
@@ -17,8 +17,6 @@
 #
 ##
 
-# @@xfail: dtv2
-
 # Big batches of addresses are tested at once in order to
 #   - manage run times
 #   - check that each module appears with a single name
@@ -225,7 +223,7 @@ fi
 # if the timeout will soon be reached, just report how many we checked.
 # But do insist that some minimum number have been checked.
 
-progress_done_min=3000
+progress_done_min=800
 if [[ $progress_done -lt $progress_done_min ]]; then
 	echo "ERROR: only $progress_done symbols checked"
 	echo "ERROR:   expect minimum of $progress_done_min"
diff --git a/test/unittest/profile-n/tst.ufunc.sh b/test/unittest/profile-n/tst.ufunc.sh
index 74ab6201..28b7c05b 100755
--- a/test/unittest/profile-n/tst.ufunc.sh
+++ b/test/unittest/profile-n/tst.ufunc.sh
@@ -6,6 +6,8 @@
 # http://oss.oracle.com/licenses/upl.
 #
 
+tmpfile=$tmpdir/tst.profile_ufunc.$$
+
 script()
 {
 	$dtrace $dt_flags -qs /dev/stdin <<EOF
@@ -40,13 +42,24 @@ spinny &
 child=$!
 disown %+
 
-#
-# The only thing we can be sure of here is that we caught some function in
-# bash doing work.  (This actually goes one step further and assumes that we
-# catch some non-static function in bash.)
-#
-script | tee /dev/fd/2 | grep 'bash`[a-zA-Z_]' > /dev/null
-status=$? 
-
+script >& $tmpfile
 kill $child
+
+# Check that some non-static function in bash is doing work.
+status=0
+if ! grep -q 'bash`[a-zA-Z_]' $tmpfile; then
+	echo ERROR: expected bash functions are missing
+	status=1
+fi
+
+# Check that functions are unique.  (Exclude shared libraries and unresolved addresses.)
+if awk '!/^ *lib/ && !/^ *0x/ {print $1}' $tmpfile | sort | uniq -c | grep -qv " 1 "; then
+	echo ERROR: duplicate ufunc
+	status=1
+fi
+
+if [ $status -ne 0 ]; then
+	cat $tmpfile
+fi
+
 exit $status
diff --git a/test/unittest/profile-n/tst.umod.sh b/test/unittest/profile-n/tst.umod.sh
index 6a7382ea..ea4f7ec5 100755
--- a/test/unittest/profile-n/tst.umod.sh
+++ b/test/unittest/profile-n/tst.umod.sh
@@ -6,6 +6,8 @@
 # http://oss.oracle.com/licenses/upl.
 #
 
+tmpfile=$tmpdir/tst.profile_umod.$$
+
 script()
 {
 	$dtrace $dt_flags -qs /dev/stdin <<EOF
@@ -40,11 +42,23 @@ spinny &
 child=$!
 disown %+
 
-#
-# The only thing we can be sure of here is that bash is doing some work.
-#
-script | tee /dev/fd/2 | grep -w bash > /dev/null
-status=$? 
-
+script >& $tmpfile
 kill $child
+
+# Check that bash is doing work.
+status=0
+if ! grep -wq 'bash' $tmpfile; then
+	echo ERROR: expected bash functions are missing
+	status=1
+fi
+
+# Check that modules are unique.  (Exclude shared libraries and unresolved addresses.)
+if awk '!/^ *lib/ && !/^ *0x/ {print $1}' $tmpfile | sort | uniq -c | grep -qv " 1 "; then
+	echo ERROR: duplicate umod
+	status=1
+fi
+
+if [ $status -ne 0 ]; then
+	cat $tmpfile
+fi
 exit $status
diff --git a/test/unittest/profile-n/tst.usym.sh b/test/unittest/profile-n/tst.usym.sh
index 5f2df717..72ff4fd4 100755
--- a/test/unittest/profile-n/tst.usym.sh
+++ b/test/unittest/profile-n/tst.usym.sh
@@ -6,6 +6,8 @@
 # http://oss.oracle.com/licenses/upl.
 #
 
+tmpfile=$tmpdir/tst.profile_usym.$$
+
 script()
 {
 	$dtrace $dt_flags -qs /dev/stdin <<EOF
@@ -40,12 +42,23 @@ spinny &
 child=$!
 disown %+
 
-#
-# This test is essentially the same as that in the ufunc test; see that
-# test for the rationale.
-#
-script | tee /dev/fd/2 | grep 'bash`[a-zA-Z_]' > /dev/null
-status=$? 
-
+script >& $tmpfile
 kill $child
+
+# Check that some non-static function in bash is doing work.
+status=0
+if ! grep -q 'bash`[a-zA-Z_]' $tmpfile; then
+	echo ERROR: expected bash functions are missing
+	status=1
+fi
+
+# Check that symbols are unique.  (Exclude shared libraries and unresolved addresses.)
+if awk '!/^ *lib/ && !/^ *0x/ {print $1}' $tmpfile | sort | uniq -c | grep -qv " 1 "; then
+	echo ERROR: duplicate usym
+	status=1
+fi
+
+if [ $status -ne 0 ]; then
+	cat $tmpfile
+fi
 exit $status
-- 
2.18.4




More information about the DTrace-devel mailing list