[DTrace-devel] [PATCH 19/38] Retain probe descriptions
Eugene Loh
eugene.loh at oracle.com
Fri Jul 19 03:34:05 UTC 2024
What do you think about replacing the array dt_retained[n] (as in,
"dt_clause_$n") with a hash table that uses a string (like
"dt_clause_$n") to look up a probe description?
On 7/18/24 17:25, Kris Van Hees wrote:
> I think this needs an actual description of what you are trying to do,
An underlying probe gets a list of clauses to call in its trampoline.
Actually, the underlying probe looks up a mask in some BPF map and then
walks the clauses, calling them conditionally based on the mask bits.
To construct the mask for a particular overlying probe, we walk the
clauses. Each clause is associated with a particular probe
description. We compare the overlying probe to the respective probe
description to decide whether to set that particular bit.
So, a uprp has a list of clauses. We want some way of getting from
clauses to probe descriptions. The linear array using that $n was one
way. I can move over to the hash table based on clause string name if
you prefer.
(Incidentally, a uprp's clause list is set during dt_probe_add_clause(),
at which point we do not know the motivating probe description.
> because
> retaining pdescs in and of itself does not seem meaningful. They do not
> contain a reference to the clause they were associated with when the code was
> parsed and compiled) and it seems to me that you are doing a sort-of reverse
> association, and are actually (indirectly) retaining clauses by keeping a
> link of pdescs, one per clause. And you identify the clause by its numeric
> id as obtained from its identifier name (which is dynamically assigned during
> compilation). That seems fragile and rather non-intuitive.
>
> If memory serves me right, the intent was to retain enablings. Of course, in
> the current implementation of DTrace, enablings are nothing more than probes
> because the probes have BPF programs associated with them (unless they are
> overlying probes, in which case the actual code that gets loaded is part of the
> BPF program of the underlying probe (which will be in the enablings list).
>
> When we are retaining enablings, it seems to me that it would make more sense
> to keep a list of objects { pdesc, clause } where clause would be the
> identifier name of the compiled clause (similar to a function name). Using a
> pointer to the actual clause instead is (I think) not going to work becauase
> AFAIK the clause does not store a pointer to its own identiifier.
>
> In the end, this will largely do the same thing as your code (here and when it
> gets used later), but it removes the implied dependency on how identifier names
> for clauses are generated. That could change in the future, and doing so would
> completely break this imlementation.
>
> On Thu, Jun 27, 2024 at 01:38:10AM -0400, eugene.loh at oracle.com wrote:
>> From: Eugene Loh <eugene.loh at oracle.com>
>>
>> To support matching probes after dtrace has started, we retain
>> probe descriptions.
>>
>> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
>> ---
>> libdtrace/dt_impl.h | 2 ++
>> libdtrace/dt_program.c | 37 ++++++++++++++++++++++++++++++++++++-
>> 2 files changed, 38 insertions(+), 1 deletion(-)
>>
>> diff --git a/libdtrace/dt_impl.h b/libdtrace/dt_impl.h
>> index 2132eda2..445cd602 100644
>> --- a/libdtrace/dt_impl.h
>> +++ b/libdtrace/dt_impl.h
>> @@ -300,6 +300,8 @@ struct dtrace_hdl {
>> dt_list_t dt_programs; /* linked list of dtrace_prog_t's */
>> dt_list_t dt_xlators; /* linked list of dt_xlator_t's */
>> dt_list_t dt_enablings; /* list of (to be) enabled probes */
>> + dtrace_probedesc_t **dt_retained; /* array of retained pdescs */
>> + int dt_maxretained; /* number of retained pdescs allocated */
>> struct dt_xlator **dt_xlatormap; /* dt_xlator_t's indexed by dx_id */
>> id_t dt_xlatorid; /* next dt_xlator_t id to assign */
>> dt_ident_t *dt_externs; /* linked list of external symbol identifiers */
>> diff --git a/libdtrace/dt_program.c b/libdtrace/dt_program.c
>> index a4b052fc..7106c249 100644
>> --- a/libdtrace/dt_program.c
>> +++ b/libdtrace/dt_program.c
>> @@ -163,7 +163,42 @@ dt_prog_stmt(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, dtrace_stmtdesc_t *sdp,
>> {
>> pi_state_t st;
>> dtrace_probedesc_t *pdp = &sdp->dtsd_ecbdesc->dted_probe;
>> - int rc;
>> + char *sclause = sdp->dtsd_clause->di_name;
>> + int rc, nclause;
>> +
>> + /* Get the clause number from the clause name "dt_clause_"$n. */
>> + assert(strncmp(sclause, "dt_clause_", strlen("dt_clause_")) == 0); // FIXME can probably drop this check (make sure the name starts "dt_clause_")
>> + nclause = atoi(sclause + strlen("dt_clause_"));
>> + assert(nclause < 65536); // FIXME are we okay here with some arbitrary limit?
>> +
>> + /* Grow the list of retained pdescs, if necessary. */
>> + if (nclause >= dtp->dt_maxretained) {
>> + int newm;
>> + dtrace_probedesc_t **newr;
>> +
>> + /* Figure how big to make the array. */
>> + if (dtp->dt_maxretained > 0)
>> + newm = 2 * dtp->dt_maxretained;
>> + else
>> + newm = 8;
>> + while (newm <= nclause)
>> + newm *= 2;
>> +
>> + /* Allocate the bigger array. */
>> + newr = dt_zalloc(dtp, newm * sizeof(dtrace_probedesc_t *));
>> + if (newr == NULL)
>> + return 0;
>> +
>> + /* Copy data and reset the parameters. */
>> + memcpy(newr, dtp->dt_retained, dtp->dt_maxretained * sizeof(dtrace_probedesc_t *));
>> + dt_free(dtp, dtp->dt_retained);
>> + dtp->dt_retained = newr;
>> + dtp->dt_maxretained = newm;
>> + }
>> +
>> + /* Add probe description to retained pdescs. */
>> + assert(dtp->dt_retained[nclause] == NULL); // FIXME can probably drop this
>> + dtp->dt_retained[nclause] = pdp; // FIXME I think just pointing to pdp is okay. No need to cache my own copy.
>>
>> st.cnt = cnt;
>> st.idp = sdp->dtsd_clause;
>> --
>> 2.18.4
>>
More information about the DTrace-devel
mailing list