[v5,05/39] ring: use C11 alignas
Checks
Commit Message
The current location used for __rte_aligned(a) for alignment of types
and variables is not compatible with MSVC. There is only a single
location accepted by both toolchains.
For variables standard C11 offers alignas(a) supported by conformant
compilers i.e. both MSVC and GCC.
For types the standard offers no alignment facility that compatibly
interoperates with C and C++ but may be achieved by relocating the
placement of __rte_aligned(a) to the aforementioned location accepted
by all currently supported toolchains.
To allow alignment for both compilers do the following:
* Move __rte_aligned from the end of {struct,union} definitions to
be between {struct,union} and tag.
The placement between {struct,union} and the tag allows the desired
alignment to be imparted on the type regardless of the toolchain being
used for all of GCC, LLVM, MSVC compilers building both C and C++.
* Replace use of __rte_aligned(a) on variables/fields with alignas(a).
Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
---
lib/ring/rte_ring_core.h | 16 +++++++++-------
lib/ring/rte_ring_peek_zc.h | 4 ++--
2 files changed, 11 insertions(+), 9 deletions(-)
Comments
>
> The current location used for __rte_aligned(a) for alignment of types
> and variables is not compatible with MSVC. There is only a single
> location accepted by both toolchains.
>
> For variables standard C11 offers alignas(a) supported by conformant
> compilers i.e. both MSVC and GCC.
>
> For types the standard offers no alignment facility that compatibly
> interoperates with C and C++ but may be achieved by relocating the
> placement of __rte_aligned(a) to the aforementioned location accepted
> by all currently supported toolchains.
>
> To allow alignment for both compilers do the following:
>
> * Move __rte_aligned from the end of {struct,union} definitions to
> be between {struct,union} and tag.
>
> The placement between {struct,union} and the tag allows the desired
> alignment to be imparted on the type regardless of the toolchain being
> used for all of GCC, LLVM, MSVC compilers building both C and C++.
>
> * Replace use of __rte_aligned(a) on variables/fields with alignas(a).
>
> Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> Acked-by: Morten Brørup <mb@smartsharesystems.com>
> ---
> lib/ring/rte_ring_core.h | 16 +++++++++-------
> lib/ring/rte_ring_peek_zc.h | 4 ++--
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/lib/ring/rte_ring_core.h b/lib/ring/rte_ring_core.h
> index b770873..497d535 100644
> --- a/lib/ring/rte_ring_core.h
> +++ b/lib/ring/rte_ring_core.h
> @@ -19,6 +19,8 @@
> * instead.
> */
>
> +#include <stdalign.h>
> +
> #ifdef __cplusplus
> extern "C" {
> #endif
> @@ -78,7 +80,7 @@ struct rte_ring_headtail {
>
> union __rte_ring_rts_poscnt {
> /** raw 8B value to read/write *cnt* and *pos* as one atomic op */
> - RTE_ATOMIC(uint64_t) raw __rte_aligned(8);
> + alignas(8) RTE_ATOMIC(uint64_t) raw;
One small question - here and below, would it possible to do 'alignas(sizeof(uint64_t))' instead of 'alignas(8)?
Or MSVC has some restrictions here?
> struct {
> uint32_t cnt; /**< head/tail reference counter */
> uint32_t pos; /**< head/tail position */
> @@ -94,7 +96,7 @@ struct rte_ring_rts_headtail {
>
On Mon, Feb 26, 2024 at 01:23:35PM +0000, Konstantin Ananyev wrote:
>
>
> >
> > The current location used for __rte_aligned(a) for alignment of types
> > and variables is not compatible with MSVC. There is only a single
> > location accepted by both toolchains.
> >
> > For variables standard C11 offers alignas(a) supported by conformant
> > compilers i.e. both MSVC and GCC.
> >
> > For types the standard offers no alignment facility that compatibly
> > interoperates with C and C++ but may be achieved by relocating the
> > placement of __rte_aligned(a) to the aforementioned location accepted
> > by all currently supported toolchains.
> >
> > To allow alignment for both compilers do the following:
> >
> > * Move __rte_aligned from the end of {struct,union} definitions to
> > be between {struct,union} and tag.
> >
> > The placement between {struct,union} and the tag allows the desired
> > alignment to be imparted on the type regardless of the toolchain being
> > used for all of GCC, LLVM, MSVC compilers building both C and C++.
> >
> > * Replace use of __rte_aligned(a) on variables/fields with alignas(a).
> >
> > Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
> > Acked-by: Morten Brørup <mb@smartsharesystems.com>
> > ---
> > lib/ring/rte_ring_core.h | 16 +++++++++-------
> > lib/ring/rte_ring_peek_zc.h | 4 ++--
> > 2 files changed, 11 insertions(+), 9 deletions(-)
> >
> > diff --git a/lib/ring/rte_ring_core.h b/lib/ring/rte_ring_core.h
> > index b770873..497d535 100644
> > --- a/lib/ring/rte_ring_core.h
> > +++ b/lib/ring/rte_ring_core.h
> > @@ -19,6 +19,8 @@
> > * instead.
> > */
> >
> > +#include <stdalign.h>
> > +
> > #ifdef __cplusplus
> > extern "C" {
> > #endif
> > @@ -78,7 +80,7 @@ struct rte_ring_headtail {
> >
> > union __rte_ring_rts_poscnt {
> > /** raw 8B value to read/write *cnt* and *pos* as one atomic op */
> > - RTE_ATOMIC(uint64_t) raw __rte_aligned(8);
> > + alignas(8) RTE_ATOMIC(uint64_t) raw;
>
> One small question - here and below, would it possible to do 'alignas(sizeof(uint64_t))' instead of 'alignas(8)?
> Or MSVC has some restrictions here?
it should be okay to use a constant expression with alignas(n) even with
MSVC because it is conformant, if it isn't it would be a bug. it is one benefit
over using __declspec(align(a)).
i'll update the series to use sizeof.
>
>
> > struct {
> > uint32_t cnt; /**< head/tail reference counter */
> > uint32_t pos; /**< head/tail position */
> > @@ -94,7 +96,7 @@ struct rte_ring_rts_headtail {
> >
@@ -19,6 +19,8 @@
* instead.
*/
+#include <stdalign.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -78,7 +80,7 @@ struct rte_ring_headtail {
union __rte_ring_rts_poscnt {
/** raw 8B value to read/write *cnt* and *pos* as one atomic op */
- RTE_ATOMIC(uint64_t) raw __rte_aligned(8);
+ alignas(8) RTE_ATOMIC(uint64_t) raw;
struct {
uint32_t cnt; /**< head/tail reference counter */
uint32_t pos; /**< head/tail position */
@@ -94,7 +96,7 @@ struct rte_ring_rts_headtail {
union __rte_ring_hts_pos {
/** raw 8B value to read/write *head* and *tail* as one atomic op */
- RTE_ATOMIC(uint64_t) raw __rte_aligned(8);
+ alignas(8) RTE_ATOMIC(uint64_t) raw;
struct {
RTE_ATOMIC(uint32_t) head; /**< head position */
RTE_ATOMIC(uint32_t) tail; /**< tail position */
@@ -117,7 +119,7 @@ struct rte_ring_hts_headtail {
* a problem.
*/
struct rte_ring {
- char name[RTE_RING_NAMESIZE] __rte_cache_aligned;
+ alignas(RTE_CACHE_LINE_SIZE) char name[RTE_RING_NAMESIZE];
/**< Name of the ring. */
int flags; /**< Flags supplied at creation. */
const struct rte_memzone *memzone;
@@ -129,20 +131,20 @@ struct rte_ring {
RTE_CACHE_GUARD;
/** Ring producer status. */
- union {
+ union __rte_cache_aligned {
struct rte_ring_headtail prod;
struct rte_ring_hts_headtail hts_prod;
struct rte_ring_rts_headtail rts_prod;
- } __rte_cache_aligned;
+ };
RTE_CACHE_GUARD;
/** Ring consumer status. */
- union {
+ union __rte_cache_aligned {
struct rte_ring_headtail cons;
struct rte_ring_hts_headtail hts_cons;
struct rte_ring_rts_headtail rts_cons;
- } __rte_cache_aligned;
+ };
RTE_CACHE_GUARD;
};
@@ -79,7 +79,7 @@
* This structure contains the pointers and length of the space
* reserved on the ring storage.
*/
-struct rte_ring_zc_data {
+struct __rte_cache_aligned rte_ring_zc_data {
/* Pointer to the first space in the ring */
void *ptr1;
/* Pointer to the second space in the ring if there is wrap-around.
@@ -92,7 +92,7 @@ struct rte_ring_zc_data {
* will give the number of elements available at ptr2.
*/
unsigned int n1;
-} __rte_cache_aligned;
+};
static __rte_always_inline void
__rte_ring_get_elem_addr(struct rte_ring *r, uint32_t head,