[DTrace-devel] [PATCH 7/9] Consolidate bpf_get_stack()-call code generation for stack and ustack()
Eugene Loh
eugene.loh at oracle.com
Fri Jan 26 17:43:30 UTC 2024
On 1/24/24 01:59, Kris Van Hees wrote:
> On Thu, Oct 05, 2023 at 05:14:05PM -0400, eugene.loh at oracle.com wrote:
>> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
>> @@ -2225,33 +2225,90 @@ dt_cg_ustack_arg(dtrace_hdl_t *dtp, dt_node_t *dnp)
>> -static void
>> -dt_cg_act_stack(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>> +/*
>> + * Call the bpf_get_stack() helper function.
>> + *
>> + * dnp->dn_arg has optional, integer-constant sizing information.
>> + *
>> + * If reg>=0, reg is a register holding the output pointer.
>> + * If reg<0, we write the stack to the output buffer in %r9.
>> + *
>> + * These cases treat "off" differently:
>> + * - reg>=0: "off" tracks how far the pointer in "reg" has
>> + * been advanced, both at function entry and return
>> + *
>> + * - reg<0: "off" is basically just a local variable since
>> + * offsets with the %r9 buffer are managed by
>> + * dt_rec_add()
>> + *
>> + * The "user" flag indicates whether a user (or kernel) stack is desired.
>> + */
>> +static int
>> +dt_cg_act_stack_sub(dt_pcb_t *pcb, dt_node_t *dnp, int reg, int off, int user)
>> {
>> dtrace_hdl_t *dtp = pcb->pcb_hdl;
>> dt_irlist_t *dlp = &pcb->pcb_ir;
>> dt_regset_t *drp = pcb->pcb_regs;
>> - int nframes;
>> - int skip = 0;
>> - uint_t off;
>> + uint64_t arg;
>> + int nframes, stacksize, prefsz, align = sizeof(uint64_t);
>> uint_t lbl_valid = dt_irlist_label(dlp);
>>
>> - nframes = dt_cg_stack_nframes(dtp, dnp);
>> + /* Get sizing information from dnp->dn_arg. */
>> + if (user) {
>> + arg = dt_cg_ustack_arg(dtp, dnp);
>> + nframes = DTRACE_USTACK_NFRAMES(arg);
>> + prefsz = sizeof(uint64_t);
>> + } else {
>> + nframes = dt_cg_stack_nframes(dtp, dnp);
>> + arg = nframes;
>> + prefsz = 0;
>> + }
> I think you might as well not have dt_cg_ustack_arg() and dt_cg_stack_nframes()
> and instead inline what they do here. Especially since (modulo some constant
> values) there is duplication for the handling of the first argument anyway.
>
> In that sense, I don't think the [5/9] patch in this series is needed at all,
> because that one introduces those two functions. But if we are not going to
> be using them anyway per my suggestion above, there is no need to introduce
> them. And that also makes [6/9] (moving one of those functions) unnecessary.
>
> Besides, patch [5/9] mentions that it refactors dt_cg_act_stack() amd
> dt_cg_act_ustack() so that what they do can be invoked by multiple callers,
> but that is not really what that patch does. The new functions it introduces
> are never called by more than a single caller, and in this patch [8/9] the
> actual implementation of stack and ustack is moved into a function that then
> can be called from multiple callers for real.
>
> So, I think you can just use this patch (with modifications) to provide a
> subroutine function that handles the real work of performing stack() and
> ustack(), and then the next patch in the series hooks it up to the arglist
> code to support using stack(), ustack(), etc as elements in a tuple.
Thanks for your comments on the @[stack()] patch series.
I've been trying to digest and incorporate your feedback, but at some
point I get stuck.
I think the linchpin for the remaining issues are your comments here.
Yes, the function(s) that determine arg/nframes are used by the
integrated (stack and ustack) dt_cg_act_stack_sub(), and that one
function is used both for the u/stack() actions and for arglist.
But that does not mean that the dt_cg_ustack_arg() and
dt_cg_stack_nframes() functions are called from only one spot. The 8/9
patch adds a call site: after the cg for the agg's arglist is finished,
we then have to add size information for the agg. At this point, we
make the arg/nframes calls. So, inlining the arg/nframes stuff would
mean having to inline in two places: once where you indicate and again
at the new site/s introduced by the 8/9 patch.
But maybe I miss what you're getting at.
>> + stacksize = nframes * sizeof(uint64_t);
>> +
>> + /* Handle alignment and reserve space in the output buffer. */
>> + if (reg >= 0) {
>> + uint_t nextoff;
>> + nextoff = (off + (align - 1)) & ~(align - 1);
>> + if (off < nextoff)
>> + emit(dlp, BPF_ALU64_IMM(BPF_ADD, reg, nextoff - off));
>> + off = nextoff + prefsz + stacksize;
>> + } else {
>> + off = dt_rec_add(dtp, dt_cg_fill_gap,
>> + user ? DTRACEACT_USTACK : DTRACEACT_STACK,
>> + prefsz + stacksize, align, NULL, arg);
>> + }
>>
More information about the DTrace-devel
mailing list