[DTrace-devel] [PATCH 06/13] Add provider-dependent struct in dt_probe_t

Eugene Loh eugene.loh at oracle.com
Wed Jul 8 10:38:18 PDT 2020


On 07/07/2020 11:02 PM, Kris Van Hees wrote:

> On Tue, Jul 07, 2020 at 10:11:44PM -0700, Eugene Loh wrote:
>> On 07/06/2020 02:50 PM, Kris Van Hees wrote:
>>> On Wed, Jul 01, 2020 at 10:41:11PM -0400, eugene.loh at oracle.com wrote:
>>>> From: Eugene Loh <eugene.loh at oracle.com>
>>>>
>>>> The dt_probe_t struct had members like event_id and event_fd.
>>>> This made sense for the providers we were supporting, since they
>>>> were all tracepoint-like.  For future providers, however, those
>>>> members might not make sense and others will be needed.  Therefore,
>>>> replace event_id and event_fd with an opaque pointer to a
>>>> provider-dependent struct.
>>>>
>>>> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
>>>>
>>>> diff --git a/libdtrace/dt_probe.c b/libdtrace/dt_probe.c
>>>> index be407dd2..496ba11e 100644
>>>> --- a/libdtrace/dt_probe.c
>>>> +++ b/libdtrace/dt_probe.c
>>>> @@ -505,6 +505,7 @@ dt_probe_destroy(dt_probe_t *prp)
>>>>    
>>>>    	if (prp->prov && prp->prov->impl && prp->prov->impl->probe_fini)
>>>>    		prp->prov->impl->probe_fini(dtp, prp);
>>>> +	dt_free(dtp, prp->prv_data);
>>> OK
>>>
>>>>    
>>>>    	dt_node_list_free(&prp->nargs);
>>>>    	dt_node_list_free(&prp->xargs);
>>>> @@ -665,7 +666,8 @@ dt_probe_tag(dt_probe_t *prp, uint_t argn, dt_node_t *dnp)
>>>>    }
>>>>    
>>>>    dt_probe_t *
>>>> -dt_probe_insert(dtrace_hdl_t *dtp, dt_provider_t *prov, const char *prv,
>>>> +dt_probe_insert(dtrace_hdl_t *dtp, dt_provider_t *prov, const void *prv_data,
>>>> +		const char *prv,
>>>>    		const char *mod, const char *fun, const char *prb)
>>> Please move the prv_data to the end of the argument list, which is more
>>> consistent with other code that supports opaque pointers.  It also shows its
>>> status as auxilliary information rather than being mixed with the elements
>>> that are part of the generic probe.  And perhaps name it datap since that is
>>> the name you used for the provider-specific data variable in other places.
>>>
>>> I would also modify dt_probe_insert() to free datap (if not NULL) if the probe
>>> cannot be created.  That avoids needing to have each caller check if the probe
>>> got created, and if not, free datap.

Maybe this is beside the point but FWIW with all tp providers using the 
new tp_probe_insert(), there are much fewer callers of dt_probe_insert() 
than there were before.  FWIW.

>> I don't think this really works.  The datap points to provider-specific
>> stuff.  It might even point to memory that contains pointers to other
>> things.  So the provider needs to free datap.
>>
>> Another option is that the provider only allocates datap but doesn't set
>> up the memory to which datap points, doing that only once the probe has
>> been inserted.  But then if there is a problem with initializing the
>> memory to which datap points, would we want to delete the probe we just
>> inserted?  We do not yet have a good function for that (deleting one
>> probe, vs cleaning them all up at the end... e.g., never do we decrement
>> dt_probe_id).
>>
>> Anyhow, one can shoehorn the change you're talking about, but it strikes
>> me as pretty ugly.
>>
>>> You already do a freeing of the datap in
>>> dt_probr_destroy() so doing it in dt_probe_insert() as well (when needed) is
>>> OK.
>> Well, no.  I mean, yes, there is a free(datap) in dt_probe_destroy(),
>> but it comes right after calling the provider-specific fini() function.
>> So, do we want dt_probe_insert(), called by a provider, to then call a
>> provider-specific callback we need to define?  My head is spinning just
>> thinking of the back-and-forth.
> If we anticipate that the provider-specific data will contains pointers to
> other memory blocks that would need to be cleaned up along with it (I cannot
> really think of a need for that in any provider we're planning to support but
> it might turn out to be needed)

What about the profile provider?  For profile-n probes, we have 
something on each CPU.  So we end up with an array of file descriptors, 
one per CPU.  datap points to (among other things) a pointer to such an 
array.

> then we will be needing a function to destroy
> the provider-specific data anyhow.

Right.  The probe_fini() function.  Just seems funny to me to have the 
provider call dt_probe_insert(), which calls back to the provider, then 
returns to dt_probe_insert(), and then back to the provider.  
Nevertheless, just calling probe_fini(dtp,prp) here simply doesn't work 
since it takes a prp argument;  meanwhile, the particular case we're 
discussing here is when we are unable to create a prp.

> I think it is safe right now to just have
> dt_probe_insert() do it (similar to dt_probe_destroy())
>
> The fact that the one in dt_probe_destroy() comes after calling a probe_fini()
> (if one exists) is not really a good argument.  You wouldn't want the fini()
> to do the cleanup of stuff referenced from datap and then have datap free'd
> by dt_probe_destroy().

Why wouldn't I?

Actually, let's just assume we won't agree on the woulds and shoulds.  
Let's just figure out some way that works.  I don't care if it seems 
unnecessarily convoluted to me;  if I can implement it, I will.  If I 
understand what you're proposing:

*)  introduce a new provider-specific function ("data_free" maybe?) that 
takes a datap and
frees resources it points to as well as freeing datap itself

*)  have dt_probe_insert() try to form a prp;  if it cannot, it will 
call the new function and then return a NULL prp

*)  change probe_fini() to take advantage of the new function

Do I understand correctly?  If that's what you're proposing, I will 
implement it.

> If you envision more complex datap variants where there
> is additional allocated data, then we really need to have a function to handle
> the freeing of datap and related structures.  And that can then be called from
> dt_probe_insert() if the probe creation fails.
>
> I still think a plan free of datap in dt_probe_insert() suffices for now, and
> we can always implement a function to do the freeing later if it turns out to
> be necessary.  Right now it seems to be a bit of over-engineering.
>
>>> The caller can count on the fact that if the probe could not be created,
>>> datap is no longer valid.



More information about the DTrace-devel mailing list