[dpdk-dev] [PATCH 2/5] ethdev: add an iterator to match some devargs input
Thomas Monjalon
thomas at monjalon.net
Mon Oct 8 09:58:44 CEST 2018
08/10/2018 09:06, Andrew Rybchenko:
> On 10/8/18 1:25 AM, Thomas Monjalon wrote:
> > --- a/lib/librte_eal/common/include/rte_common.h
> > +++ b/lib/librte_eal/common/include/rte_common.h
> > @@ -164,6 +164,12 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)
> > */
> > #define RTE_PTR_DIFF(ptr1, ptr2) ((uintptr_t)(ptr1) - (uintptr_t)(ptr2))
> >
> > +/**
> > + * Workaround to cast a const field of a structure to non-const type.
> > + */
> > +#define RTE_CAST_FIELD(var,field,type) \
>
> Missing space after each comma.
>
> > + (*(type*)((uintptr_t)(var) + offsetof(typeof(*(var)), field)))
> > +
>
> In general it is bad symptom that we need it. I'd think more that twice
> before adding it :)
Yes, I tried to remove const in the struct but it brings other problems
when assigning const to the non-const fields.
And I think it was a good idea (from Gaetan) to give const hint to these
fields as they are not changed at each iteration.
So yes, it is a nasty hack, but I feel it is the best tradeoff.
[...]
> > --- a/lib/librte_ethdev/rte_ethdev.c
> > +++ b/lib/librte_ethdev/rte_ethdev.c
> > + /* Split bus, device and parameters. */
> > + ret = rte_devargs_parse(&devargs, devargs_str);
>
> rte_devargs_parse() does strdup() for args. It requires free() in the
> function
> if devargs parsed successfully, but init fails.
> In the case of success it is moved to cls_str which is 'const' and I see
> not code which frees it as well.
Oh yes, you're right!
[...]
> > + do { /* loop for matching rte_device */
> > + if (iter->class_device == NULL) {
> > + iter->device = iter->bus->dev_iterate(
> > + iter->device, iter->bus_str, iter);
> > + if (iter->device == NULL)
> > + break;
> > + }
> > + iter->class_device = iter->cls->dev_iterate(
> > + iter->class_device, iter->cls_str, iter);
> > + if (iter->class_device != NULL)
> > + return eth_dev_to_id(iter->class_device);
> > + } while (iter->class_device == NULL);
>
> It is non-obvious what is happening above. It would be very useful to
> add comments which explains it. May be just hints.
OK I will try to add good comments.
> > +
> > + /* No more ethdev port to iterate. */
> > + free(RTE_CAST_FIELD(iter, bus_str, char *)); /* workaround const */
> > + iter->bus_str = NULL;
>
> Who does it if RTE_ETH_FOREACH_MATCHING_DEV caller breaks
> the loop before reaching maximum?
If the app breaks the loop, it becomes a responsibility of the app.
It is documented for the functions but not the macro.
I should add a comment in the doxygen of the macro, thanks.
[...]
> > +#define RTE_ETH_FOREACH_MATCHING_DEV(id, devargs, iter) \
> > + for (rte_eth_iterator_init(iter, devargs), \
> > + id = rte_eth_iterator_next(iter); \
> > + id != RTE_MAX_ETHPORTS; \
> > + id = rte_eth_iterator_next(iter))
> > +
>
> Such iterators are very convenient, but in this particular case
> it is a source of non-obvious memory leaks and necessity
> of the hack to discard 'const'.
>
> May be iterator free callback with its own opaque data
> can help to avoid these hacks with const discard?
> I.e. rte_eth_iterator_free() which does the job and mentioned
> in the rte_eth_iterator_init() and the macro description.
Yes, definitely, I will add rte_eth_iterator_free().
Thanks for the very good review!
More information about the dev
mailing list