|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] ring.h: introduce macros to handle monodirectional rings with multiple req sizes
>>> On 17.02.17 at 23:38, <sstabellini@xxxxxxxxxx> wrote:
For all of the comments below, please understand that I'm giving
them in the understanding that pre-existing code may be similarly
problematic; we shouldn't introduce new issues though.
> --- a/xen/include/public/io/ring.h
> +++ b/xen/include/public/io/ring.h
> @@ -313,6 +313,128 @@ typedef struct __name##_back_ring __name##_back_ring_t
> (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
> } while (0)
>
> +
> +/*
> + * DEFINE_XEN_FLEX_RING defines two monodirectional rings and functions
> + * to check if there is data on the ring, and to read and write to them.
> + *
> + * XEN_FLEX_RING_SIZE
> + * Convenience macro to calculate the size of one of the two rings
> + * from the overall order.
> + *
> + * $NAME_mask
> + * Function to apply the size mask to an index, to reduce the index
> + * within the range [0-size].
> + *
> + * $NAME_read_packet
> + * Function to read a defined amount of data from the ring. The amount
> + * of data read is sizeof(__packet_t).
> + *
> + * $NAME_write_packet
> + * Function to write a defined amount of data to the ring. The amount
> + * of data to write is sizeof(__packet_t).
> + *
> + * $NAME_data_intf
> + * Indexes page, shared between frontend and backend. It also
> + * contains the array of grant refs. Different protocols can have
> + * extensions to the basic format, in such cases please define your
> + * own data_intf struct.
> + *
> + * $NAME_queued
> + * Function to calculate how many bytes are currently on the ring,
> + * read to be read. It can also be used to calculate how much free
ready to be ...
> + * space is currently on the ring (ring_size - $NAME_queued()).
> + */
> +#define XEN_FLEX_RING_SIZE(__order)
> \
> + ((1 << ((__order) + XEN_PAGE_SHIFT)) / 2)
Double-underscore prefixed names are reserved. Please avoid using
leading underscores namely in public headers.
Also, while likely not relevant for the near future, may I suggest to
use 1UL here, or even (size_t)1 (to also cope with P64 environments)?
Further, with PAGE_SHIFT never zero, I think the expression would
better be
(1UL << ((__order) + XEN_PAGE_SHIFT - 1))
> +#define DEFINE_XEN_FLEX_RING(__name, __packet_t)
> \
> +
> \
> +static inline RING_IDX __name##_mask(RING_IDX idx, RING_IDX ring_size)
> \
> +{
> \
> + return ((idx) & (ring_size - 1));
> \
In an inline function you don't need to parenthesize parameter
name uses. But the use of inline functions here is questionable
in the first place - so far there are none, as they're not standard
C89. Granted they are being used in a macro only, so won't cause
immediate issues for code not using the macros, but anyway.
> +static inline void __name##_read_packet(char *buf,
> \
const
> + RING_IDX *masked_prod, RING_IDX *masked_cons,
> \
You don't update *masked_prod - why do you need a pointer here?
> + RING_IDX ring_size, __packet_t *h) {
> \
> + if (*masked_cons < *masked_prod) {
> \
> + memcpy(h, buf + *masked_cons, sizeof(*h));
> \
> + } else {
> \
> + if (sizeof(*h) > ring_size - *masked_cons) {
> \
> + memcpy(h, buf + *masked_cons, ring_size - *masked_cons);
> \
> + memcpy((char *)h + ring_size - *masked_cons, buf,
> \
> + sizeof(*h) - (ring_size - *masked_cons));
> \
> + } else {
> \
> + memcpy(h, buf + *masked_cons, sizeof(*h));
> \
This is the same as the first memcpy(). Care to adjust (merge) the
conditionals so you need this only once?
> +static inline void __name##_write_packet(char *buf,
> \
> + RING_IDX *masked_prod, RING_IDX *masked_cons,
> \
> + RING_IDX ring_size, __packet_t h) {
> \
Passing a (possibly large) structure by value? Apart from that similar
comments as for read apply here.
> +struct __name##_data {
> \
> + char *in; /* half of the allocation */
> \
> + char *out; /* half of the allocation */
> \
Why plain char? Void would seem the most neutral option here, but
if arithmetic needs doing inside the header, then unsigned char may
need to be used.
> +struct __name##_data_intf {
> \
> + RING_IDX in_cons, in_prod;
> \
> +
> \
> + uint8_t pad1[56];
> \
> +
> \
> + RING_IDX out_cons, out_prod;
> \
> +
> \
> + uint8_t pad2[56];
> \
> +
> \
> + RING_IDX ring_order;
> \
> + grant_ref_t ref[];
> \
> +};
> \
Above you talk about the option of defining private _data_intf
structures. How is that supposed to work when you define a
suitably named structure already here? Other than #define-s
one can't undo such a type definition.
> +static inline RING_IDX __name##_queued(RING_IDX prod,
> \
> + RING_IDX cons, RING_IDX ring_size)
> \
> +{
> \
> + RING_IDX size;
> \
> +
> \
> + if (prod == cons)
> \
> + return 0;
> \
> +
> \
> + prod = __name##_mask(prod, ring_size);
> \
> + cons = __name##_mask(cons, ring_size);
> \
> +
> \
> + if (prod == cons)
> \
> + return ring_size;
> \
> +
> \
> + if (prod > cons)
> \
> + size = prod - cons;
> \
> + else {
> \
> + size = ring_size - cons;
> \
> + size += prod;
> \
> + }
To me this would read easier (due to matching up better with the
if() path) as
else
size = ring_size - (cons - prod);
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |