[DTrace-devel] [PATCH 04/16] cpc: Add probe-args tests

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


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

A few additional utilities are added to support these and future tests:

  * workload_kernel.c is a simple, kernel-intensive workload

  * perf_count_event.sh uses "perf stat" to count some event for
    some executable

Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
---
 test/unittest/cpc/tst.args_kernel.sh | 79 ++++++++++++++++++++++++
 test/unittest/cpc/tst.args_user.sh   | 90 ++++++++++++++++++++++++++++
 test/utils/.gitignore                |  1 +
 test/utils/Build                     |  2 +-
 test/utils/perf_count_event.sh       | 28 +++++++++
 test/utils/workload_kernel.c         | 44 ++++++++++++++
 6 files changed, 243 insertions(+), 1 deletion(-)
 create mode 100755 test/unittest/cpc/tst.args_kernel.sh
 create mode 100755 test/unittest/cpc/tst.args_user.sh
 create mode 100755 test/utils/perf_count_event.sh
 create mode 100644 test/utils/workload_kernel.c

diff --git a/test/unittest/cpc/tst.args_kernel.sh b/test/unittest/cpc/tst.args_kernel.sh
new file mode 100755
index 00000000..0cb2480a
--- /dev/null
+++ b/test/unittest/cpc/tst.args_kernel.sh
@@ -0,0 +1,79 @@
+#!/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
+
+# use "perf" to get total
+total=`$utils/perf_count_event.sh cpu-clock $target $niters`
+if [ $total -lt 0 ]; then
+	echo "perf_count_event.sh failed with $target"
+	exit 1
+fi
+
+# set how many probe firings to expect
+expect=100
+period=$(($total / $expect))
+
+# run DTrace
+echo $niters iterations and period $period
+$dtrace $dt_flags -qn '
+	cpc:::cpu_clock-all-'$period'
+	/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/cpc/tst.args_user.sh b/test/unittest/cpc/tst.args_user.sh
new file mode 100755
index 00000000..a882635d
--- /dev/null
+++ b/test/unittest/cpc/tst.args_user.sh
@@ -0,0 +1,90 @@
+#!/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
+
+# use "perf" to get total
+total=`$utils/perf_count_event.sh cpu-clock $target $niters`
+if [ $total -lt 0 ]; then
+	echo "perf_count_event.sh failed with $target"
+	exit 1
+fi
+
+# set how many probe firings to expect
+expect=100
+period=$(($total / $expect))
+
+# run DTrace
+echo $niters iterations and period $period
+$dtrace $dt_flags -qn '
+	cpc:::cpu_clock-all-'$period'
+	/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
diff --git a/test/utils/.gitignore b/test/utils/.gitignore
index d8e2ccb5..7c25cb18 100644
--- a/test/utils/.gitignore
+++ b/test/utils/.gitignore
@@ -1,6 +1,7 @@
 # In-place built executables
 baddof
 badioctl
+workload_kernel
 workload_user
 print-stack-layout
 showUSDT
diff --git a/test/utils/Build b/test/utils/Build
index b57cdda8..5cc8e090 100644
--- a/test/utils/Build
+++ b/test/utils/Build
@@ -3,7 +3,7 @@
 # Licensed under the Universal Permissive License v 1.0 as shown at
 # http://oss.oracle.com/licenses/upl.
 
-TEST_UTILS = baddof badioctl workload_user showUSDT print-stack-layout
+TEST_UTILS = baddof badioctl workload_kernel workload_user showUSDT print-stack-layout
 
 define test-util-template
 CMDS += $(1)
diff --git a/test/utils/perf_count_event.sh b/test/utils/perf_count_event.sh
new file mode 100755
index 00000000..606a18d6
--- /dev/null
+++ b/test/utils/perf_count_event.sh
@@ -0,0 +1,28 @@
+#!/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.
+
+# count some event for some executable
+
+# get the test/utils directory name
+utils=`dirname $0`
+
+# get the event to count
+event=$1
+
+# the rest of the command line is the executable and its arguments
+shift
+
+# Use "perf stat" to count "event" for this executable and its children.
+#   If the output is no good, report -1.
+#   If the output is time in msec, convert to nsec.
+#   Otherwise, just report the count.
+perf stat -e $event --no-big-num -x\  $utils/$* |& awk '
+/^[^0-9]/ { print -1; exit 1 }
+/ msec / { print int(1000000. * $1); exit 0 }
+{ print $1; exit 0 }'
+
+exit 0
diff --git a/test/utils/workload_kernel.c b/test/utils/workload_kernel.c
new file mode 100644
index 00000000..1368a300
--- /dev/null
+++ b/test/utils/workload_kernel.c
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include <stdlib.h>
+#define BUFLEN 256
+
+#if 0
+/* use getrandom() wrapper in glibc */
+#include <sys/random.h>
+#else
+/* getrandom() wrapper was not added to glibc until 2.25 */
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/random.h>
+ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
+	return syscall(__NR_getrandom, buf, buflen, flags);
+}
+#endif
+
+/*
+ * The command-line argument specifies how many iterations to execute
+ * in this kernel-intensive loop to run.
+ */
+
+int
+main(int argc, const char **argv)
+{
+	char buf[BUFLEN];
+	long long n;
+
+	if (argc < 2)
+		return 1;
+	n = atoll(argv[1]);
+
+	for (long long i = 0; i < n; i++)
+		if (getrandom(buf, BUFLEN, GRND_NONBLOCK) != BUFLEN)
+			return 1;
+
+	return 0;
+}
-- 
2.18.4




More information about the DTrace-devel mailing list