[DTrace-devel] [PATCH 16/16] Fix profile-provider probe args arg0 and arg1

eugene.loh at oracle.com eugene.loh at oracle.com
Fri Jan 27 02:23:29 UTC 2023


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

Set arg0 and arg1 for the profile provider.

Note that arg2 is still not unimplemented.

Add stronger tests for profile-* probe args.  (Since the new tests use
a target process that might be running on a different CPU from where
a tick-* probe fires, we do not add corresponding tick-* tests.
On the other hand, testing arg0 and arg1 for profile-* ought to be
sufficient.)

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 libdtrace/dt_prov_profile.c                | 34 ++++-----
 test/unittest/profile-n/tst.args_kernel.sh | 74 +++++++++++++++++++
 test/unittest/profile-n/tst.args_user.sh   | 85 ++++++++++++++++++++++
 3 files changed, 175 insertions(+), 18 deletions(-)
 create mode 100755 test/unittest/profile-n/tst.args_kernel.sh
 create mode 100755 test/unittest/profile-n/tst.args_user.sh

diff --git a/libdtrace/dt_prov_profile.c b/libdtrace/dt_prov_profile.c
index 6d1d3a80..cf391566 100644
--- a/libdtrace/dt_prov_profile.c
+++ b/libdtrace/dt_prov_profile.c
@@ -1,6 +1,6 @@
 /*
  * Oracle Linux DTrace.
- * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved.
  * Licensed under the Universal Permissive License v 1.0 as shown at
  * http://oss.oracle.com/licenses/upl.
  *
@@ -229,28 +229,26 @@ static void trampoline(dt_pcb_t *pcb)
 	dt_cg_tramp_copy_regs(pcb);
 
 	/*
-	 * TODO:
-	 * For profile-n probes:
-	 *     dctx->mst->argv[0] = kernel PC
-	 *     dctx->mst->argv[1] = userspace PC
+	 * dctx->mst->argv[0] = kernel PC
+	 * dctx->mst->argv[1] = userspace PC
+	 */
+        dt_cg_tramp_copy_PC_from_regs(pcb);
+
+	/*
+	 * TODO: For profile-n probes:
 	 *     dctx->mst->argv[2] = elapsed nsecs
-	 *
-	 * For tick-n probes:
-	 *     dctx->mst->argv[0] = kernel PC
-	 *     dctx->mst->argv[1] = userspace PC
-	 *
-	 * For now, we can only provide the first argument:
-	 *     dctx->mst->argv[0] = PT_REGS_IP((dt_pt_regs *)&dctx->ctx->regs);
-	 *                              //  lddw %r0, [%r8 + PT_REGS_IP]
-	 *                              //  stdw [%r7 + DMST_ARG(0)], %r0
+	 * The documentation does not say elapsed since when?
+	 * From the legacy port to Oracle Linux, in dtrace/profile_dev.c,
+	 * in profile_prof_fn(), it appears that we have a per-CPU variable
+	 * that tracks the expected time of the next profile probe.
+	 * Each time the probe fires, we compute arg2 = time - expected
+	 * and update expected+=interval.
 	 */
-	emit(dlp, BPF_LOAD(BPF_DW, BPF_REG_0, BPF_REG_8, PT_REGS_IP));
-	emit(dlp, BPF_STORE(BPF_DW, BPF_REG_7, DMST_ARG(0), BPF_REG_0));
 
 	/*
-	 *     (we clear dctx->mst->argv[1] and on)
+	 *     (we clear dctx->mst->argv[2] and on)
 	 */
-	for (i = 1; i < ARRAY_SIZE(((dt_mstate_t *)0)->argv); i++)
+	for (i = 2; i < ARRAY_SIZE(((dt_mstate_t *)0)->argv); i++)
 		emit(dlp, BPF_STORE_IMM(BPF_DW, BPF_REG_7, DMST_ARG(i), 0));
 
 	dt_cg_tramp_epilogue(pcb);
