[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

 


Rackspace

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