On Wed, 8 Mar 2017, Boris Ostrovsky wrote:
> On 03/08/2017 02:33 PM, Stefano Stabellini wrote:
> > On Wed, 8 Mar 2017, Boris Ostrovsky wrote:
> >>>>> +}
> >>>>> +
> >>>>> +static int p9_xen_write_todo(struct xen_9pfs_dataring *ring, RING_IDX 
> >>>>> size)
> >>>>> +{
> >>>>> +       RING_IDX cons, prod;
> >>>>> +
> >>>>> +       cons = ring->intf->out_cons;
> >>>>> +       prod = ring->intf->out_prod;
> >>>>> +       mb();
> >>>>> +
> >>>>> +       if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons, 
> >>>>> XEN_9PFS_RING_SIZE) >= size)
> >>>>> +               return 1;
> >>>>> +       else
> >>>>> +               return 0;
> >>>>>  }
> >>>>>  
> >>>>>  static int p9_xen_request(struct p9_client *client, struct p9_req_t 
> >>>>> *p9_req)
> >>>>>  {
> >>>>> +       struct xen_9pfs_front_priv *priv = NULL;
> >>>>> +       RING_IDX cons, prod, masked_cons, masked_prod;
> >>>>> +       unsigned long flags;
> >>>>> +       uint32_t size = p9_req->tc->size;
> >>>>> +       struct xen_9pfs_dataring *ring;
> >>>>> +       int num;
> >>>>> +
> >>>>> +       list_for_each_entry(priv, &xen_9pfs_devs, list) {
> >>>>> +               if (priv->client == client)
> >>>>> +                       break;
> >>>>> +       }
> >>>>> +       if (priv == NULL || priv->client != client)
> >>>>> +               return -EINVAL;
> >>>>> +
> >>>>> +       num = p9_req->tc->tag % priv->num_rings;
> >>>>> +       ring = &priv->rings[num];
> >>>>> +
> >>>>> +again:
> >>>>> +       while (wait_event_interruptible(ring->wq,
> >>>>> +                               p9_xen_write_todo(ring, size) > 0) != 
> >>>>> 0);
> >>>>> +
> >>>>> +       spin_lock_irqsave(&ring->lock, flags);
> >>>>> +       cons = ring->intf->out_cons;
> >>>>> +       prod = ring->intf->out_prod;
> >>>>> +       mb();
> >>>>> +
> >>>>> +       if (XEN_9PFS_RING_SIZE - xen_9pfs_queued(prod, cons, 
> >>>>> XEN_9PFS_RING_SIZE) < size) {
> >>>> This looks like p9_xen_write_todo().
> >>> p9_xen_write_todo is just a wrapper around xen_9pfs_queued to provide
> >>> a return value that works well with wait_event_interruptible.
> >>>
> >>> I would prefer not to call p9_xen_write_todo here, because it's simpler
> >>> if we don't read prod and cons twice.
> >> I was referring to the whole code fragment after spin_lock_irqsave(),
> >> not just the last line. Isn't it exactly !p9_xen_write_todo()?
> > Yes, it is true they are almost the same. The difference, and the reason
> > for p9_xen_write_todo to exist, is that p9_xen_write_todo is called in
> > the wait_event_interruptible loop, as such it needs to read prod and
> > cons every time. On the other end, here we want to read them once. Does
> > it make sense?
> 
> 
> I am clearly being particularly dense here but what I was thinking was:
> 
> again:
>       while (wait_event_interruptible(ring->wq,
>                               p9_xen_write_todo(ring, size) > 0) != 0);
> 
>       spin_lock_irqsave(&ring->lock, flags);
>       if (!p9_xen_write_todo(ring, size)) {
>               spin_unlock_irqrestore(&ring->lock, flags);
>               goto again;
>       }
> 
> There is no extra read of prod/cons.

Yes, there are: just after this if statement we would have to read them
again to calculate masked_prod and masked_cons.

Reply via email to