On Wed, Oct 18, 2017 at 09:48:04PM +0000, Carrillo, Erik G wrote:
>
>
> > -----Original Message-----
> > From: Pavan Nikhilesh Bhagavatula
> > [mailto:pbhagavat...@caviumnetworks.com]
> > Sent: Monday, October 16, 2017 7:37 AM
> > To: Carrillo, Erik G <erik.g.carri...@intel.com>
> > Cc: dev@dpdk.org
> > Subject: Re: [RFC PATCH v2 0/1] eventtimer: introduce event timer adapter
> >
> > On Mon, Oct 16, 2017 at 05:34:36PM +0530, Pavan Nikhilesh Bhagavatula
> > wrote:
> > > On Mon, Oct 09, 2017 at 08:30:35PM +0000, Carrillo, Erik G wrote:
> > > > > >
> > > > > > The second big change is to replace API parameters specifying
> > > > > > pointer to rte_event_timer_adapter with ids, which seems more
> > > > > > common throughout DPDK.
> > > > > >
> > > > > > Other changes include:
> > > > > >  - removed rte_event_timer_adapter_lookup() function, since APIs
> > > > > > no
> > > > > longer
> > > > > >    accept pointer to rte_event_timer_adapter
> > > > >
> > > > > There is one difference between ethdev rx adapter, where we have
> > > > > rte_event_timer_arm_burst(),
> > rte_event_timer_arm_tmo_tick_burst(),
> > > > > rte_event_timer_cancel_burst(),
> > > > > APIs in fastpath. So any multi process scheme where resolving the
> > > > > fastpath API functions in _one_ or zero redirection is fine.
> > > >
> > > > I see, makes sense.
> > > >
> > > > >
> > > > > I guess in we may need 2 or 3 indirection to resolve the fastpath
> > > > > functions with id scheme. Please choose scheme with one 1 or no
> > redirection.
> > > > > I think,
> > > > > - By allocating adapter memory from the heap and
> > > >
> > > > Just to check, are you talking about the heap (e.g., rte_malloc) in
> > hugepage memory?
> > >
> > > Yes, If we use rte_memzone_reserve and create the adapter in the
> > > primary process, the name can be used to do a lookup in the secondary.
> > > >
> > > > > - adapter hold the function pointers for multi process and
> > > > > - mempool kind of pointer object scheme without id and lookup()
> > > > > Can resolve function pointers without any indirection.
> > > > >
> > > >
> > > > Can you elaborate here?  In the mempool implementation, it looks like
> > there's a per-process array of ops objects, and each mempool instance has
> > an index into the array that it uses to select the ops object to call 
> > through.
> > Since the ops structures are initialized per-process, they get function
> > pointers valid in that process - which relates to the second point above. 
> > If the
> > adapter holds function pointers for a primary process (for example), they'll
> > be invalid in the secondary.  Am I missing something?
> > > >
> > >
> > > Once adapter is created using memzone in the Primary process, the
> > > secondary process can use the memzone name to get the pointer to the
> > > adapter and use data such as ops_id stored in the memzone to fixup the
> > fastpath function pointers.
> > > The slowpath could still use ops_id based function pointers(mempool).
> > >
> > > > Thanks,
> > > > Gabriel
> > > >
> > > > > So please analyze on those lines as well.
> > > > >
> > > > >
> > > >
> > >
> > > Pavan
> >
> > Adding to this
> >
> > Have a two level scheme such as:
> >
> > --Allocate this structure from a global array based on the adapter ID:
> >
> > struct rte_event_timer_wheel {
> >     event_timer_arm_burst arm_burst;
> >     /**< Pointer to driver arm_burst function. */
> >     event_timer_arm_tmo_tick_burst arm_tmo_tick_burst;
> >     /**< Pointer to driver arm_tmo_tick_burst function. */
> >     event_timer_cancel_burst cancel_burst;
> >     /**< Pointer to driver cancel function. */
> >
> > --Allocate the data section using memzone reserve.
> >     struct rte_event_timer_wheel_data *data;
> >
> >
> >     /**< Pointer to timer wheel data*/
> >     struct rte_event_timer_wheel_ops *ops;
> >     /**< Driver specific ops */
> > } __rte_cache_aligned;
> >
> > /**
> >  * Timer wheel data structure.
> >  */
> > struct rte_event_timer_wheel_data {
> >     void *wheel_priv;
> >     /**< Timer wheel private data*/
> >     uint8_t ops_index;
> >     /**< Timer wheel ops index id. */
> >     uint8_t wheel_id;
> >     /**< Timer wheel id. */
> >     uint8_t event_port_id;
> >     /**< Optional Event port used when the inbuilt port is absent.*/
> >     const struct rte_memzone *mz;
> >     /**< Timer wheel memzone pointer. */
> >     struct rte_event_timer_wheel_config conf;
> >     /**< Configuration used to configure the wheel. */
> >
> >     RTE_STD_C11
> >     uint8_t started : 1;
> >     /**< Flag to indicate wheel started. */ } __rte_cache_aligned;
> >
> > /* Primary process */
> > *_create(wheel_id, ...)
> > {
> >     struct rte_event_timer_wheel *wl;
> >
> >     /* do checks */
> >     ...
> >
> >     wl = &rte_event_timer_wheels[wheel_id];
> >
> >     ...
> >     /* Get ops ID based on eventdev */
> >     ...
> >     ret = rte_event_dev_get_timer_wheel_capability(event_dev_id,
> > &flags,
> >             &ops_id);
> >
> >     mz = rte_memzone_reserve(name, ...);
> >     ...
> >     /* fill in data */
> >     data = mz->addr;
> >     ...
> >
> >     data = ops_id;
> >     ...
> >     /* Call the driver specific functions. */ }
> >
> > /*Secondaty process*/
> > struct rte_event_timer_wheel *
> > rte_event_timer_wheel_lookup(uint16_t wheel_id) {
> >     ...
> >     struct rte_event_timer_wheel *wl;
> >     struct rte_event_timer_wheel_data *data;
> >     ...
> >
> >     /* Do checks*/
> >     ...
> >     /* Look up memzone created in primary. */
> >     mz = rte_memzone_lookup(name);
> >
> >     data = mz->addr;
> >
> >     /* Setup up global array in secondary */
> >     wl = &rte_event_timer_wheels[data->wheel_id];
> >     wl->data = data;
> >     ...
> >     /* Use the ops_id set in primary to get the ops in secondary*/
> >     wl->ops = rte_event_timer_wheel_get_ops(data->ops_index);
> >
> >     /* Reset the ops*/
> >     (*wl->ops->set_ops)(wl);
> >
> >     return wl;
> > }
> >
> > Hope this clears few things up.
>
> Hi Pavan,
>
> OK, I think I see what you mean.  We could have a global table of ops structs 
> (one per plugin), where each entry contained function pointers valid in that 
> process.  We could save the ops_index in the shared data portion of the timer 
> wheel, and in create() or lookup(), we could use that index to retrieve the 
> ops struct, which could contain an operation to set the fastpath pointers for 
> the timer wheel instance.  I assume the *lookup()  function would rely on the 
> memzone having a predictable name (e.g. "timer_wheel_memzone_<id>")  so that 
> it could locate it knowing only the wheel_id.

Ack

>
> Thanks for the info,
> Gabriel

Cheers,
Pavan
>

Reply via email to