[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 16/25] argo: implement the notify op



On Thu, Dec 13, 2018 at 6:06 AM Jan Beulich <JBeulich@xxxxxxxx> wrote:
>
> >>> On 01.12.18 at 02:32, <christopher.w.clark@xxxxxxxxx> wrote:
> > +static uint32_t
> > +argo_ringbuf_payload_space(struct domain *d, struct argo_ring_info 
> > *ring_info)
> > +{
> > +    argo_ring_t ring;
> > +    int32_t ret;
> > +
> > +    ASSERT(spin_is_locked(&ring_info->lock));
> > +
> > +    ring.len = ring_info->len;
> > +    if ( !ring.len )
> > +        return 0;
> > +
> > +    ring.tx_ptr = ring_info->tx_ptr;
> > +
> > +    if ( argo_ringbuf_get_rx_ptr(ring_info, &ring.rx_ptr) )
> > +        return 0;
> > +
> > +    argo_dprintk("argo_ringbuf_payload_space: tx_ptr=%d rx_ptr=%d\n",
> > +                 ring.tx_ptr, ring.rx_ptr);
> > +
> > +    if ( ring.rx_ptr == ring.tx_ptr )
> > +        return ring.len - sizeof(struct argo_ring_message_header);
> > +
> > +    ret = ring.rx_ptr - ring.tx_ptr;
> > +    if ( ret < 0 )
> > +        ret += ring.len;
>
> Seeing these two if()-s - how is an empty ring distinguished from
> a completely full one? I'm getting the impression that
> ring.rx_ptr == ring.tx_ptr in both cases.

The subtraction from ring.len above is missing an additional subtraction of
ARGO_ROUNDUP(1), which doesn't help reasoning about this. (Fixed in v2.)

If rx_ptr == tx_ptr, then the ring is empty. The ring insertion
functions won't allow filling the ring, and I've added more comments
in the v2 code to explain.

> > +    ret -= sizeof(struct argo_ring_message_header);
> > +    ret -= ARGO_ROUNDUP(1);
>
> Wouldn't you instead better round ret to a suitable multiple of
> whatever granularity you try to arrange for here? Otherwise
> what is this extra subtraction supposed to do?

re: subtraction, have added new comment:
/*
 * The maximum size payload for a message that will be accepted is:
 * (the available space between the ring indexes)
 *    minus (space for a message header)
 *    minus (space for one message slot)
 * since argo_ringbuf_insert requires that one message slot be left
 * unfilled, to avoid filling the ring to capacity and confusing a full
 * ring with an empty one.
 */

re: rounding: Possibly. Not sure. In practice, both sides are
updating the indexes in quantized steps matching the
ARGO_ROUNDUP unit. Not sure it needs to change.

>
> > @@ -627,6 +679,43 @@ argo_pending_remove_all(struct argo_ring_info 
> > *ring_info)
> >      }
> >  }
> >
> > +static void
> > +argo_pending_notify(struct hlist_head *to_notify)
> > +{
> > +    struct hlist_node *node, *next;
> > +    struct argo_pending_ent *pending_ent;
> > +
> > +    ASSERT(rw_is_locked(&argo_lock));
> > +
> > +    hlist_for_each_entry_safe(pending_ent, node, next, to_notify, node)
> > +    {
> > +        hlist_del(&pending_ent->node);
> > +        argo_signal_domid(pending_ent->id);
> > +        xfree(pending_ent);
> > +    }
> > +}
> > +
> > +static void
> > +argo_pending_find(const struct domain *d, struct argo_ring_info *ring_info,
> > +                  uint32_t payload_space, struct hlist_head *to_notify)
> > +{
> > +    struct hlist_node *node, *next;
> > +    struct argo_pending_ent *ent;
> > +
> > +    ASSERT(rw_is_locked(&d->argo->lock));
> > +
> > +    spin_lock(&ring_info->lock);
> > +    hlist_for_each_entry_safe(ent, node, next, &ring_info->pending, node)
> > +    {
> > +        if ( payload_space >= ent->len )
> > +        {
> > +            hlist_del(&ent->node);
> > +            hlist_add_head(&ent->node, to_notify);
> > +        }
> > +    }
>
> So if there's space available to fit e.g. just the first pending entry,
> you'd continue the loop and also signal all others, provided their
> lengths aren't too big? What good does producing such a burst of
> notifications do, when only one of the interested parties is
> actually going to be able to put something on the ring?

Added new comment:
/*
 * TODO: Current policy here is to signal _all_ of the waiting domains
 *       interested in sending a message of size less than payload_space.
 *
 * This is likely to be suboptimal, since once one of them has added
 * their message to the ring, there may well be insufficient room
 * available for any of the others to transmit, meaning that they were
 * woken in vain, which created extra work just to requeue their wait.
 *
 * Retain this simple policy for now since it at least avoids starving a
 * domain of available space notifications because of a policy that only
 * notified other domains instead. Improvement may be possible;
 * investigation required.
 */

> > +typedef struct argo_ring_data
> > +{
> > +    uint64_t magic;
>
> What is this good for?

New comment added:
/*
 * Contents of the 'magic' field are inspected to verify that they contain
 * an expected value before the hypervisor will perform writes into this
 * structure in guest-supplied memory.
 */

>
> > @@ -179,6 +214,33 @@ struct argo_ring_message_header
> >   */
> >  #define ARGO_MESSAGE_OP_sendv               5
> >
> > +/*
> > + * ARGO_MESSAGE_OP_notify
> > + *
> > + * Asks Xen for information about other rings in the system.
> > + *
> > + * ent->ring is the argo_addr_t of the ring you want information on.
> > + * Uses the same ring matching rules as ARGO_MESSAGE_OP_sendv.
> > + *
> > + * ent->space_required : if this field is not null then Xen will check
> > + * that there is space in the destination ring for this many bytes of  
> > payload.
> > + * If sufficient space is available, it will set 
> > ARGO_RING_DATA_F_SUFFICIENT
> > + * and CANCEL any pending notification for that ent->ring; otherwise it
> > + * will schedule a notification event and the flag will not be set.
> > + *
> > + * These flags are set by Xen when notify replies:
> > + * ARGO_RING_DATA_F_EMPTY       ring is empty
> > + * ARGO_RING_DATA_F_PENDING     notify event is pending - * don't rely on 
> > this *
> > + * ARGO_RING_DATA_F_SUFFICIENT  sufficient space for space_required is 
> > there
> > + * ARGO_RING_DATA_F_EXISTS      ring exists
> > + *
> > + * arg1: XEN_GUEST_HANDLE(argo_ring_data_t) ring_data (may be NULL)
> > + * arg2: NULL
> > + * arg3: 0 (ZERO)
> > + * arg4: 0 (ZERO)
>
> Another observation I probably should have made earlier: You
> don't check that the NULL/ZERO specified argument are indeed
> so. Just like for padding fields, please do.

ack, thanks.

Christopher

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.