diff --git a/test/unittest/profile-n/tst.args_kernel.sh b/test/unittest/profile-n/tst.args_kernel.sh
new file mode 100755
index 00000000..d489e554
--- /dev/null
+++ b/test/unittest/profile-n/tst.args_kernel.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+
+# @@reinvoke-failure: 1
+
+utils=`pwd`/test/utils
+
+dtrace=$1
+tmpfile=$tmpdir/tst.args_kernel.$$
+mkdir $tmpfile
+cd $tmpfile
+
+target=workload_kernel
+
+# determine number of iterations for target number of seconds
+nsecs=2
+niters=`$utils/workload_get_iterations.sh $target $nsecs`
+if [ $niters -lt 0 ]; then
+	echo "workload_get_iterations.sh failed with $target"
+	exit 1
+fi
+
+# set how many probe firings to expect
+expect=100
+
+# set the probe period (in msec)
+period=$(($nsecs * 1000 / $expect))
+
+# run DTrace
+echo $niters iterations and period $period msec
+$dtrace $dt_flags -qn '
+	profile:::profile-'$period'ms
+	/pid == $target/
+	{
+		printf("%x %x\n", arg0, arg1);
+	}' -c "$utils/$target $niters" | awk 'NF == 2' | sort | uniq -c > D.out
+if [[ $? -ne 0 ]]; then
+	echo ERROR running DTrace
+	cat D.out
+	exit 1
+fi
+
+echo "summary of D output (occurrences, arg0, arg1)"
+cat D.out
+
+# check the PCs
+read ntotal nwarn nerror <<< `awk '
+BEGIN { ntotal = nwarn = nerror = 0; }
+
+# file reports 1:occurrences, 2:arg0, 3:arg1
+                                             { ntotal += $1 }
+$3 != 0                                      { nwarn  += $1 }
+$2 == 0 && $3 == 0                           { nerror += $1 }
+$2 != 0 && $3 != 0                           { nerror += $1 }
+rshift(strtonum("0x"$2), 63) == 0 && $2 != 0 { nerror += $1 }
+rshift(strtonum("0x"$3), 63) != 0            { nerror += $1 }
+
+# report
+END {
+	print ntotal, nwarn, nerror;
+}' D.out`
+
+# report
+status=0
+margin=$(($expect / 10))
+$utils/check_result.sh $ntotal $expect $margin; status=$(($status + $?))
+$utils/check_result.sh $nwarn     0    $margin; status=$(($status + $?))
+$utils/check_result.sh $nerror    0       0   ; status=$(($status + $?))
+
+exit $status
diff --git a/test/unittest/profile-n/tst.args_user.sh b/test/unittest/profile-n/tst.args_user.sh
new file mode 100755
index 00000000..c40d2d52
--- /dev/null
+++ b/test/unittest/profile-n/tst.args_user.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+#
+# Oracle Linux DTrace.
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at
+# http://oss.oracle.com/licenses/upl.
+
+# @@reinvoke-failure: 1
+
+utils=`pwd`/test/utils
+
+dtrace=$1
+tmpfile=$tmpdir/tst.args_user.$$
+mkdir $tmpfile
+cd $tmpfile
+
+target=workload_user
+
+# dump the loop PCs
+$utils/workload_analyze_loop.sh $target | awk 'NF == 1' > PCs.txt
+echo PCs in the loop: `cat PCs.txt`
+
+# determine number of iterations for target number of seconds
+nsecs=2
+niters=`$utils/workload_get_iterations.sh $target $nsecs`
+if [ $niters -lt 0 ]; then
+	echo "workload_get_iterations.sh failed with $target"
+	exit 1
+fi
+
+# set how many probe firings to expect
+expect=100
+
+# set the probe period (in msec)
+period=$(($nsecs * 1000 / $expect))
+
+# run DTrace
+echo $niters iterations and period $period msec
+$dtrace $dt_flags -qn '
+	profile:::profile-'$period'ms
+	/pid == $target/
+	{
+		printf("%x %x\n", arg0, arg1);
+	}' -c "$utils/$target $niters" | awk 'NF == 2' | sort | uniq -c > D.out
+if [[ $? -ne 0 ]]; then
+	echo ERROR running DTrace
+	cat D.out
+	exit 1
+fi
+
+echo "summary of D output (occurrences, arg0, arg1)"
+cat D.out
+
+# check the PCs
+read ntotal narg0 narg1 nwarn nerror <<< `awk '
+BEGIN { ntotal = narg0 = narg1 = nwarn = nerror = 0; }
+
+# one file has the PCs that are in the inner loop
+FILENAME == "PCs.txt" { PCs[$1] = 1; next; }
+
+# other file reports 1:occurrences, 2:arg0, 3:arg1
+                                             { ntotal += $1 }
+($2 in PCs)                                  { narg0  += $1 }
+($3 in PCs)                                  { narg1  += $1 }
+$2 != 0                                      { nwarn  += $1 }
+$2 == 0 && $3 == 0                           { nerror += $1 }
+$2 != 0 && $3 != 0                           { nerror += $1 }
+rshift(strtonum("0x"$2), 63) == 0 && $2 != 0 { nerror += $1 }
+rshift(strtonum("0x"$3), 63) != 0            { nerror += $1 }
+
+# report
+END {
+	print ntotal, narg0, narg1, nwarn, nerror;
+}' PCs.txt D.out`
+
+# report
+status=0
+margin=$(($expect / 10))
+$utils/check_result.sh $ntotal $expect $margin; status=$(($status + $?))
+$utils/check_result.sh $narg0     0    $margin; status=$(($status + $?))
+$utils/check_result.sh $narg1  $expect $margin; status=$(($status + $?))
+$utils/check_result.sh $nwarn     0    $margin; status=$(($status + $?))
+$utils/check_result.sh $nerror    0       0   ; status=$(($status + $?))
+
+exit $status
-- 
2.18.4




More information about the DTrace-devel mailing list