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

Kris Van Hees kris.van.hees at oracle.com
Mon Feb 20 17:01:38 UTC 2023


I have seen some intermittent failures for these tests.  It seems to be a bit
unstable (similar to the cpc tst.args_*.sh tests).  Perhaps we should mark them
as unstable for the upcoming release and do further investigation on how they
can be firmed up?

On Thu, Jan 26, 2023 at 09:23:29PM -0500, eugene.loh--- via DTrace-devel wrote:
> 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
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list