[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 16/25] argo: implement the notify op
>>> 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. > + 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? > @@ -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? > @@ -705,6 +812,107 @@ argo_ring_remove_info(struct domain *d, struct > argo_ring_info *ring_info) > xfree(ring_info); > } > > +/*ring data*/ Now this comment is malformed in any event. > +static int > +argo_fill_ring_data(struct domain *src_d, const? > +static long > +argo_notify(struct domain *d, > + XEN_GUEST_HANDLE_PARAM(argo_ring_data_t) ring_data_hnd) > +{ > + argo_ring_data_t ring_data; > + int ret = 0; > + > + read_lock(&argo_lock); > + > + if ( !d->argo ) > + { > + read_unlock(&argo_lock); > + argo_dprintk("!d->argo, ENODEV\n"); > + return -ENODEV; > + } > + > + argo_notify_check_pending(d); > + > + do { > + if ( !guest_handle_is_null(ring_data_hnd) ) > + { > + /* Quick sanity check on ring_data_hnd */ > + ret = copy_field_from_guest_errno(&ring_data, ring_data_hnd, > magic); > + if ( ret ) > + break; > + > + if ( ring_data.magic != ARGO_RING_DATA_MAGIC ) > + { > + argo_dprintk( > + "ring.magic(%"PRIx64") != ARGO_RING_MAGIC(%llx), > EINVAL\n", > + ring_data.magic, ARGO_RING_MAGIC); > + ret = -EINVAL; > + break; > + } > + > + ret = copy_from_guest_errno(&ring_data, ring_data_hnd, 1); > + if ( ret ) > + break; > + > + { > + /* > + * This is a guest pointer passed as a field in a struct > + * so XEN_GUEST_HANDLE is used. > + */ > + XEN_GUEST_HANDLE(argo_ring_data_ent_t) ring_data_ent_hnd; > + ring_data_ent_hnd = guest_handle_for_field(ring_data_hnd, > + > argo_ring_data_ent_t, > + data[0]); > + ret = argo_fill_ring_data_array(d, ring_data.nent, > + ring_data_ent_hnd); > + } Stray braces and bogus indentation: The declaration can move up and then you don't need the braces and the extra level of indentation. > @@ -103,6 +104,40 @@ typedef struct argo_ring > */ > #define ARGO_ROUNDUP(a) (((a) + 0xf) & ~(typeof(a))0xf) > > +/* > + * Notify flags > + */ > +/* Ring is empty */ > +#define ARGO_RING_DATA_F_EMPTY (1U << 0) > +/* Ring exists */ > +#define ARGO_RING_DATA_F_EXISTS (1U << 1) > +/* Pending interrupt exists. Do not rely on this field - for profiling only > */ > +#define ARGO_RING_DATA_F_PENDING (1U << 2) > +/* Sufficient space to queue space_required bytes exists */ > +#define ARGO_RING_DATA_F_SUFFICIENT (1U << 3) > + > +typedef struct argo_ring_data_ent > +{ > + argo_addr_t ring; > + uint16_t flags; > + uint16_t pad; > + uint32_t space_required; > + uint32_t max_message_size; > +} argo_ring_data_ent_t; > + > +typedef struct argo_ring_data > +{ > + uint64_t magic; What is this good for? > @@ -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. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |