[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