msvc integration changes
cover msvc integration changes
In accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Tyler Retzlaff (9):
eal: use rdtsc intrinsic when compiling with msvc
eal: use rtm and xtest intrinsics when compiling with msvc
eal: use barrier intrinsics when compiling with msvc
eal: typedef cpu flag enum as int for msvc
eal: hide GCC extension based alignment markers
eal: expand most macros to empty when using msvc
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: disable json print formatting with msvc
telemetry: avoid expanding versioned symbol macros on msvc
lib/eal/include/generic/rte_atomic.h | 11 ++++++++++ lib/eal/include/generic/rte_cpuflags.h | 12 ++++++----- lib/eal/include/rte_branch_prediction.h | 8 +++++++ lib/eal/include/rte_common.h | 37 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++ lib/eal/x86/include/rte_atomic.h | 14 ++++++++++++- lib/eal/x86/include/rte_cycles.h | 8 +++++++ lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++ lib/telemetry/telemetry_data.c | 16 ++++++++++++++ lib/telemetry/telemetry_json.h | 6 ++++++ 10 files changed, 145 insertions(+), 6 deletions(-)
Signature · 1 line
1.8.3.1
PATCH 1/9 eal: use rdtsc intrinsic when compiling with msvc
Inline assembly is not supported for msvc x64 instead use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 8 ++++++++ 1 file changed, 8 insertions(+)
lib/eal/x86/include/rte_cycles.h +8 -0
@@ -6,6 +6,10 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifdef RTE_TOOLCHAIN_MSVC +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +27,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifndef RTE_TOOLCHAIN_MSVC union { uint64_t tsc_64; RTE_STD_C11
@@ -47,6 +52,9 @@"=a" (tsc.lo_32), "=d" (tsc.hi_32));return tsc.tsc_64; +#else +return __rdtsc (); +#endif } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH 2/9 eal: use rtm and xtest intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _xbegin, _xend, _xabort and _xtest intrinsics.
--- lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
lib/eal/x86/include/rte_rtm.h +19 -0
@@ -5,6 +5,9 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#ifdef RTE_TOOLCHAIN_MSVC +#include <immintrin.h> +#endif /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +31,47 @@static __rte_always_inline unsigned int rte_xbegin(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned int ret =RTE_XBEGIN_STARTED ; asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" );return ret; +#else +return _xbegin (); +#endif }static __rte_always_inline void rte_xend(void) { +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +#else +_xend (); +#endif }/* not an inline function to workaround a clang bug with -O0 */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_xabort (status) do { \ asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ } while (0) +#else +#define rte_xabort (status) _xabort(status) +#endif static __rte_always_inline int rte_xtest(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned char out; asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" :"=r" (out) ::"memory" );return out; +#else +return _xtest (); +#endif }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH 3/9 eal: use barrier intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +9 -1
@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3;
@@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 14 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +0
-0
lib/eal/include/generic/rte_atomic.h line 124
Quoted 9 lines
lib/eal/include/generic/rte_atomic.h +3
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier()
Does this actually add a full memory barrier? If so, that's really not what we want, and will slow things down.
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 19 lines · Bruce Richardson
Quoted 18 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +1
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC
Quoted 8 lines
lib/eal/include/generic/rte_atomic.h line 124
Quoted 5 lines
lib/eal/include/generic/rte_atomic.h +2
-0#define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier()Does this actually add a full memory barrier? If so, that's really not what we want, and will slow things down.
for background MSVC when targeting amd64/arm64 do not permit inline assmebly. The main reason is inline assembly can't be optimized. instead it provides intrinsics (that are known) that can participate in optimization.
specific answer to your question. yes, it implements only a "compiler barrier" not a full memory barrier preventing processor reordering.
https://learn.microsoft.com/en-us/cpp/intrinsics/readwritebarrier?view=msvc-170
"Limits the compiler optimizations that can reorder memory accesses
across the point of the call."
note: ignore the caution on the documentation it only applies to C++
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 34 lines · Tyler Retzlaff
Quoted 19 lines · Bruce Richardson
Quoted 18 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +1
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC Quoted 8 lines
lib/eal/include/generic/rte_atomic.h line 124
Quoted 5 lines
lib/eal/include/generic/rte_atomic.h +2
-0#define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier()Does this actually add a full memory barrier? If so, that's really not what we want, and will slow things down.
for background MSVC when targeting amd64/arm64 do not permit inline assmebly. The main reason is inline assembly can't be optimized. instead it provides intrinsics (that are known) that can participate in optimization.
Quoted 8 lines
specific answer to your question. yes, it implements only a "compiler barrier" not a full memory barrier preventing processor reordering.
https://learn.microsoft.com/en-us/cpp/intrinsics/readwritebarrier?view=msvc-170
"Limits the compiler optimizations that can reorder memory accesses
across the point of the call."note: ignore the caution on the documentation it only applies to C++
Thanks for clarifying. In that case, I think we need a different macro/barrier for the rte_smp_mp() case. When mixing reads and writes on x86, there are cases where we actually do need a full memory barrier/mfence, rather than just a compiler barrier.
/Bruce
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 42 lines · Bruce Richardson
Quoted 41 lines · Tyler Retzlaff
Quoted 19 lines · Bruce Richardson
Quoted 18 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +1
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC Quoted 8 lines
lib/eal/include/generic/rte_atomic.h line 124
Quoted 5 lines
lib/eal/include/generic/rte_atomic.h +2
-0#define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier()Does this actually add a full memory barrier? If so, that's really not what we want, and will slow things down.
for background MSVC when targeting amd64/arm64 do not permit inline assmebly. The main reason is inline assembly can't be optimized. instead it provides intrinsics (that are known) that can participate in optimization.
specific answer to your question. yes, it implements only a "compiler barrier" not a full memory barrier preventing processor reordering.
https://learn.microsoft.com/en-us/cpp/intrinsics/readwritebarrier?view=msvc-170
"Limits the compiler optimizations that can reorder memory accesses
across the point of the call."
Quoted 6 lines
Quoted 1 line
note: ignore the caution on the documentation it only applies to C++
Thanks for clarifying. In that case, I think we need a different macro/barrier for the
rte_smp_mp()case. When mixing reads and writes on x86, there are cases where we actually do need a full memory barrier/mfence, rather than just a compiler barrier.
yes, unfortunately i got distracted by expansion of rte_smp_{w,r}mp() macros in lib/eal/x86/include/rte_atomic.h and assumed they were compiler barriers. i can see now i should have been looking at the documentation comments of the inline function prototypes in lib/eal/include/generic/rte_atomic.h
Quoted 2 lines
/Bruce
RE: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
In reply to Tyler RetzlaffQuoted 51 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +5
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void )
lib/eal/x86/include/rte_atomic.h line 81
Quoted 10 lines
lib/eal/x86/include/rte_atomic.h +4
-0{ +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif
It doesn't look right to me: compiler_barrier is not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.
Another ore generic comment - do we really need to pollute all that code with RTE_TOOLCHAIN_MSVC ifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +0
-1}#define rte_io_mb () rte_mb() --1.8.3.1
RE: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 2 lines
From: Konstantin Ananyev [mailto:[email protected]]
Sent: Tuesday, 4 April 2023 14.11
[...]
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs?
Right now we have ability to have subdir per arch (x86/arm/etc.). Can we treat x86+windows+msvc as a special arch?
I disagree with the per-arch suggestion.
We should have arch directories in EAL only, where the differences are significant.
Anything else, such as drivers and libraries, should be allowed to implement architecture and compiler specific variants using #ifdef or subdirectories/-files as the developer deems appropriate, i.e. #ifdef for few/minor variations, and subfiles or -directories for larger variations.
Multi-architecture code is voluminous, but I don't want separate files for only small variations.
It would be nice to agree on some official guidance on this for the coding guidelines.
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
In reply to Konstantin AnanyevQuoted 56 lines · Konstantin Ananyev
Quoted 56 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else
Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.
i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Quoted 6 lines
Quoted 6 lines
lib/eal/x86/include/rte_atomic.h +0
-1}#define rte_io_mb () rte_mb() --1.8.3.1
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
04/04/2023 16:49, Tyler Retzlaff пишет:
Quoted 70 lines · Konstantin Ananyev
Quoted 56 lines
Quoted 56 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 1 line
Quoted 8 lines
Quoted 3 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
It is really hard to read an follow acode that is heavily ifdefed.
Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to compiler_barrier(), which is already redefined. Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 75 lines · Konstantin Ananyev
04/04/2023 16:49, Tyler Retzlaff пишет:
Quoted 74 lines · Konstantin Ananyev
Quoted 56 lines
Quoted 56 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?
Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef SOME_FOO
/* some documentation */
#define some_macro
#else
#define some_macro
#endif
#ifdef SOME_FOO
/* some documentation 2 */
#define some_macro2
#else
#define some_macro2
#endif
i can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef SOME_FOO
/* some documentation */
#define some_macro
/* some documentation 2 */
#define some_macro2
#else
#define some_macro
#define some_macro2
#endif
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for rte_common.h because it seems doing this would be really ugly there. take a look let me know.
Quoted 4 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.
can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in generic/rte_atomic.h they are intended to be memory barriers.
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
thanks
RE: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endif
Quoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.
My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both SOME_FOO on/off */ #ifdef SOME_FOO
#define some_macro
#else
#define some_macro
#endif
Quoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.
Commented, pls check if I explained my thoughts clear enough there.
Quoted 9 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts: __rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?
RE: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 57 lines
From: Konstantin Ananyev [mailto:[email protected]]
Sent: Wednesday, 5 April 2023 12.57Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Another ore generic comment - do we really need to pollute all that code
with
RTE_TOOLCHAIN_MSVCifdefs?Quoted 44 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
Right now we have ability to have subdir per arch (x86/arm/etc.). Can we treat x86+windows+msvc as a special arch?
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
Quoted 7 lines
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endif
Or the third option of using a dummy for documentation purposes only. rte_memcpy() does this [1], although it is an inline function and not a macro.
[1]: https://elixir.bootlin.com/dpdk/v23.03/source/lib/eal/include/generic/rte_memcpy.h#L90
No preferences here, just mentioning it!
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
It is really hard to read an follow acode that is heavily ifdefed.
Yes, and sometimes it is even harder reading code that is spread across multiple arch-depending files.
It is a choice between the plague or cholera.
But it is one of the unavoidable downsides to supporting many architectures and compilers, so we have to seek out the best compromises.
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 73 lines · Morten Brørup
Quoted 57 lines
From: Konstantin Ananyev [mailto:[email protected]]
Sent: Wednesday, 5 April 2023 12.57Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Another ore generic comment - do we really need to pollute all that code
with
RTE_TOOLCHAIN_MSVCifdefs?Quoted 44 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
Right now we have ability to have subdir per arch (x86/arm/etc.). Can we treat x86+windows+msvc as a special arch?
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
Quoted 7 lines
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifOr the third option of using a dummy for documentation purposes only.
rte_memcpy()does this [1], although it is an inline function and not a macro.[1]: https://elixir.bootlin.com/dpdk/v23.03/source/lib/eal/include/generic/rte_memcpy.h#L90
No preferences here, just mentioning it!
Quoted 2 lines
Quoted 2 lines
Quoted 7 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
It is really hard to read an follow acode that is heavily ifdefed.
Yes, and sometimes it is even harder reading code that is spread across multiple arch-depending files.
It is a choice between the plague or cholera.
But it is one of the unavoidable downsides to supporting many architectures and compilers, so we have to seek out the best compromises.
yes, there is a conditional that has to be *somewhere*. i would propose for now that it be done per-macro or whatever. but when i get the bulk of the changes in i can commit to refactoring some groups out into their own header. rte_common.h is a good candidate for this because of how many conditionals it will contain.
generic/rte_common.h
-> msvc/rte_common.h #include "generic/rte_common.h" -> gnu?/rte_common.h #include "generic/rte_common.h"
this could carry inline/macro documentation in generic/rte_common.h but again i'd prefer to do this after msvc work is stood up at least to the point of having unit tests working before i start moving code around.
for other conditionals i don't think it's worth having a whole file e.g. x86/include/rte_pause.h or something only a couple of blocks are conditional.
ty
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
05/04/2023 16:38, Tyler Retzlaff пишет:
Quoted 74 lines · Morten Brørup
Quoted 73 lines
Quoted 57 lines
From: Konstantin Ananyev [mailto:[email protected]]
Sent: Wednesday, 5 April 2023 12.57Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Another ore generic comment - do we really need to pollute all that code
with
RTE_TOOLCHAIN_MSVCifdefs?Quoted 44 lines
Quoted 10 lines
Quoted 7 lines
Quoted 2 lines
Right now we have ability to have subdir per arch (x86/arm/etc.). Can we treat x86+windows+msvc as a special arch?
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
Quoted 7 lines
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifOr the third option of using a dummy for documentation purposes only.
rte_memcpy()does this [1], although it is an inline function and not a macro.[1]: https://elixir.bootlin.com/dpdk/v23.03/source/lib/eal/include/generic/rte_memcpy.h#L90
No preferences here, just mentioning it!
Quoted 2 lines
Quoted 2 lines
Quoted 5 lines
Quoted 5 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
It is really hard to read an follow acode that is heavily ifdefed.
Yes, and sometimes it is even harder reading code that is spread across multiple arch-depending files.
It is a choice between the plague or cholera.
That's an interesting analogy - never thought about programming as a decease :)
Back to the subject, at least to me two clear files with one conditional include is much more sane then one file with bunch of ifdefs inside.
Quoted 9 lines
Quoted 2 lines
But it is one of the unavoidable downsides to supporting many architectures and compilers, so we have to seek out the best compromises.
yes, there is a conditional that has to be *somewhere*. i would propose for now that it be done per-macro or whatever. but when i get the bulk of the changes in i can commit to refactoring some groups out into their own header.
rte_common.his a good candidate for this because of how many conditionals it will contain.
Quoted 7 lines
generic/rte_common.h
->msvc/rte_common.h#include "generic/rte_common.h" -> gnu?/rte_common.h #include "generic/rte_common.h"this could carry inline/macro documentation in
generic/rte_common.hbut again i'd prefer to do this after msvc work is stood up at least to the point of having unit tests working before i start moving code around.
About special rte_common.h for msvc - that sounds like a good option to me.
Quoted 7 lines
for other conditionals i don't think it's worth having a whole file e.g.
x86/include/rte_pause.hor something only a couple of blocks are conditional.ty
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
In reply to Konstantin AnanyevQuoted 149 lines · Konstantin Ananyev
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifQuoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.Commented, pls check if I explained my thoughts clear enough there.
Quoted 6 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?
Quoted 8 lines
Quoted 3 lines
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts:
__rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?
i'm going to propose if we do this we do it as a separate change later.
i fear it could turn into the following dance which seems not a lot better given i'm sure some people will argue there is no benefit to removing inline assembly for gcc/clang. my preference is not to get side-tracked on refactoring with the short merge window.
#if (defined(__clang__) && clang version < x) ||
(defined(__GNUC__) && gcc version < x)__asm(whatever...
#else__rdtsc()
#endif
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
06/04/2023 01:07, Tyler Retzlaff пишет:
Quoted 166 lines · Konstantin Ananyev
Quoted 149 lines
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifQuoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.Commented, pls check if I explained my thoughts clear enough there.
Quoted 6 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?Quoted 8 lines
Quoted 3 lines
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts:
__rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?i'm going to propose if we do this we do it as a separate change later.
i fear it could turn into the following dance which seems not a lot better given i'm sure some people will argue there is no benefit to removing inline assembly for gcc/clang. my preference is not to get side-tracked on refactoring with the short merge window.
Quoted 6 lines
#if (defined(__clang__) && clang version < x) || (defined(__GNUC__) && gcc version < x)__asm(whatever...
#else__rdtsc()
#endif
Played a bit with https://godbolt.org/.
It seems that __rdtsc() and RMT builtins (xbegin/xend/xtest) are supported all way down to gcc 4.8.1.
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 174 lines · Konstantin Ananyev
06/04/2023 01:07, Tyler Retzlaff пишет:
Quoted 165 lines · Konstantin Ananyev
Quoted 148 lines
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifQuoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.Commented, pls check if I explained my thoughts clear enough there.
Quoted 6 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?Quoted 8 lines
Quoted 3 lines
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts:
__rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?i'm going to propose if we do this we do it as a separate change later.
i fear it could turn into the following dance which seems not a lot better given i'm sure some people will argue there is no benefit to removing inline assembly for gcc/clang. my preference is not to get side-tracked on refactoring with the short merge window.
Quoted 6 lines
#if (defined(__clang__) && clang version < x) || (defined(__GNUC__) && gcc version < x)__asm(whatever...
#else__rdtsc()
#endif
Quoted 3 lines
Played a bit with https://godbolt.org/.
It seems that__rdtsc()and RMT builtins (xbegin/xend/xtest) are supported all way down to gcc 4.8.1.
Do you know what version of clang comes with RHEL 7. Because for 23.07 release at least I need to know it won't break clang compile on RHEL 7 either (which is what makes this painful).
I played around with clang 7 (which i'm not sure is the right version) it had __rdtsc() but it did not have xbegin/xend/xtest. For the various instructions they're appearing in different versions of the compilers.
I'm starting to wonder if i should drop the intrinsics changes into a separate series?
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 175 lines · Tyler Retzlaff
Quoted 174 lines · Konstantin Ananyev
06/04/2023 01:07, Tyler Retzlaff пишет:
Quoted 171 lines · Konstantin Ananyev
Quoted 148 lines
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifQuoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.Commented, pls check if I explained my thoughts clear enough there.
Quoted 6 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?Quoted 8 lines
Quoted 3 lines
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts:
__rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?i'm going to propose if we do this we do it as a separate change later.
i fear it could turn into the following dance which seems not a lot better given i'm sure some people will argue there is no benefit to removing inline assembly for gcc/clang. my preference is not to get side-tracked on refactoring with the short merge window.
#if (defined(__clang__) && clang version < x) || (defined(__GNUC__) && gcc version < x)__asm(whatever...
#else__rdtsc()
#endif
Quoted 8 lines
Quoted 3 lines
Played a bit with https://godbolt.org/.
It seems that__rdtsc()and RMT builtins (xbegin/xend/xtest) are supported all way down to gcc 4.8.1.Do you know what version of clang comes with RHEL 7. Because for 23.07 release at least I need to know it won't break clang compile on RHEL 7 either (which is what makes this painful).
I don't know if we ever stated that we need to support clang from RHEL 7. I always assumed that it was just gcc 4.8 compiler, but I suppose we never stated either that we didn't need to support it....
Quoted 4 lines
I played around with clang 7 (which i'm not sure is the right version) it had
__rdtsc()but it did not have xbegin/xend/xtest. For the various instructions they're appearing in different versions of the compilers.
Running Centos 7 in a VM, I see Clang v3.4.2.
Quoted 3 lines
I'm starting to wonder if i should drop the intrinsics changes into a separate series?
Re: [PATCH 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 189 lines · Bruce Richardson
Quoted 175 lines · Tyler Retzlaff
Quoted 174 lines · Konstantin Ananyev
06/04/2023 01:07, Tyler Retzlaff пишет:
Quoted 171 lines · Konstantin Ananyev
Quoted 148 lines
Quoted 113 lines
Quoted 72 lines
Quoted 72 lines
Quoted 55 lines
Quoted 55 lines
Inline assembly is not supported for msvc x64 instead use _{Read,Write,ReadWrite}Barrier() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +6
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _WriteBarrier() +#define rte_smp_rmb () _ReadBarrier() +#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else Quoted 8 lines
lib/eal/x86/include/rte_atomic.h line 81
Quoted 5 lines
lib/eal/x86/include/rte_atomic.h +3
-0asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +rte_compiler_barrier (); +#endif It doesn't look right to me:
compiler_barrieris not identical to LOCK-ed operation, and is not enough to serve as a proper memory barrier for SMP.i think i'm confused by the macro naming here. i'll take another look thank you for raising it.
Quoted 4 lines
Another ore generic comment - do we really need to pollute all that code with
RTE_TOOLCHAIN_MSVCifdefs? Right now we have ability to have subdir per arch (x86/arm/etc.).
Can we treat x86+windows+msvc as a special arch?Quoted 7 lines
Quoted 4 lines
i asked this question previously and confirmed in the technical board meeting. the answer i received was that the community did not want new directory/headers introduced for compiler support matrix and i should use #ifdef in the existing headers.
Ok, can I then ask at least to minimize number of ifdefs to absolute minimum?
in principal no objection at all, one question though is what to do with comment based documentation attached to macros? e.g.
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
#else
#definesome_macro
#endif#ifdef
SOME_FOO
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro2
#endifi can either duplicate the documentation for every define so it stays "attached" or i can only document the first expansion. let me know what you expect.
so something like this?
#ifdef
SOME_FOO
/* some documentation */
#definesome_macro
/* some documentation 2 */
#definesome_macro2
#else
#definesome_macro
#definesome_macro2
#endifQuoted 4 lines
or should all documentation be duplicated? which can become a teadious redundancy for anyone maintaining it. keep in mind we might have to make an exception for
rte_common.hbecause it seems doing this would be really ugly there. take a look let me know.My personal preference would be to keep one documentation block for both cases (yes, I suppose it needs to be updated if required):
/* some documentation, probably for both
SOME_FOOon/off */ #ifdefSOME_FOO
#definesome_macro
#else
#definesome_macro
#endifQuoted 11 lines
Quoted 5 lines
It is really hard to read an follow acode that is heavily ifdefed. Let say above we probably don't need to re-define rte_smp_rmb/rte_smp_wmb, as both are boiled down to
compiler_barrier(), which is already redefined.can you take a look at v2 of the patch and re-prescribe your advise here? in v2 only the intel macros expand to the compiler barrier. though i find this vexing since as you pointed out it seems they aren't supposed to be compiler only barriers according to the documentation in
generic/rte_atomic.hthey are intended to be memory barriers.Commented, pls check if I explained my thoughts clear enough there.
Quoted 6 lines
please help me if i've goofed up in this regard.
Quoted 2 lines
Another question - could it be visa-versa approach:
can we replace some inline assembly with common instincts whenever possible?Quoted 8 lines
Quoted 3 lines
msvc has only intrinsics and the conditional expansion for msvc is to use those intrinsics, gcc doesn't generally define intrinsics for processor specific code does it?
AFAIK latest gcc (and clang) versions do support majority of these instincts:
__rdtsc, _xbegin/_xend, etc. So my thought was - might be we can use same instincts for all compilers...
One implication I can think about - older versions of gcc.
But might be we can re-order things and have inlines only for these oldere gcc versions?i'm going to propose if we do this we do it as a separate change later.
i fear it could turn into the following dance which seems not a lot better given i'm sure some people will argue there is no benefit to removing inline assembly for gcc/clang. my preference is not to get side-tracked on refactoring with the short merge window.
#if (defined(__clang__) && clang version < x) || (defined(__GNUC__) && gcc version < x)__asm(whatever...
#else__rdtsc()
#endifQuoted 8 lines
Quoted 3 lines
Played a bit with https://godbolt.org/.
It seems that__rdtsc()and RMT builtins (xbegin/xend/xtest) are supported all way down to gcc 4.8.1.Do you know what version of clang comes with RHEL 7. Because for 23.07 release at least I need to know it won't break clang compile on RHEL 7 either (which is what makes this painful).
I don't know if we ever stated that we need to support clang from RHEL 7. I always assumed that it was just gcc 4.8 compiler, but I suppose we never stated either that we didn't need to support it....
Quoted 6 lines
Quoted 4 lines
I played around with clang 7 (which i'm not sure is the right version) it had
__rdtsc()but it did not have xbegin/xend/xtest. For the various instructions they're appearing in different versions of the compilers.Running Centos 7 in a VM, I see Clang v3.4.2.
Konstantin, Bruce
okay, i'm trying this. i sent a new series version where i use the gcc intrinsics if they are available in gcc 4.9. for intrinsics that were not available in 4.9 they have been left as conditional compile for now.
if the CI blows up i will revert back to conditional compile.
this series isn't supposed to be about cleaning up existing code so i'm trying to be helpful here but please check out the latest and ack if you're happy. if we want refactor / cleanups beyond this i'll commit to making the changes in subsequent series that aren't *blocking* this work.
thanks
PATCH 4/9 eal: typedef cpu flag enum as int for msvc
In reply to Tyler RetzlaffForward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
PATCH 5/9 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with msvc don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH 6/9 eal: expand most macros to empty when using msvc
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 ++++++++ lib/eal/include/rte_common.h | 33 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x) == 1) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x) == 0) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +33 -0
@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif #ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);
@@ -88,8 +92,13 @@#define __rte_may_alias __attribute__((__may_alias__))/******* Macro to mark functions and fields scheduled for removal *****/ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_deprecated __attribute__((__deprecated__))#define __rte_deprecated_msg (msg) __attribute__((__deprecated__(msg))) +#else +#define __rte_deprecated +#define __rte_deprecated_msg (msg) +#endif /** * Macro to mark macros and defines scheduled for removal
@@ -117,7 +126,11 @@/** * short definition to mark a function parameter unused */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_unused __attribute__((__unused__)) +#else +#define __rte_unused +#endif /** * Mark pointer as restricted with regard to pointer aliasing.
@@ -141,6 +154,7 @@* even if the underlying stdio implementation is ANSI-compliant, * so this must be overridden. */ +#ifndef RTE_TOOLCHAIN_MSVC #if RTE_CC_IS_GNU #define __rte_format_printf (format_index, first_arg) \ __attribute__((format(gnu_printf, format_index, first_arg)))
@@ -148,6 +162,9 @@#define __rte_format_printf (format_index, first_arg) \ __attribute__((format(printf, format_index, first_arg)))#endif +#else +#define __rte_format_printf (format_index, first_arg) +#endif /** * Tells compiler that the function returns a value that points to
@@ -222,7 +239,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** * Hint never returning function */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_noreturn __attribute__((noreturn)) +#else +#define __rte_noreturn +#endif /** * Issue a warning in case the function's return value is ignored.
@@ -247,12 +268,20 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)* } * @endcode */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_warn_unused_result __attribute__((warn_unused_result)) +#else +#define __rte_warn_unused_result +#endif /** * Force a function to be inlined */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_always_inline inline __attribute__((always_inline)) +#else +#define __rte_always_inline +#endif /** * Force a function to be noinlined
@@ -437,7 +466,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)#define RTE_CACHE_LINE_MIN_SIZE 64/** Force alignment to cache line. */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) +#else +#define __rte_cache_aligned +#endif /** Force minimum cache line alignment. */ #define __rte_cache_min_aligned __rte_aligned(RTE_CACHE_LINE_MIN_SIZE)
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
PATCH 7/9 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -87,6 +87,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -283,6 +285,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH 8/9 telemetry: disable json print formatting with msvc
In reply to Tyler RetzlaffVLAs are unsafe and will never be implemented in MSVC. When compiling with MSVC just return immediately indicating 0 output characters formatted.
For now telemetry doesn't work on Windows, we will revisit support for the telemetry library sometime after we establish the DPDK unit tests.
--- lib/telemetry/telemetry_json.h | 6 ++++++ 1 file changed, 6 insertions(+)
lib/telemetry/telemetry_json.h +6 -0
@@ -30,6 +30,7 @@static inline int __json_snprintf (char *buf,const int len,const char *format, ...) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];va_list ap;int ret;
@@ -41,6 +42,7 @@strcpy (buf, tmp); return ret; } +#endif return 0 ;/* nothing written or modified */ }
@@ -60,6 +62,7 @@static inline int __json_format_str (char *buf,const int len,const char *prefix,const char *str,const char *suffix) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];int tmpidx =0 ;
@@ -98,6 +101,9 @@strcpy (buf, tmp);return tmpidx; +#else +return 0 ; +#endif }/* Copies an empty array into the provided buffer. */
Signature · 1 line
1.8.3.1
PATCH 9/9 telemetry: avoid expanding versioned symbol macros on msvc
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
v2 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64.
Tyler Retzlaff (9):
eal: use rdtsc intrinsic when compiling with msvc
eal: use rtm and xtest intrinsics when compiling with msvc
eal: use barrier intrinsics when compiling with msvc
eal: typedef cpu flag enum as int for msvc
eal: hide GCC extension based alignment markers
eal: expand most macros to empty when using msvc
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: disable json print formatting with msvc
telemetry: avoid expanding versioned symbol macros on msvc
lib/eal/include/generic/rte_atomic.h | 11 ++++++++++ lib/eal/include/generic/rte_cpuflags.h | 12 ++++++----- lib/eal/include/rte_branch_prediction.h | 8 +++++++ lib/eal/include/rte_common.h | 37 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++ lib/eal/x86/include/rte_atomic.h | 14 ++++++++++++- lib/eal/x86/include/rte_cycles.h | 8 +++++++ lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++ lib/telemetry/telemetry_data.c | 16 ++++++++++++++ lib/telemetry/telemetry_json.h | 6 ++++++ 10 files changed, 145 insertions(+), 6 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v2 1/9 eal: use rdtsc intrinsic when compiling with msvc
Inline assembly is not supported for msvc x64 instead use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 8 ++++++++ 1 file changed, 8 insertions(+)
lib/eal/x86/include/rte_cycles.h +8 -0
@@ -6,6 +6,10 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifdef RTE_TOOLCHAIN_MSVC +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +27,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifndef RTE_TOOLCHAIN_MSVC union { uint64_t tsc_64; RTE_STD_C11
@@ -47,6 +52,9 @@"=a" (tsc.lo_32), "=d" (tsc.hi_32));return tsc.tsc_64; +#else +return __rdtsc (); +#endif } static inline uint64_t
Signature · 1 line
1.8.3.1
Re: [PATCH v2 1/9] eal: use rdtsc intrinsic when compiling with msvc
Quoted 32 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use
__rdtscintrinsic.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/x86/include/rte_cycles.h | 8 ++++++++ 1 file changed, 8 insertions(+)lib/eal/x86/include/rte_cycles.h +5
-0@@ -6,6 +6,10 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifdef RTE_TOOLCHAIN_MSVC +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif@@ -23,6 +27,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifndef RTE_TOOLCHAIN_MSVC union { uint64_t tsc_64; RTE_STD_C11
lib/eal/x86/include/rte_cycles.h line 58
Quoted 7 lines
lib/eal/x86/include/rte_cycles.h +3
-0@@ -47,6 +52,9 @@"=a" (tsc.lo_32), "=d" (tsc.hi_32));return tsc.tsc_64; +#else +return __rdtsc (); +#endif }
Checking with google it seems that gcc/clang have an __rdtsc intrinsic as well, so we may be able to avoid ifdefs here completely.
/Bruce
PATCH v2 2/9 eal: use rtm and xtest intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _xbegin, _xend, _xabort and _xtest intrinsics.
--- lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
lib/eal/x86/include/rte_rtm.h +19 -0
@@ -5,6 +5,9 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#ifdef RTE_TOOLCHAIN_MSVC +#include <immintrin.h> +#endif /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +31,47 @@static __rte_always_inline unsigned int rte_xbegin(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned int ret =RTE_XBEGIN_STARTED ; asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" );return ret; +#else +return _xbegin (); +#endif }static __rte_always_inline void rte_xend(void) { +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +#else +_xend (); +#endif }/* not an inline function to workaround a clang bug with -O0 */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_xabort (status) do { \ asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ } while (0) +#else +#define rte_xabort (status) _xabort(status) +#endif static __rte_always_inline int rte_xtest(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned char out; asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" :"=r" (out) ::"memory" );return out; +#else +return _xtest (); +#endif }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v2 3/9 eal: use barrier intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _mm_{s,l,m}fence() intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +9 -1
@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _mm_sfence() +#define rte_smp_rmb () _mm_lfence() +#endif /* * From Intel Software Development Manual; Vol 3;
@@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
Re: [PATCH v2 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 34 lines · Tyler Retzlaff
Inline assembly is not supported for msvc x64 instead use _mm_{s,l,m}fence() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +0
-0@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence()
lib/eal/x86/include/rte_atomic.h line 37
Quoted 10 lines
lib/eal/x86/include/rte_atomic.h +5
-1+#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _mm_sfence() +#define rte_smp_rmb () _mm_lfence() +#endif
I think this change can be dropped from the diff. "rte_compiler_barrier()" is valid in MSVC because you defined it above.
Quoted 21 lines
lib/eal/x86/include/rte_atomic.h +4
-0/* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()Signature · 1 line
1.8.3.1
RE: [PATCH v2 3/9] eal: use barrier intrinsics when compiling with msvc
In reply to Tyler RetzlaffQuoted 34 lines
Inline assembly is not supported for msvc x64 instead use _mm_{s,l,m}fence() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +0
-0
lib/eal/x86/include/rte_atomic.h line 35
Quoted 10 lines
lib/eal/x86/include/rte_atomic.h +4
-1@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence() +#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _mm_sfence() +#define rte_smp_rmb () _mm_lfence()
With x86 memory model CPU doesn't reorder with older reads and write with older writes (there are few exceptions for writes: NT stores, fast string ops, but I think it can be skipped here). For more info pls refer to: IA Software Developer's Manual, 3.8.3 8.2 MEMORY ORDERING. That's why DPDK uses compiler_barrier() as expansion of smp_wmb() and smp_rmb() for x86 platforms. There is nothing wrong in using sfence and lfence here, except that it is probably an overkill.
Quoted 22 lines
lib/eal/x86/include/rte_atomic.h +5
-1+#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb() --1.8.3.1
Re: [PATCH v2 3/9] eal: use barrier intrinsics when compiling with msvc
Quoted 37 lines · Konstantin Ananyev
Quoted 37 lines
Inline assembly is not supported for msvc x64 instead use _mm_{s,l,m}fence() intrinsics.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +0
-0@@ -27,9 +27,13 @@#define rte_rmb () _mm_lfence()
Quoted 13 lines
lib/eal/x86/include/rte_atomic.h line 35
Quoted 7 lines
lib/eal/x86/include/rte_atomic.h +4
-1+#ifndef RTE_TOOLCHAIN_MSVC #define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier() +#else +#define rte_smp_wmb () _mm_sfence() +#define rte_smp_rmb () _mm_lfence()With x86 memory model CPU doesn't reorder with older reads and write with older writes (there are few exceptions for writes: NT stores, fast string ops, but I think it can be skipped here). For more info pls refer to: IA Software Developer's Manual, 3.8.3 8.2 MEMORY ORDERING. That's why DPDK uses
compiler_barrier()as expansion ofsmp_wmb()andsmp_rmb()for x86 platforms. There is nothing wrong in using sfence and lfence here, except that it is probably an overkill.
thank you and Bruce for the explanation. how it was documented confused me. now i understand and i will drop this change.
thanks!
Quoted 23 lines
Quoted 23 lines
lib/eal/x86/include/rte_atomic.h +5
-1+#endif /* * From Intel Software Development Manual; Vol 3; @@ -66,11 +70,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb() --1.8.3.1
PATCH v2 4/9 eal: typedef cpu flag enum as int for msvc
In reply to Tyler RetzlaffForward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appeared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
PATCH v2 5/9 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with msvc don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v2 6/9 eal: expand most macros to empty when using msvc
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 ++++++++ lib/eal/include/rte_common.h | 33 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x) == 1) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x) == 0) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +33 -0
@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif #ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);
@@ -88,8 +92,13 @@#define __rte_may_alias __attribute__((__may_alias__))/******* Macro to mark functions and fields scheduled for removal *****/ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_deprecated __attribute__((__deprecated__))#define __rte_deprecated_msg (msg) __attribute__((__deprecated__(msg))) +#else +#define __rte_deprecated +#define __rte_deprecated_msg (msg) +#endif /** * Macro to mark macros and defines scheduled for removal
@@ -117,7 +126,11 @@/** * short definition to mark a function parameter unused */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_unused __attribute__((__unused__)) +#else +#define __rte_unused +#endif /** * Mark pointer as restricted with regard to pointer aliasing.
@@ -141,6 +154,7 @@* even if the underlying stdio implementation is ANSI-compliant, * so this must be overridden. */ +#ifndef RTE_TOOLCHAIN_MSVC #if RTE_CC_IS_GNU #define __rte_format_printf (format_index, first_arg) \ __attribute__((format(gnu_printf, format_index, first_arg)))
@@ -148,6 +162,9 @@#define __rte_format_printf (format_index, first_arg) \ __attribute__((format(printf, format_index, first_arg)))#endif +#else +#define __rte_format_printf (format_index, first_arg) +#endif /** * Tells compiler that the function returns a value that points to
@@ -222,7 +239,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** * Hint never returning function */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_noreturn __attribute__((noreturn)) +#else +#define __rte_noreturn +#endif /** * Issue a warning in case the function's return value is ignored.
@@ -247,12 +268,20 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)* } * @endcode */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_warn_unused_result __attribute__((warn_unused_result)) +#else +#define __rte_warn_unused_result +#endif /** * Force a function to be inlined */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_always_inline inline __attribute__((always_inline)) +#else +#define __rte_always_inline +#endif /** * Force a function to be noinlined
@@ -437,7 +466,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)#define RTE_CACHE_LINE_MIN_SIZE 64/** Force alignment to cache line. */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) +#else +#define __rte_cache_aligned +#endif /** Force minimum cache line alignment. */ #define __rte_cache_min_aligned __rte_aligned(RTE_CACHE_LINE_MIN_SIZE)
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
Re: [PATCH v2 6/9] eal: expand most macros to empty when using msvc
Quoted 20 lines · Tyler Retzlaff
For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++++ lib/eal/include/rte_common.h | 33 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+)lib/eal/include/rte_branch_prediction.h +0
-0
lib/eal/include/rte_branch_prediction.h line 32
Quoted 8 lines
lib/eal/include/rte_branch_prediction.h +4
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x) == 1) +#endif
I think this should just be "#define likely(x) (x)", since the likely is just a hint as to which way we expect the branch to go. It does not change the logic in the expression.
lib/eal/include/rte_branch_prediction.h line 50
Quoted 12 lines
lib/eal/include/rte_branch_prediction.h +4
-0#endif /* likely */ /** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x) == 0) +#endif
This expansion is wrong, because it changes the logic of the expression, rather than being a hint. As above with likely, I think this should just expand as "(x)", making the unlikely ignored.
lib/eal/include/rte_common.h
Quoted 7 lines
lib/eal/include/rte_branch_prediction.h +0
-0#endif /* unlikely */ #ifdef __cpluspluslib/eal/include/rte_common.h +0
-0
This file has a lot of ifdefs in it now for msvc. Couple of suggestions:
1. can we group these defines together so we can hit multiple entries with a single msvc block?
2. alternatively, for those we want to just permanently null, we could split the responsibility for them between the currnet headers and possibly the build system. Specifically, rather than doing macros based on MSVC, change each macro to the simpler:
#ifndef MACRO #define MACRO macro_definition #endif
Then in the meson.build processing, we can have some separte MSVC processing to put null defines for these into rte_build_config.h, or put in null defines for them in some MSVC-specific header.
Just some thoughts.
/Bruce
Re: [PATCH v2 6/9] eal: expand most macros to empty when using msvc
Quoted 36 lines · Bruce Richardson
Quoted 20 lines · Tyler Retzlaff
For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++++ lib/eal/include/rte_common.h | 33 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+)lib/eal/include/rte_branch_prediction.h +0
-0lib/eal/include/rte_branch_prediction.h line 32
Quoted 8 lines
lib/eal/include/rte_branch_prediction.h +4
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x) == 1) +#endif I think this should just be "#define likely(x) (x)", since the likely is just a hint as to which way we expect the branch to go. It does not change the logic in the expression.
Quoted 2 lines
lib/eal/include/rte_branch_prediction.h +0
-0#endif /* likely */
Quoted 14 lines
lib/eal/include/rte_branch_prediction.h line 50
Quoted 10 lines
lib/eal/include/rte_branch_prediction.h +4
-0/** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x) == 0) +#endif This expansion is wrong, because it changes the logic of the expression, rather than being a hint. As above with likely, I think this should just expand as "(x)", making the unlikely ignored.
ooh, obviously wrong will fix.
Quoted 25 lines
lib/eal/include/rte_common.h
Quoted 8 lines
lib/eal/include/rte_branch_prediction.h +0
-0#endif /* unlikely */ #ifdef __cpluspluslib/eal/include/rte_common.h +0
-0This file has a lot of ifdefs in it now for msvc. Couple of suggestions:
1. can we group these defines together so we can hit multiple entries with a single msvc block?
2. alternatively, for those we want to just permanently null, we could split the responsibility for them between the currnet headers and possibly the build system. Specifically, rather than doing macros based on MSVC, change each macro to the simpler:
#ifndef MACRO #define MACRO macro_definition #endif
Quoted 3 lines
Then in the meson.build processing, we can have some separte MSVC processing to put null defines for these into
rte_build_config.h, or put in null defines for them in some MSVC-specific header.
yes, i'll do this for now. i won't go the route of rte_build_config.h for now since some of the macros i will eventually try to find a way to provide equivalent expansion.
Quoted 3 lines
Just some thoughts.
/Bruce
PATCH v2 7/9 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -87,6 +87,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -283,6 +285,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v2 8/9 telemetry: disable json print formatting with msvc
In reply to Tyler RetzlaffVLAs are unsafe and will never be implemented in MSVC. When compiling with MSVC just return immediately indicating 0 output characters formatted.
For now telemetry doesn't work on Windows, we will revisit support for the telemetry library sometime after we establish the DPDK unit tests.
--- lib/telemetry/telemetry_json.h | 6 ++++++ 1 file changed, 6 insertions(+)
lib/telemetry/telemetry_json.h +6 -0
@@ -30,6 +30,7 @@static inline int __json_snprintf (char *buf,const int len,const char *format, ...) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];va_list ap;int ret;
@@ -41,6 +42,7 @@strcpy (buf, tmp); return ret; } +#endif return 0 ;/* nothing written or modified */ }
@@ -60,6 +62,7 @@static inline int __json_format_str (char *buf,const int len,const char *prefix,const char *str,const char *suffix) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];int tmpidx =0 ;
@@ -98,6 +101,9 @@strcpy (buf, tmp);return tmpidx; +#else +return 0 ; +#endif }/* Copies an empty array into the provided buffer. */
Signature · 1 line
1.8.3.1
PATCH v2 9/9 telemetry: avoid expanding versioned symbol macros on msvc
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
Re: [PATCH v2 9/9] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 11 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>
Does this require a change in telemetry itself? Can it be done via the header file with the versioning macros in it, so it would apply to any other versioned functions we have in DPDK?
/Bruce
Quoted 45 lines
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)lib/telemetry/telemetry_data.c +16
-0@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,Signature · 1 line
1.8.3.1
Re: [PATCH v2 9/9] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 8 lines · Bruce Richardson
Quoted 7 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.
Quoted 8 lines
Quoted 4 lines
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>Does this require a change in telemetry itself? Can it be done via the header file with the versioning macros in it, so it would apply to any other versioned functions we have in DPDK?
i didn't spend a lot of time thinking if the existing macros could be made to expand in the way needed. there is a way of doing versioning on windows but it is foreign to how this symbol versioning scheme works so i plan to investigate it separately after i get unit tests running.
for now i know what i'm doing is ugly but i need to get protection of unit tests so i'm doing minimal changes to get to that point. if you're not comfortable with this going in on a temporary basis i can remove it from this series and we can work on it as a separated patch set.
my bar is pretty low here, as long as it doesn't break any existing linux/gcc/clang etc ok, if msvc is not right i'll take a second pass and design each stop-gap properly. it already doesn't work so things aren't made worse.
let me know if i need to carve this out of the series.
ty
Quoted 48 lines
/Bruce
Quoted 45 lines
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)lib/telemetry/telemetry_data.c +16
-0@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,Signature · 1 line
1.8.3.1
Re: [PATCH v2 9/9] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 28 lines · Tyler Retzlaff
Quoted 8 lines · Bruce Richardson
Quoted 7 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.Quoted 8 lines
Quoted 4 lines
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>Does this require a change in telemetry itself? Can it be done via the header file with the versioning macros in it, so it would apply to any other versioned functions we have in DPDK?
i didn't spend a lot of time thinking if the existing macros could be made to expand in the way needed. there is a way of doing versioning on windows but it is foreign to how this symbol versioning scheme works so i plan to investigate it separately after i get unit tests running.
for now i know what i'm doing is ugly but i need to get protection of unit tests so i'm doing minimal changes to get to that point. if you're not comfortable with this going in on a temporary basis i can remove it from this series and we can work on it as a separated patch set.
Quoted 7 lines
my bar is pretty low here, as long as it doesn't break any existing linux/gcc/clang etc ok, if msvc is not right i'll take a second pass and design each stop-gap properly. it already doesn't work so things aren't made worse.
let me know if i need to carve this out of the series.
It's not that ugly. :-) If no other clear solution is apparent, I can certainly live with this.
/Bruce
v3 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64.
Tyler Retzlaff (11):
eal: use rdtsc intrinsic when compiling with msvc
eal: use rtm and xtest intrinsics when compiling with msvc
eal: use barrier intrinsics when compiling with msvc
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: typedef cpu flag enum as int for msvc
eal: hide GCC extension based alignment markers
eal: expand most macros to empty when using msvc
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: disable json print formatting with msvc
telemetry: avoid expanding versioned symbol macros on msvc
lib/eal/include/generic/rte_atomic.h | 11 ++++++++++ lib/eal/include/generic/rte_cpuflags.h | 12 ++++++----- lib/eal/include/rte_branch_prediction.h | 8 +++++++ lib/eal/include/rte_common.h | 37 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++ lib/eal/x86/include/rte_atomic.h | 9 +++++++- lib/eal/x86/include/rte_cycles.h | 8 +++++++ lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++ lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ lib/eal/x86/rte_power_intrinsics.c | 12 +++++++++++ lib/telemetry/telemetry_data.c | 16 ++++++++++++++ lib/telemetry/telemetry_json.h | 6 ++++++ 15 files changed, 203 insertions(+), 6 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v3 1/11 eal: use rdtsc intrinsic when compiling with msvc
Inline assembly is not supported for msvc x64 instead use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 8 ++++++++ 1 file changed, 8 insertions(+)
lib/eal/x86/include/rte_cycles.h +8 -0
@@ -6,6 +6,10 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifdef RTE_TOOLCHAIN_MSVC +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +27,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifndef RTE_TOOLCHAIN_MSVC union { uint64_t tsc_64; RTE_STD_C11
@@ -47,6 +52,9 @@"=a" (tsc.lo_32), "=d" (tsc.hi_32));return tsc.tsc_64; +#else +return __rdtsc (); +#endif } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH v3 2/11 eal: use rtm and xtest intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _xbegin, _xend, _xabort and _xtest intrinsics.
--- lib/eal/x86/include/rte_rtm.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
lib/eal/x86/include/rte_rtm.h +19 -0
@@ -5,6 +5,9 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#ifdef RTE_TOOLCHAIN_MSVC +#include <immintrin.h> +#endif /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +31,47 @@static __rte_always_inline unsigned int rte_xbegin(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned int ret =RTE_XBEGIN_STARTED ; asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" );return ret; +#else +return _xbegin (); +#endif }static __rte_always_inline void rte_xend(void) { +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +#else +_xend (); +#endif }/* not an inline function to workaround a clang bug with -O0 */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_xabort (status) do { \ asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ } while (0) +#else +#define rte_xabort (status) _xabort(status) +#endif static __rte_always_inline int rte_xtest(void) { +#ifndef RTE_TOOLCHAIN_MSVC unsigned char out; asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" :"=r" (out) ::"memory" );return out; +#else +return _xtest (); +#endif }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v3 3/11 eal: use barrier intrinsics when compiling with msvc
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -1
@@ -28,7 +28,6 @@#define rte_rmb () _mm_lfence()#define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier()/*
@@ -66,11 +65,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
PATCH v3 4/11 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v3 5/11 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for msvc x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
PATCH v3 6/11 eal: typedef cpu flag enum as int for msvc
In reply to Tyler RetzlaffForward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appeared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
Re: [PATCH v3 06/11] eal: typedef cpu flag enum as int for msvc
06/04/2023 01:45, Tyler Retzlaff пишет:
Quoted 22 lines
Forward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum
rte_cpu_flag_tin function parameter lists by re-typdefing the enumrte_cpu_flag_tto therte_cpu_flag_tidentifier.Remove the use of
__extension__on function prototypes whererte_cpu_flag_tappeared in parameter lists, it is sufficient to have the conditionally compiled__extension__at the non-standard forward declaration site.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)lib/eal/include/generic/rte_cpuflags.h +0
-0
lib/eal/include/generic/rte_cpuflags.h struct rte_cpu_intrinsics { · line 52
Quoted 10 lines
lib/eal/include/generic/rte_cpuflags.h +5
-1@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif
Just curious what exactly MSVC doesn't support here? Is that construction like:
enum rte_cpu_flag_t {....};
enum rte_cpu_flag_t;
...
Or something else?
Quoted 24 lines
lib/eal/include/generic/rte_cpuflags.h +2
-4/** * Get name of CPU flag @@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability @@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Re: [PATCH v3 06/11] eal: typedef cpu flag enum as int for msvc
Quoted 35 lines · Konstantin Ananyev
06/04/2023 01:45, Tyler Retzlaff пишет:
Quoted 22 lines
Forward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum
rte_cpu_flag_tin function parameter lists by re-typdefing the enumrte_cpu_flag_tto therte_cpu_flag_tidentifier.Remove the use of
__extension__on function prototypes whererte_cpu_flag_tappeared in parameter lists, it is sufficient to have the conditionally compiled__extension__at the non-standard forward declaration site.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)lib/eal/include/generic/rte_cpuflags.h +0
-0lib/eal/include/generic/rte_cpuflags.h struct rte_cpu_intrinsics { · line 52
Quoted 10 lines
lib/eal/include/generic/rte_cpuflags.h +5
-1@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif
Quoted 6 lines
Just curious what exactly MSVC doesn't support here? Is that construction like:
enumrte_cpu_flag_t{....};
enumrte_cpu_flag_t;
...
Or something else?
Forward declaration of an enum is non standard. It's probably only allowed by gcc as an extension because gcc will make some kind of implementation specific promise for it always to be int size by default (assuming no other -foptions).
If the enum was defined before reference it would probably be accepted by msvc since it could 'see' the definition and know the integer width in use.
Quoted 24 lines
Quoted 24 lines
lib/eal/include/generic/rte_cpuflags.h +2
-4/** * Get name of CPU flag @@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability @@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Re: [PATCH v3 06/11] eal: typedef cpu flag enum as int for msvc
10/04/2023 21:53, Tyler Retzlaff пишет:
Quoted 43 lines · Konstantin Ananyev
Quoted 35 lines
06/04/2023 01:45, Tyler Retzlaff пишет:
Quoted 22 lines
Forward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum
rte_cpu_flag_tin function parameter lists by re-typdefing the enumrte_cpu_flag_tto therte_cpu_flag_tidentifier.Remove the use of
__extension__on function prototypes whererte_cpu_flag_tappeared in parameter lists, it is sufficient to have the conditionally compiled__extension__at the non-standard forward declaration site.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)lib/eal/include/generic/rte_cpuflags.h +0
-0lib/eal/include/generic/rte_cpuflags.h struct rte_cpu_intrinsics { · line 52
Quoted 10 lines
lib/eal/include/generic/rte_cpuflags.h +5
-1@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif Quoted 6 lines
Just curious what exactly MSVC doesn't support here? Is that construction like:
enumrte_cpu_flag_t{....};
enumrte_cpu_flag_t;
...
Or something else?
Quoted 4 lines
Forward declaration of an enum is non standard. It's probably only allowed by gcc as an extension because gcc will make some kind of implementation specific promise for it always to be
intsize by default (assuming no other -foptions).
I understood that part, what is not clear to me from where we are getting forward declarations? As I remember the usual organization of arch specific rte_cpuflags.h:
/* type definition */
enum rte_cpu_flag_t {...};
/some other stuff */
#include "generic/rte_cpuflags.h"
Which contains 'enum rte_cpu_flag_t' type declaration.
But it doesn't look like a forward declaration to me.
Is there a place where we do include "generic/rte_cpuflags.h" directly (not from arch specific header)?
If so. might be we should change it to include arch specific header instead?
Quoted 29 lines
If the enum was defined before reference it would probably be accepted by msvc since it could 'see' the definition and know the integer width in use.
Quoted 24 lines
Quoted 24 lines
lib/eal/include/generic/rte_cpuflags.h +2
-4/** * Get name of CPU flag @@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability @@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Re: [PATCH v3 06/11] eal: typedef cpu flag enum as int for msvc
Quoted 44 lines · Konstantin Ananyev
10/04/2023 21:53, Tyler Retzlaff пишет:
Quoted 43 lines · Konstantin Ananyev
Quoted 41 lines
06/04/2023 01:45, Tyler Retzlaff пишет:
Quoted 22 lines
Forward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum
rte_cpu_flag_tin function parameter lists by re-typdefing the enumrte_cpu_flag_tto therte_cpu_flag_tidentifier.Remove the use of
__extension__on function prototypes whererte_cpu_flag_tappeared in parameter lists, it is sufficient to have the conditionally compiled__extension__at the non-standard forward declaration site.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)lib/eal/include/generic/rte_cpuflags.h +0
-0lib/eal/include/generic/rte_cpuflags.h struct rte_cpu_intrinsics { · line 52
Quoted 10 lines
lib/eal/include/generic/rte_cpuflags.h +5
-1@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif Just curious what exactly MSVC doesn't support here? Is that construction like:
enumrte_cpu_flag_t{....};
enumrte_cpu_flag_t;
...
Or something else?
Quoted 7 lines
Quoted 4 lines
Forward declaration of an enum is non standard. It's probably only allowed by gcc as an extension because gcc will make some kind of implementation specific promise for it always to be
intsize by default (assuming no other -foptions).I understood that part, what is not clear to me from where we are getting forward declarations?
i investigated and expirmented with this further. i can see now there were two things that were tripping things up portability wise.
* it's still a forward declaration even if the full enum definition is visible and thus generates a warning (but not an error).
* the use of __extension__ which is valid in this context because it is after all an extension (causes compilation error for msvc).
my testing shows i'm still getting correct sizes (because the definition is visible) so what i'll do is update this patch to remove the use of __extension__ and allow the warning to be emitted for now. i think this is probably what you're preference would be.
in a future series i will either suppress the warning for msvc or remove the declaration entirely which as you point out should not be needed due to the include via arch/rte_cpuflags.h -> include generic/rte_cpuflags.h.
thanks!
Quoted 44 lines
As I remember the usual organization of arch specific
rte_cpuflags.h:/* type definition */
enumrte_cpu_flag_t{...};/some other stuff */
#include "
generic/rte_cpuflags.h"Which contains 'enum
rte_cpu_flag_t' type declaration.
But it doesn't look like a forward declaration to me.
Is there a place where we do include "generic/rte_cpuflags.h" directly (not from arch specific header)?
If so. might be we should change it to include arch specific header instead?Quoted 29 lines
If the enum was defined before reference it would probably be accepted by msvc since it could 'see' the definition and know the integer width in use.
Quoted 24 lines
Quoted 24 lines
lib/eal/include/generic/rte_cpuflags.h +2
-4/** * Get name of CPU flag @@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability @@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Re: [PATCH v3 06/11] eal: typedef cpu flag enum as int for msvc
17/04/2023 16:46, Tyler Retzlaff пишет:
Quoted 62 lines · Konstantin Ananyev
Quoted 44 lines
10/04/2023 21:53, Tyler Retzlaff пишет:
Quoted 43 lines · Konstantin Ananyev
Quoted 41 lines
06/04/2023 01:45, Tyler Retzlaff пишет:
Quoted 22 lines
Forward declaration of a typedef is a non-standard extension and is not supported by msvc. Use an int instead.
Abstract the use of the int/enum
rte_cpu_flag_tin function parameter lists by re-typdefing the enumrte_cpu_flag_tto therte_cpu_flag_tidentifier.Remove the use of
__extension__on function prototypes whererte_cpu_flag_tappeared in parameter lists, it is sufficient to have the conditionally compiled__extension__at the non-standard forward declaration site.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)lib/eal/include/generic/rte_cpuflags.h +0
-0lib/eal/include/generic/rte_cpuflags.h struct rte_cpu_intrinsics { · line 52
Quoted 10 lines
lib/eal/include/generic/rte_cpuflags.h +5
-1@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif Just curious what exactly MSVC doesn't support here? Is that construction like:
enumrte_cpu_flag_t{....};
enumrte_cpu_flag_t;
...
Or something else?Quoted 7 lines
Quoted 4 lines
Forward declaration of an enum is non standard. It's probably only allowed by gcc as an extension because gcc will make some kind of implementation specific promise for it always to be
intsize by default (assuming no other -foptions).I understood that part, what is not clear to me from where we are getting forward declarations?
i investigated and expirmented with this further. i can see now there were two things that were tripping things up portability wise.
* it's still a forward declaration even if the full enum definition is visible and thus generates a warning (but not an error).
* the use of
__extension__which is valid in this context because it is after all an extension (causes compilation error for msvc).
Quoted 8 lines
my testing shows i'm still getting correct sizes (because the definition is visible) so what i'll do is update this patch to remove the use of
__extension__and allow the warning to be emitted for now. i think this is probably what you're preference would be.in a future series i will either suppress the warning for msvc or remove the declaration entirely which as you point out should not be needed due to the include via
arch/rte_cpuflags.h-> includegeneric/rte_cpuflags.h.
Agree, let's try to remove this declaration.
I don't see any point to have declaration straight after defintion. Thanks
Konstantin
Quoted 47 lines
thanks!
Quoted 44 lines
As I remember the usual organization of arch specific
rte_cpuflags.h:/* type definition */
enumrte_cpu_flag_t{...};/some other stuff */
#include "
generic/rte_cpuflags.h"Which contains 'enum
rte_cpu_flag_t' type declaration.
But it doesn't look like a forward declaration to me.
Is there a place where we do include "generic/rte_cpuflags.h" directly (not from arch specific header)?
If so. might be we should change it to include arch specific header instead?Quoted 29 lines
If the enum was defined before reference it would probably be accepted by msvc since it could 'see' the definition and know the integer width in use.
Quoted 24 lines
Quoted 24 lines
lib/eal/include/generic/rte_cpuflags.h +2
-4/** * Get name of CPU flag @@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability @@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
PATCH v3 7/11 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with msvc don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v3 8/11 eal: expand most macros to empty when using msvc
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 ++++++++ lib/eal/include/rte_common.h | 33 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +33 -0
@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif #ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);
@@ -88,8 +92,13 @@#define __rte_may_alias __attribute__((__may_alias__))/******* Macro to mark functions and fields scheduled for removal *****/ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_deprecated __attribute__((__deprecated__))#define __rte_deprecated_msg (msg) __attribute__((__deprecated__(msg))) +#else +#define __rte_deprecated +#define __rte_deprecated_msg (msg) +#endif /** * Macro to mark macros and defines scheduled for removal
@@ -117,7 +126,11 @@/** * short definition to mark a function parameter unused */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_unused __attribute__((__unused__)) +#else +#define __rte_unused +#endif /** * Mark pointer as restricted with regard to pointer aliasing.
@@ -141,6 +154,7 @@* even if the underlying stdio implementation is ANSI-compliant, * so this must be overridden. */ +#ifndef RTE_TOOLCHAIN_MSVC #if RTE_CC_IS_GNU #define __rte_format_printf (format_index, first_arg) \ __attribute__((format(gnu_printf, format_index, first_arg)))
@@ -148,6 +162,9 @@#define __rte_format_printf (format_index, first_arg) \ __attribute__((format(printf, format_index, first_arg)))#endif +#else +#define __rte_format_printf (format_index, first_arg) +#endif /** * Tells compiler that the function returns a value that points to
@@ -222,7 +239,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** * Hint never returning function */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_noreturn __attribute__((noreturn)) +#else +#define __rte_noreturn +#endif /** * Issue a warning in case the function's return value is ignored.
@@ -247,12 +268,20 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)* } * @endcode */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_warn_unused_result __attribute__((warn_unused_result)) +#else +#define __rte_warn_unused_result +#endif /** * Force a function to be inlined */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_always_inline inline __attribute__((always_inline)) +#else +#define __rte_always_inline +#endif /** * Force a function to be noinlined
@@ -437,7 +466,11 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)#define RTE_CACHE_LINE_MIN_SIZE 64/** Force alignment to cache line. */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_cache_aligned __rte_aligned(RTE_CACHE_LINE_SIZE) +#else +#define __rte_cache_aligned +#endif /** Force minimum cache line alignment. */ #define __rte_cache_min_aligned __rte_aligned(RTE_CACHE_LINE_MIN_SIZE)
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
Re: [PATCH v3 08/11] eal: expand most macros to empty when using msvc
Quoted 9 lines · On Wed, 5 Apr 2023 17:45:16 -0700 Tyler Retzlaff…
For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>
Ok, but doesn't SAL have definitions for most of these?
Re: [PATCH v3 08/11] eal: expand most macros to empty when using msvc
Quoted 7 lines · Stephen Hemminger
Quoted 4 lines · On Wed, 5 Apr 2023 17:45:16 -0700 Tyler Retzlaff…
For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Quoted 7 lines
Quoted 5 lines
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>Ok, but doesn't SAL have definitions for most of these?
SAL could be used too, but i was considering that more as an integration with David's recent clang annotation additions. SAL is a broader topic since to be useful it would need to leverage tooling.
depending on the macros some will come from existing msvc e.g. __declspec some will come from standard C e.g. _Noreturn
many may not be critical for correct behavior but when used can decrease misuse or increase performance through better codegen. once we have things functioning correctly there will naturally be improvements in both areas that follow.
PATCH v3 9/11 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -82,6 +82,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -278,6 +280,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v3 10/11 telemetry: disable json print formatting with msvc
In reply to Tyler RetzlaffVLAs are unsafe and will never be implemented in MSVC. When compiling with MSVC just return immediately indicating 0 output characters formatted.
For now telemetry doesn't work on Windows, we will revisit support for the telemetry library sometime after we establish the DPDK unit tests.
--- lib/telemetry/telemetry_json.h | 6 ++++++ 1 file changed, 6 insertions(+)
lib/telemetry/telemetry_json.h +6 -0
@@ -30,6 +30,7 @@static inline int __json_snprintf (char *buf,const int len,const char *format, ...) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];va_list ap;int ret;
@@ -41,6 +42,7 @@strcpy (buf, tmp); return ret; } +#endif return 0 ;/* nothing written or modified */ }
@@ -60,6 +62,7 @@static inline int __json_format_str (char *buf,const int len,const char *prefix,const char *str,const char *suffix) { +#ifndef RTE_TOOLCHAIN_MSVC char tmp[len];int tmpidx =0 ;
@@ -98,6 +101,9 @@strcpy (buf, tmp);return tmpidx; +#else +return 0 ; +#endif }/* Copies an empty array into the provided buffer. */
Signature · 1 line
1.8.3.1
Re: [PATCH v3 10/11] telemetry: disable json print formatting with msvc
Quoted 4 lines · Tyler Retzlaff
VLAs are unsafe and will never be implemented in MSVC. When compiling with MSVC just return immediately indicating 0 output characters formatted.
Quoted 8 lines
For now telemetry doesn't work on Windows, we will revisit support for the telemetry library sometime after we establish the DPDK unit tests.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/telemetry/telemetry_json.h | 6 ++++++ 1 file changed, 6 insertions(+)
I'm guessing this patch can be dropped if patchset [1] is merged, right?
/Bruce
Re: [PATCH v3 10/11] telemetry: disable json print formatting with msvc
Quoted 8 lines · Bruce Richardson
Quoted 7 lines · Tyler Retzlaff
VLAs are unsafe and will never be implemented in MSVC. When compiling with MSVC just return immediately indicating 0 output characters formatted.
For now telemetry doesn't work on Windows, we will revisit support for the telemetry library sometime after we establish the DPDK unit tests.
Quoted 6 lines
Quoted 5 lines
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/telemetry/telemetry_json.h | 6 ++++++ 1 file changed, 6 insertions(+)I'm guessing this patch can be dropped if patchset [1] is merged, right?
Absolutely. I'll take a look at the referenced series soon.
Quoted 4 lines
/Bruce
PATCH v3 11/11 telemetry: avoid expanding versioned symbol macros on msvc
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
Re: [PATCH v3 11/11] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 24 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)lib/telemetry/telemetry_data.c +1
-0@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC
lib/telemetry/telemetry_data.c line 95
Quoted 10 lines
lib/telemetry/telemetry_data.c +7
-0MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif
Can't see any general way to do this from the versioning header file, so agree that we need some changes here. Rather than defining a public funcion, we could keep the diff reduced by just using a macro alias here, right? For example:
#ifdef RTE_TOOLCHAIN_MSVC
#define rte_tel_data_add_array_int rte_tel_data_add_array_int_v24 #else
MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d,
int64_t x), rte_tel_data_add_array_int_v24);
#endif
If this is a temporary measure, I'd tend towards the shortest solution that can work. However, no strong opinions, so, either using functions as you have it, or macros:
Re: [PATCH v3 11/11] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 45 lines · Bruce Richardson
Quoted 24 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)lib/telemetry/telemetry_data.c +1
-0@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC lib/telemetry/telemetry_data.c line 95
Quoted 10 lines
lib/telemetry/telemetry_data.c +7
-0MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif Can't see any general way to do this from the versioning header file, so agree that we need some changes here. Rather than defining a public funcion, we could keep the diff reduced by just using a macro alias here, right? For example:
#ifdef
RTE_TOOLCHAIN_MSVC
#definerte_tel_data_add_array_intrte_tel_data_add_array_int_v24#else
MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(structrte_tel_data*d,
Quoted 6 lines
int64_t x), rte_tel_data_add_array_int_v24);#endif
If this is a temporary measure, I'd tend towards the shortest solution that can work. However, no strong opinions, so, either using functions as you have it, or macros:
so i have to leave it as it is the reason being the version.map -> exports.def generation does not handle this. the .def only contains the rte_tel_data_add_array_int symbol. if we expand it away to the _v24 name the link will fail.
let's consume the change as-is for now and i will work on the generalized solution when changes are integrated that actually make the windows dso/dll functional.
Quoted 2 lines
Acked-by Bruce Richardson <[email protected]>
Re: [PATCH v3 11/11] telemetry: avoid expanding versioned symbol macros on msvc
Quoted 49 lines · Tyler Retzlaff
Quoted 48 lines · Bruce Richardson
Quoted 24 lines · Tyler Retzlaff
Windows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export
rte_tel_data_add_array_int->rte_tel_data_add_array_int_24andrte_tel_data_add_dict_int->rte_tel_data_add_dict_int_v24functions.Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)lib/telemetry/telemetry_data.c +1
-0@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC lib/telemetry/telemetry_data.c line 95
Quoted 10 lines
lib/telemetry/telemetry_data.c +7
-0MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif Can't see any general way to do this from the versioning header file, so agree that we need some changes here. Rather than defining a public funcion, we could keep the diff reduced by just using a macro alias here, right? For example:
#ifdef
RTE_TOOLCHAIN_MSVC
#definerte_tel_data_add_array_intrte_tel_data_add_array_int_v24#else
MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(structrte_tel_data*d,int64_t x), rte_tel_data_add_array_int_v24);#endif
Quoted 9 lines
Quoted 3 lines
If this is a temporary measure, I'd tend towards the shortest solution that can work. However, no strong opinions, so, either using functions as you have it, or macros:
so i have to leave it as it is the reason being the version.map -> exports.def generation does not handle this. the .def only contains the
rte_tel_data_add_array_intsymbol. if we expand it away to the_v24name the link will fail.
Ah, thanks for clarifying
Quoted 4 lines
let's consume the change as-is for now and i will work on the generalized solution when changes are integrated that actually make the windows dso/dll functional.
Sure, good for now. Keep my ack on any future versions.
Quoted 2 lines
Quoted 2 lines
Acked-by Bruce Richardson <[email protected]>
v4 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v4:
* update rdtsc patch to use gcc intrinsics
* update rtm patch to use gcc intrinsics
* drop patch disable json print formatting, we will utilize series removing VLAs from Bruce
* added patch using prefetch intrinsics for msvc
* added patch using byte swap intrinsics for msvc
* added patch hiding typdefs for msvc using gcc vector extension
* added patch defining MSVC as little endian always
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64
Tyler Retzlaff (14):
eal: use rdtsc intrinsic
eal: use rtm and xtest intrinsics
eal: use barrier intrinsics
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: use prefetch intrinsics
eal: use byte swap intrinsics
eal: typedef cpu flag enum as int
eal: hide GCC extension based alignment markers
eal: hide typedefs based on GCC vector extensions
eal: expand most macros to empty when using MSVC
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: avoid expanding versioned symbol macros on MSVC
eal: always define MSVC as little endian
config/x86/meson.build | 6 +++++ lib/eal/include/generic/rte_atomic.h | 11 ++++++++ lib/eal/include/generic/rte_byteorder.h | 2 ++ lib/eal/include/generic/rte_cpuflags.h | 12 +++++---- lib/eal/include/generic/rte_vect.h | 4 +++ lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ lib/eal/x86/include/rte_atomic.h | 9 ++++++- lib/eal/x86/include/rte_byteorder.h | 27 ++++++++++++++++++++ lib/eal/x86/include/rte_cycles.h | 14 +++++----- lib/eal/x86/include/rte_prefetch.h | 29 +++++++++++++++++++++ lib/eal/x86/include/rte_rtm.h | 18 ++++--------- lib/eal/x86/rte_cpuflags.c | 4 +++ lib/eal/x86/rte_cpuid.h | 7 +++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 +++ lib/eal/x86/rte_power_intrinsics.c | 12 +++++++++ lib/telemetry/telemetry_data.c | 16 ++++++++++++ 19 files changed, 259 insertions(+), 25 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v4 1/14 eal: use rdtsc intrinsic
Inline assembly is not supported for MSVC x64. Convert code to use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
lib/eal/x86/include/rte_cycles.h +8 -6
@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11
@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :
@@ -42,11 +48,7 @@return tsc.tsc_64; }#endif - - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t
Signature · 1 line
1.8.3.1
RE: [PATCH v4 01/14] eal: use rdtsc intrinsic
Quoted 47 lines
Inline assembly is not supported for MSVC x64. Convert code to use
__rdtscintrinsic.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)lib/eal/x86/include/rte_cycles.h +7
-1@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :@@ -42,11 +48,7 @@ return tsc.tsc_64; }#endif
lib/eal/x86/include/rte_cycles.h
Quoted 10 lines
lib/eal/x86/include/rte_cycles.h +1
-6- - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t --
Quoted 1 line
1.8.3.1
PATCH v4 2/14 eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64. Convert code to use _xend, _xabort and _xtest intrinsics.
--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)
config/x86/meson.build +6 -0
@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]
lib/eal/x86/include/rte_rtm.h +5 -13
@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
Re: [PATCH v4 02/14] eal: use rtm and xtest intrinsics
Quoted 5 lines · Tyler Retzlaff
Inline assembly is not supported for MSVC x64. Convert code to use
_xend,_xabortand_xtestintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>---
Subject to the CI not reporting any errors:
Quoted 72 lines
config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)config/x86/meson.build +6
-0@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]lib/eal/x86/include/rte_rtm.h +5
-13@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */ @@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplusSignature · 1 line
1.8.3.1
RE: [PATCH v4 02/14] eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffQuoted 67 lines
Inline assembly is not supported for MSVC x64. Convert code to use
_xend,_xabortand_xtestintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)config/x86/meson.build +6
-0@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]lib/eal/x86/include/rte_rtm.h +4
-8@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */ @@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) {
lib/eal/x86/include/rte_rtm.h
Quoted 10 lines
lib/eal/x86/include/rte_rtm.h +1
-6-unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus --
Quoted 1 line
1.8.3.1
PATCH v4 3/14 eal: use barrier intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -1
@@ -28,7 +28,6 @@#define rte_rmb () _mm_lfence()#define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier()/*
@@ -66,11 +65,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
Re: [PATCH v4 03/14] eal: use barrier intrinsics
Quoted 5 lines · Tyler Retzlaff
Inline assembly is not supported for MSVC x64 instead expand
rte_compiler_barrieras_ReadWriteBarrierand forrte_smp_mb_m_mfenceintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>
One whitespace line deletion below which can be dropped from diff if doing a new revision.
Quoted 28 lines
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +0
-0
lib/eal/x86/include/rte_atomic.h line 31
Quoted 4 lines
lib/eal/x86/include/rte_atomic.h +0
-1@@ -28,7 +28,6 @@#define rte_rmb () _mm_lfence()#define rte_smp_wmb () rte_compiler_barrier() -
^^ unnecessary drop
Quoted 22 lines
lib/eal/x86/include/rte_atomic.h +4
-0#define rte_smp_rmb () rte_compiler_barrier()/* @@ -66,11 +65,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()Signature · 1 line
1.8.3.1
RE: [PATCH v4 03/14] eal: use barrier intrinsics
In reply to Tyler RetzlaffQuoted 48 lines
Inline assembly is not supported for MSVC x64 instead expand
rte_compiler_barrieras_ReadWriteBarrierand forrte_smp_mb_m_mfenceintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-)lib/eal/include/generic/rte_atomic.h +4
-0@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order. lib/eal/x86/include/rte_atomic.h +1
-1@@ -28,7 +28,6 @@#define rte_rmb () _mm_lfence()#define rte_smp_wmb () rte_compiler_barrier() -#define rte_smp_rmb () rte_compiler_barrier()/* @@ -66,11 +65,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );
lib/eal/x86/include/rte_atomic.h
Quoted 10 lines
lib/eal/x86/include/rte_atomic.h +3
-1#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb() --
Quoted 1 line
1.8.3.1
PATCH v4 4/14 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v4 5/14 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
PATCH v4 6/14 eal: use prefetch intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _mm_prefetch and _mm_cldemote intrinsics.
--- lib/eal/x86/include/rte_prefetch.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
lib/eal/x86/include/rte_prefetch.h +29 -0
@@ -13,6 +13,7 @@#include <rte_common.h> #include "generic/rte_prefetch.h" +#ifndef RTE_TOOLCHAIN_MSVC static inline void rte_prefetch0 (const volatile void *p) { asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p));
@@ -43,6 +44,34 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +static inline void rte_prefetch0 (const volatile void *p) +{ +_mm_prefetch (p,1 ); +} + +static inline void rte_prefetch1 (const volatile void *p) +{ +_mm_prefetch (p,2 ); +} + +static inline void rte_prefetch2 (const volatile void *p) +{ +_mm_prefetch (p,3 ); +} + +static inline void rte_prefetch_non_temporal (const volatile void *p) +{ +_mm_prefetch (p,0 ); +} +__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
Re: [PATCH v4 06/14] eal: use prefetch intrinsics
Quoted 5 lines · Tyler Retzlaff
Inline assembly is not supported for MSVC x64 instead use
_mm_prefetchand_mm_cldemoteintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>---
One comment inline below for future consideration.
Quoted 29 lines
lib/eal/x86/include/rte_prefetch.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)lib/eal/x86/include/rte_prefetch.h +11
-0@@ -13,6 +13,7 @@#include <rte_common.h> #include "generic/rte_prefetch.h" +#ifndef RTE_TOOLCHAIN_MSVC static inline void rte_prefetch0 (const volatile void *p) { asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p));@@ -43,6 +44,34 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +static inline void rte_prefetch0 (const volatile void *p) +{ +_mm_prefetch (p,1 ); +} + +static inline void rte_prefetch1 (const volatile void *p) +{ +_mm_prefetch (p,2 ); +}
lib/eal/x86/include/rte_prefetch.h static inline void rte_prefetch_non_temporal(const volatile void *p) · line 66
Quoted 10 lines
lib/eal/x86/include/rte_prefetch.h +10
-0+ +static inline void rte_prefetch2 (const volatile void *p) +{ +_mm_prefetch (p,3 ); +} + +static inline void rte_prefetch_non_temporal (const volatile void *p) +{ +_mm_prefetch (p,0 ); +}
For these prefetch instructions, I'm not sure there is any reason why we can't drop the inline assembly versions. The instructions are very old at this point and should be widely supported by all compilers we use.
Rather than using hard-coded 1, 2, 3 values in the prefetch calls, I believe there should be defines for the levels: "_MM_HINT_T0", "_MM_HINT_T1" etc.
Quoted 14 lines
lib/eal/x86/include/rte_prefetch.h +8
-0+__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }Signature · 1 line
1.8.3.1
RE: [PATCH v4 06/14] eal: use prefetch intrinsics
Quoted 57 lines · Tyler Retzlaff
Quoted 5 lines
Inline assembly is not supported for MSVC x64 instead use
_mm_prefetchand_mm_cldemoteintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>---
Acked-by Bruce Richardson <[email protected]>One comment inline below for future consideration.
Quoted 29 lines
lib/eal/x86/include/rte_prefetch.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)lib/eal/x86/include/rte_prefetch.h +11
-0@@ -13,6 +13,7 @@#include <rte_common.h> #include "generic/rte_prefetch.h" +#ifndef RTE_TOOLCHAIN_MSVC static inline void rte_prefetch0 (const volatile void *p) { asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p));@@ -43,6 +44,34 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +static inline void rte_prefetch0 (const volatile void *p) +{ +_mm_prefetch (p,1 ); +} + +static inline void rte_prefetch1 (const volatile void *p) +{ +_mm_prefetch (p,2 ); +}lib/eal/x86/include/rte_prefetch.h static inline void rte_prefetch_non_temporal(const volatile void *p) · line 66
Quoted 10 lines
lib/eal/x86/include/rte_prefetch.h +10
-0+ +static inline void rte_prefetch2 (const volatile void *p) +{ +_mm_prefetch (p,3 ); +} + +static inline void rte_prefetch_non_temporal (const volatile void *p) +{ +_mm_prefetch (p,0 ); +}For these prefetch instructions, I'm not sure there is any reason why we can't drop the inline assembly versions. The instructions are very old at this point and should be widely supported by all compilers we use.
Quoted 3 lines
Rather than using hard-coded 1, 2, 3 values in the prefetch calls, I believe there should be defines for the levels: "
_MM_HINT_T0", "_MM_HINT_T1" etc.
+1
Quoted 15 lines
Quoted 15 lines
lib/eal/x86/include/rte_prefetch.h +8
-1+__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus } --1.8.3.1
Re: [PATCH v4 06/14] eal: use prefetch intrinsics
In reply to Bruce RichardsonQuoted 55 lines · Bruce Richardson
Quoted 5 lines · Tyler Retzlaff
Inline assembly is not supported for MSVC x64 instead use
_mm_prefetchand_mm_cldemoteintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>---
Acked-by Bruce Richardson <[email protected]>One comment inline below for future consideration.
Quoted 29 lines
lib/eal/x86/include/rte_prefetch.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)lib/eal/x86/include/rte_prefetch.h +11
-0@@ -13,6 +13,7 @@#include <rte_common.h> #include "generic/rte_prefetch.h" +#ifndef RTE_TOOLCHAIN_MSVC static inline void rte_prefetch0 (const volatile void *p) { asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p));@@ -43,6 +44,34 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +static inline void rte_prefetch0 (const volatile void *p) +{ +_mm_prefetch (p,1 ); +} + +static inline void rte_prefetch1 (const volatile void *p) +{ +_mm_prefetch (p,2 ); +}lib/eal/x86/include/rte_prefetch.h static inline void rte_prefetch_non_temporal(const volatile void *p) · line 66
Quoted 10 lines
lib/eal/x86/include/rte_prefetch.h +10
-0+ +static inline void rte_prefetch2 (const volatile void *p) +{ +_mm_prefetch (p,3 ); +} + +static inline void rte_prefetch_non_temporal (const volatile void *p) +{ +_mm_prefetch (p,0 ); +}For these prefetch instructions, I'm not sure there is any reason why we can't drop the inline assembly versions. The instructions are very old at this point and should be widely supported by all compilers we use.
Quoted 3 lines
Rather than using hard-coded 1, 2, 3 values in the prefetch calls, I believe there should be defines for the levels: "
_MM_HINT_T0", "_MM_HINT_T1" etc.
hm, i did not know about these and i bet they fix the problem i had. i.e. if i use e.g. bare '1' i would not get the same prefetch codegen on gcc/msvc but these defines probably resolve that problem.
let me take another look at this one.
Quoted 15 lines
Quoted 15 lines
lib/eal/x86/include/rte_prefetch.h +8
-0+__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }Signature · 1 line
1.8.3.1
PATCH v4 7/14 eal: use byte swap intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand use _byteswap_u{short,long} intrinsics instead.
--- lib/eal/x86/include/rte_byteorder.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
lib/eal/x86/include/rte_byteorder.h +27 -0
@@ -9,6 +9,7 @@extern "C" {#endif +#include <stdlib.h> #include <stdint.h> #include <rte_common.h> #include <rte_config.h>
@@ -18,6 +19,7 @@#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif +#ifndef RTE_TOOLCHAIN_MSVC /* * An architecture-optimized byte swap for a 16-bit value. *
@@ -46,6 +48,31 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x) ); return x; } +#else +/* +* note: we may want to #pragma intrsinsic(_byteswap_u{short,long}) +*/ + +/* +* An architecture-optimized byte swap for a 16-bit value. +* +* Do not use this function directly. The preferred function is rte_bswap16(). +*/ +static inline uint16_t rte_arch_bswap16 (uint16_t _x) +{ +return _byteswap_ushort (_x); +} + +/* +* An architecture-optimized byte swap for a 32-bit value. +* +* Do not use this function directly. The preferred function is rte_bswap32(). +*/ +static inline uint32_t rte_arch_bswap32 (uint32_t _x) +{ +return _byteswap_ulong (_x); +} +#endif #ifndef RTE_FORCE_INTRINSICS #define rte_bswap16 (x) ((uint16_t)(__builtin_constant_p(x) ? \
Signature · 1 line
1.8.3.1
PATCH v4 8/14 eal: typedef cpu flag enum as int
In reply to Tyler RetzlaffForward declaration of a enum is a non-standard extension and is not supported by MSVC. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appeared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
PATCH v4 9/14 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v4 10/14 eal: hide typedefs based on GCC vector extensions
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs based on GCC vector extensions.
--- lib/eal/include/generic/rte_vect.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/generic/rte_vect.h +4 -0
@@ -17,6 +17,8 @@#include <rte_compat.h> +#ifndef RTE_TOOLCHAIN_MSVC +/* Unsigned vector types */ /**
@@ -186,6 +188,8 @@*/ typedef int64_t rte_v256s64_t __attribute__((vector_size (32 ),aligned (32 ))); +#endif +/** * The max SIMD bitwidth value to limit vector path selection. */
Signature · 1 line
1.8.3.1
PATCH v4 11/14 eal: expand most macros to empty when using MSVC
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 +++++++ lib/eal/include/rte_common.h | 41 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++++ 3 files changed, 69 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +41 -0
111 lines not on this page · raw message
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
PATCH v4 12/14 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -82,6 +82,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -278,6 +280,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v4 13/14 telemetry: avoid expanding versioned symbol macros on MSVC
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
PATCH v4 14/14 eal: always define MSVC as little endian
In reply to Tyler RetzlaffThe MSVC compiler does not target big endian platforms so define little endian always.
--- lib/eal/include/generic/rte_byteorder.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/generic/rte_byteorder.h +2 -0
@@ -45,6 +45,8 @@#define RTE_BYTE_ORDER RTE_BIG_ENDIAN#elif defined __LITTLE_ENDIAN__#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN +#elif definedRTE_TOOLCHAIN_MSVC +#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif #if !defined(RTE_BYTE_ORDER )#error Unknown endianness.
Signature · 1 line
1.8.3.1
v5 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v5:
* remove accidental line removal in barrier patch
* update prefetch patch to use intrinsics for all toolchains
* remove x86 specific changes for byte swap patch since msvc intrinsics are processor agnostic always use intrinsics from generic include
* expand __rte_packed empty for msvc packing will be addressed in a separate series
v4:
* update rdtsc patch to use gcc intrinsics
* update rtm patch to use gcc intrinsics
* drop patch disable json print formatting, we will utilize series removing VLAs from Bruce
* added patch using prefetch intrinsics for msvc
* added patch using byte swap intrinsics for msvc
* added patch hiding typdefs for msvc using gcc vector extension
* added patch defining MSVC as little endian always
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64
Tyler Retzlaff (14):
eal: use rdtsc intrinsic
eal: use rtm and xtest intrinsics
eal: use barrier intrinsics
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: use prefetch intrinsics
eal: use byte swap intrinsics
eal: typedef cpu flag enum as int
eal: hide GCC extension based alignment markers
eal: hide typedefs based on GCC vector extensions
eal: expand most macros to empty when using MSVC
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: avoid expanding versioned symbol macros on MSVC
eal: always define MSVC as little endian
config/x86/meson.build | 6 ++++ lib/eal/include/generic/rte_atomic.h | 11 ++++++++ lib/eal/include/generic/rte_byteorder.h | 13 +++++++++ lib/eal/include/generic/rte_cpuflags.h | 12 ++++---- lib/eal/include/generic/rte_vect.h | 4 +++ lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 49 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++++ lib/eal/x86/include/rte_atomic.h | 8 ++++++ lib/eal/x86/include/rte_byteorder.h | 4 +++ lib/eal/x86/include/rte_cycles.h | 14 ++++++---- lib/eal/x86/include/rte_prefetch.h | 25 ++++++++++++++--- lib/eal/x86/include/rte_rtm.h | 18 ++++-------- lib/eal/x86/rte_cpuflags.c | 4 +++ lib/eal/x86/rte_cpuid.h | 7 +++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 +++ lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++ lib/telemetry/telemetry_data.c | 16 +++++++++++ 19 files changed, 243 insertions(+), 28 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v5 1/14 eal: use rdtsc intrinsic
Inline assembly is not supported for MSVC x64. Convert code to use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
lib/eal/x86/include/rte_cycles.h +8 -6
@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11
@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :
@@ -42,11 +48,7 @@return tsc.tsc_64; }#endif - - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH v5 2/14 eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64. Convert code to use _xend, _xabort and _xtest intrinsics.
--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)
config/x86/meson.build +6 -0
@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]
lib/eal/x86/include/rte_rtm.h +5 -13
@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v5 3/14 eal: use barrier intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 8 insertions(+)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -66,11 +66,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
PATCH v5 4/14 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v5 5/14 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
PATCH v5 6/14 eal: use prefetch intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _mm_prefetch and _mm_cldemote intrinsics.
--- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
lib/eal/x86/include/rte_prefetch.h +21 -4
@@ -9,30 +9,38 @@extern "C" {#endif +#include <emmintrin.h> +#include <rte_compat.h> #include <rte_common.h> #include "generic/rte_prefetch.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +static inline void rte_prefetch0 (const volatile void *p) { - asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T0); }static inline void rte_prefetch1 (const volatile void *p) { - asmvolatile ("prefetcht1 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T1); }static inline void rte_prefetch2 (const volatile void *p) { - asmvolatile ("prefetcht2 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T2); }static inline void rte_prefetch_non_temporal (const volatile void *p) { - asmvolatile ("prefetchnta %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_NTA); } +#pragma GCC diagnostic pop + +#ifndef RTE_TOOLCHAIN_MSVC /* * We use raw byte codes for now as only the newest compiler * versions support this instruction natively.
@@ -43,6 +51,15 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
Re: [PATCH v5 06/14] eal: use prefetch intrinsics
Quoted 5 lines · Tyler Retzlaff
Inline assembly is not supported for MSVC x64 instead use
_mm_prefetchand_mm_cldemoteintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>---
PATCH v5 7/14 eal: use byte swap intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand use _byteswap_u{ushort,ulong,uint64} intrinsics instead.
--- lib/eal/include/generic/rte_byteorder.h | 11 +++++++++++ lib/eal/x86/include/rte_byteorder.h | 4 ++++ 2 files changed, 15 insertions(+)
lib/eal/include/generic/rte_byteorder.h +11 -0
@@ -234,6 +234,7 @@#endif /* __DOXYGEN__ */ #ifdef RTE_FORCE_INTRINSICS +#ifndef RTE_TOOLCHAIN_MSVC #if __GNUC__ >4 || (__GNUC__ ==4 && __GNUC_MINOR__ >=8 )#define rte_bswap16 (x) __builtin_bswap16(x)#endif
@@ -241,6 +242,16 @@#define rte_bswap32 (x) __builtin_bswap32(x)#define rte_bswap64 (x) __builtin_bswap64(x) +#else +/* +* note: we may want to #pragma intrsinsic(_byteswap_u{short,long,uint64}) +*/ +#define rte_bswap16 (x) _byteswap_ushort(x) + +#define rte_bswap32 (x) _byteswap_ulong(x) + +#define rte_bswap64 (x) _byteswap_uint64(x) +#endif #endif
lib/eal/x86/include/rte_byteorder.h +4 -0
@@ -18,6 +18,7 @@#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif +#ifndef RTE_TOOLCHAIN_MSVC /* * An architecture-optimized byte swap for a 16-bit value. *
@@ -69,6 +70,7 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x) rte_arch_bswap16(x)))#endif #endif +#endif #define rte_cpu_to_le_16 (x) (x)#define rte_cpu_to_le_32 (x) (x)
@@ -86,11 +88,13 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x)#define rte_be_to_cpu_32 (x) rte_bswap32(x)#define rte_be_to_cpu_64 (x) rte_bswap64(x) +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 #include "rte_byteorder_32.h" #else #include "rte_byteorder_64.h" #endif +#endif #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v5 8/14 eal: typedef cpu flag enum as int
In reply to Tyler RetzlaffForward declaration of a enum is a non-standard extension and is not supported by MSVC. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appeared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
PATCH v5 9/14 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v5 10/14 eal: hide typedefs based on GCC vector extensions
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs based on GCC vector extensions.
--- lib/eal/include/generic/rte_vect.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/generic/rte_vect.h +4 -0
@@ -17,6 +17,8 @@#include <rte_compat.h> +#ifndef RTE_TOOLCHAIN_MSVC +/* Unsigned vector types */ /**
@@ -186,6 +188,8 @@*/ typedef int64_t rte_v256s64_t __attribute__((vector_size (32 ),aligned (32 ))); +#endif +/** * The max SIMD bitwidth value to limit vector path selection. */
Signature · 1 line
1.8.3.1
PATCH v5 11/14 eal: expand most macros to empty when using MSVC
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +45 -0
120 lines not on this page · raw message
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
RE: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 25 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)lib/eal/include/rte_branch_prediction.h +0
-0
lib/eal/include/rte_branch_prediction.h line 31
Quoted 7 lines
lib/eal/include/rte_branch_prediction.h +3
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x)
This must be (!!(x)), because x may be non-Boolean, e.g. likely(n & 0x10), and likely() must return Boolean (0 or 1).
lib/eal/include/rte_branch_prediction.h line 49
Quoted 12 lines
lib/eal/include/rte_branch_prediction.h +4
-0+#endif #endif /* likely */ /** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x)
This must also be (!!(x)), for the same reason as above.
Quoted 9 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* unlikely */ #ifdef __cpluspluslib/eal/include/rte_common.h +0
-0
lib/eal/include/rte_common.h line 72
Quoted 8 lines
lib/eal/include/rte_common.h +4
-0@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif
It should be reviewed that __rte_aligned() is only used for optimization purposes, and is not required for DPDK to function properly.
lib/eal/include/rte_common.h line 91
Quoted 12 lines
lib/eal/include/rte_common.h +4
-0#ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);@@ -80,16 +84,29 @@/** * Force a structure to be packed */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif
Similar comment as for __rte_aligned(); however, I consider it more likely that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
The same risk applies to __rte_aligned(), but with lower probability.
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 19 lines · Morten Brørup
Quoted 19 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)
Quoted 16 lines
lib/eal/include/rte_branch_prediction.h line 31
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +3
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x)This must be (!!(x)), because x may be non-Boolean, e.g.
likely(n & 0x10), andlikely()must return Boolean (0 or 1).
Will this really make a difference? Is there somewhere likely/unlikely would be used where we would not get the same conversion to boolean than we get using "!!" operator. [NOTE: Not saying we shouldn't put in the !!, just wondering if there are actual cases where it affects the output?]
Quoted 18 lines
lib/eal/include/rte_branch_prediction.h line 49
Quoted 12 lines
lib/eal/include/rte_branch_prediction.h +4
-0+#endif #endif /* likely */ /** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x)This must also be (!!(x)), for the same reason as above.
Quoted 3 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* unlikely */
Quoted 17 lines
Quoted 6 lines
lib/eal/include/rte_branch_prediction.h +0
-0#ifdef __cpluspluslib/eal/include/rte_common.h +0
-0lib/eal/include/rte_common.h line 72
Quoted 8 lines
lib/eal/include/rte_common.h +4
-0@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used for optimization purposes, and is not required for DPDK to function properly.
Good point.
If we look across all of DPDK, things will likely break, as we are relying on alignment in various places to use the aligned versions of instructions. For example _mm256_load_si256() vs _mm256_loadu_si256() in our x86 vectorized driver code. A "git grep _load_si" shows quite a few aligned vector load instructions used in our codebase. These will fault and cause a crash if the data is not properly aligned. [I suspect that there are similar restrictions on other architectures too, just not familiar with their intrinsics to check.]
However, it may be that none of the code paths where these are used is in code currently compiled on windows, so this may be safe for now. The occurances are mostly in drivers.
$ git grep -l _load_si drivers/common/idpf/idpf_common_rxtx_avx512.c drivers/event/dlb2/dlb2.c drivers/net/bnxt/bnxt_rxtx_vec_avx2.c drivers/net/bnxt/bnxt_rxtx_vec_sse.c drivers/net/enic/enic_rxtx_vec_avx2.c drivers/net/i40e/i40e_rxtx_vec_avx2.c drivers/net/i40e/i40e_rxtx_vec_avx512.c drivers/net/iavf/iavf_rxtx_vec_avx2.c drivers/net/iavf/iavf_rxtx_vec_avx512.c drivers/net/iavf/iavf_rxtx_vec_sse.c drivers/net/ice/ice_rxtx_vec_avx2.c drivers/net/ice/ice_rxtx_vec_avx512.c drivers/net/ice/ice_rxtx_vec_sse.c drivers/net/mlx5/mlx5_rxtx_vec_sse.h lib/acl/acl_bld.c lib/distributor/rte_distributor_match_sse.c lib/efd/rte_efd_x86.h lib/hash/rte_cuckoo_hash.c lib/member/rte_member_x86.h lib/net/net_crc_avx512.c lib/net/net_crc_sse.c
Quoted 15 lines
lib/eal/include/rte_common.h line 91
Quoted 12 lines
lib/eal/include/rte_common.h +4
-0#ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);@@ -80,16 +84,29 @@/** * Force a structure to be packed */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider it more likely that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
+1
Once libraries such as the net library in DPDK will form part of the windows build this will need to be addressed or things will break.
Quoted 2 lines
The same risk applies to
__rte_aligned(), but with lower probability.
/Bruce
RE: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 38 lines
From: Bruce Richardson [mailto:[email protected]]
Sent: Friday, 14 April 2023 11.22Quoted 19 lines · Morten Brørup
Quoted 19 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)Quoted 15 lines
lib/eal/include/rte_branch_prediction.h line 31
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +3
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x)This must be (!!(x)), because x may be non-Boolean, e.g.
likely(n & 0x10),
Quoted 7 lines
and
likely()must return Boolean (0 or 1).Quoted 1 line
Will this really make a difference? Is there somewhere likely/unlikely would be used where we would not get the same conversion to boolean than we get using "!!" operator. [NOTE: Not saying we shouldn't put in the !!, just wondering if there are actual cases where it affects the output?]
I agree that it makes no difference the way it is typically used.
But there are creative developers out there, so these macros definitely need the "!!" conversion to Boolean.
Quoted 40 lines
Quoted 19 lines
lib/eal/include/rte_branch_prediction.h line 49
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +4
-0+#endif #endif /* likely */ /** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x)This must also be (!!(x)), for the same reason as above.
Quoted 3 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* unlikely */ Quoted 16 lines
Quoted 6 lines
lib/eal/include/rte_branch_prediction.h +0
-0#ifdef __cpluspluslib/eal/include/rte_common.h +0
-0lib/eal/include/rte_common.h line 72
Quoted 8 lines
lib/eal/include/rte_common.h +4
-0@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used for optimizationpurposes, and is not required for DPDK to function properly.
Quoted 1 line
Good point.
Quoted 8 lines
If we look across all of DPDK, things will likely break, as we are relying on alignment in various places to use the aligned versions of instructions. For example
_mm256_load_si256()vs_mm256_loadu_si256()in our x86 vectorized driver code. A "git grep_load_si" shows quite a few aligned vector load instructions used in our codebase. These will fault and cause a crash if the data is not properly aligned. [I suspect that there are similar restrictions on other architectures too, just not familiar with their intrinsics to check.]
Another thing that has been annoying me with the use of vector instructions:
Vector instructions are often used in a way where they cast away the type they are working on, so if that type is modified (e.g. a field is moved), the code will happily build, but fail at runtime.
When casting away the type for vector instructions, _Static_assert or BUILD_BUG_ON should be used to verify the assumptions about the cast away type. Such a practice might catch some of the places where the missing alignment (and missing structure packing) would fail.
Quoted 43 lines
However, it may be that none of the code paths where these are used is in code currently compiled on windows, so this may be safe for now. The occurances are mostly in drivers.
$ git grep -l _load_si drivers/common/idpf/idpf_common_rxtx_avx512.c drivers/event/dlb2/dlb2.c drivers/net/bnxt/bnxt_rxtx_vec_avx2.c drivers/net/bnxt/bnxt_rxtx_vec_sse.c drivers/net/enic/enic_rxtx_vec_avx2.c drivers/net/i40e/i40e_rxtx_vec_avx2.c drivers/net/i40e/i40e_rxtx_vec_avx512.c drivers/net/iavf/iavf_rxtx_vec_avx2.c drivers/net/iavf/iavf_rxtx_vec_avx512.c drivers/net/iavf/iavf_rxtx_vec_sse.c drivers/net/ice/ice_rxtx_vec_avx2.c drivers/net/ice/ice_rxtx_vec_avx512.c drivers/net/ice/ice_rxtx_vec_sse.c drivers/net/mlx5/mlx5_rxtx_vec_sse.h lib/acl/acl_bld.c lib/distributor/rte_distributor_match_sse.c lib/efd/rte_efd_x86.h lib/hash/rte_cuckoo_hash.c lib/member/rte_member_x86.h lib/net/net_crc_avx512.c lib/net/net_crc_sse.cQuoted 14 lines
lib/eal/include/rte_common.h line 91
Quoted 12 lines
lib/eal/include/rte_common.h +4
-0#ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);@@ -80,16 +84,29 @@/** * Force a structure to be packed */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider it more likely
Quoted 8 lines
that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
Quoted 1 line
+1
Once libraries such as the net library in DPDK will form part of the windows build this will need to be addressed or things will break.
Yes. And for application developers, we should deprecate and replace the __rte_packed macro with something that works on both MSVC and GCC/CLANG. The same probably goes for __rte_aligned().
But, let's not hold back Tyler's work. Just put it on the long term TODO list for MSVC support.
Quoted 5 lines
Quoted 3 lines
The same risk applies to
__rte_aligned(), but with lower probability./Bruce
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 41 lines · Morten Brørup
Quoted 41 lines
From: Bruce Richardson [mailto:[email protected]]
Sent: Friday, 14 April 2023 11.22Quoted 19 lines · Morten Brørup
Quoted 19 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)Quoted 15 lines
lib/eal/include/rte_branch_prediction.h line 31
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +3
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x)This must be (!!(x)), because x may be non-Boolean, e.g.
likely(n & 0x10),and
likely()must return Boolean (0 or 1).Quoted 1 line
Quoted 9 lines
Quoted 4 lines
Will this really make a difference? Is there somewhere likely/unlikely would be used where we would not get the same conversion to boolean than we get using "!!" operator. [NOTE: Not saying we shouldn't put in the !!, just wondering if there are actual cases where it affects the output?]
I agree that it makes no difference the way it is typically used.
But there are creative developers out there, so these macros definitely need the "!!" conversion to Boolean.
Sure.
Quoted 49 lines
Quoted 40 lines
Quoted 19 lines
lib/eal/include/rte_branch_prediction.h line 49
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +4
-0+#endif #endif /* likely */ /** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x)This must also be (!!(x)), for the same reason as above.
Quoted 3 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* unlikely */ Quoted 16 lines
Quoted 6 lines
lib/eal/include/rte_branch_prediction.h +0
-0#ifdef __cpluspluslib/eal/include/rte_common.h +0
-0lib/eal/include/rte_common.h line 72
Quoted 8 lines
lib/eal/include/rte_common.h +4
-0@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used for optimizationpurposes, and is not required for DPDK to function properly.
Quoted 1 line
Good point.
Quoted 8 lines
If we look across all of DPDK, things will likely break, as we are relying on alignment in various places to use the aligned versions of instructions. For example
_mm256_load_si256()vs_mm256_loadu_si256()in our x86 vectorized driver code. A "git grep_load_si" shows quite a few aligned vector load instructions used in our codebase. These will fault and cause a crash if the data is not properly aligned. [I suspect that there are similar restrictions on other architectures too, just not familiar with their intrinsics to check.]
Quoted 6 lines
Another thing that has been annoying me with the use of vector instructions:
Vector instructions are often used in a way where they cast away the type they are working on, so if that type is modified (e.g. a field is moved), the code will happily build, but fail at runtime.
When casting away the type for vector instructions,
_Static_assertorBUILD_BUG_ONshould be used to verify the assumptions about the cast away type. Such a practice might catch some of the places where the missing alignment (and missing structure packing) would fail.
Agreed. And, in fairness, this is sometimes done in our code, e.g. [1], but should probably be more widely done. It's something we should try and catch in reviews of vector code, as it also helps document what exactly we are doing and why.
/Bruce
[1] http://git.dpdk.org/dpdk/tree/drivers/net/i40e/i40e_rxtx_vec_avx2.c#n183
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
In reply to Morten BrørupQuoted 19 lines · Morten Brørup
Quoted 19 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>--- lib/eal/include/rte_branch_prediction.h | 8 ++++++ lib/eal/include/rte_common.h | 45 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++++++ 3 files changed, 73 insertions(+)
Quoted 15 lines
lib/eal/include/rte_branch_prediction.h line 31
Quoted 13 lines
lib/eal/include/rte_branch_prediction.h +3
-0@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (x)This must be (!!(x)), because x may be non-Boolean, e.g.
likely(n & 0x10), andlikely()must return Boolean (0 or 1).
yes, you're right. will fix.
Quoted 4 lines
Quoted 4 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* likely */
Quoted 11 lines
lib/eal/include/rte_branch_prediction.h line 49
Quoted 9 lines
lib/eal/include/rte_branch_prediction.h +3
-0/** @@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (x)This must also be (!!(x)), for the same reason as above.
ack
Quoted 4 lines
Quoted 4 lines
lib/eal/include/rte_branch_prediction.h +1
-0+#endif #endif /* unlikely */
Quoted 16 lines
Quoted 6 lines
lib/eal/include/rte_branch_prediction.h +0
-0#ifdef __cpluspluslib/eal/include/rte_common.h +0
-0lib/eal/include/rte_common.h line 72
Quoted 8 lines
lib/eal/include/rte_common.h +4
-0@@ -65,7 +65,11 @@/** * Force alignment */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used for optimization purposes, and is not required for DPDK to function properly.
so to expand on what i have in mind (and explain why i leave it expanded empty for now)
while msvc has a __declspec for align there is a mismatch between where gcc and msvc want it placed to control alignment of objects.
msvc support won't be functional in 23.07 because of atomics. so once we reach the 23.11 cycle (where we can merge c11 changes) it means we can also use standard _Alignas which can accomplish the same thing but portably.
full disclosure the catch is i still have to properly locate the <thing> that does the alignment and some small questions about the expansion and use of the existing macro.
on the subject of DPDK requiring proper alignment, you're right it is generally for performance but also for pre-c11 atomics.
one question i have been asking myself is would the community see value in more compile time assertions / testing of the size and alignment of structures and offset of structure fields? we have a few key RTE_BUILD_BUG_ON() assertions but i've discovered they don't offer comprehensive protection.
Quoted 15 lines
lib/eal/include/rte_common.h line 91
Quoted 13 lines
lib/eal/include/rte_common.h +4
-0#ifdef RTE_ARCH_STRICT_ALIGN typedef uint64_t unaligned_uint64_t __rte_aligned(1);@@ -80,16 +84,29 @@/** * Force a structure to be packed */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider it more likely that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
so interestingly i've discovered this is kind of a mess and as you note some places we can't just "fix" it for abi compatibility reasons.
in some instances the packing is being applied to structures where it is essentially a noop. i.e. natural alignment gets you the same thing so it is superfluous.
in some instances the packing is being applied to structures that are private and it appears to be completely unnecessary e.g. some structure that isn't nested into something else and sizeof() or offsetof() fields don't matter in the context of their use.
in some instances it is completely necessary usually when type punning buffers containing network framing etc...
unfortunately the standard doesn't offer me an out here as there is an issue of placement of the pragma/attributes that do the packing.
for places it isn't needed it, whatever i just expand empty. for places it is superfluous again because msvc has no stable abi (we're not established yet) again i just expand empty. finally for the places where it is needed i'll probably need to expand conditionally but i think the instances are far fewer than current use.
Quoted 2 lines
The same risk applies to
__rte_aligned(), but with lower probability.
so that's the long winded story of why they are both expanded empty for now for msvc. but when the time comes i want to submit patch series that focus on each specifically to generate robust discussion.
ty
RE: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 20 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Friday, 14 April 2023 19.02Quoted 4 lines · Morten Brørup
Quoted 4 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is
we
Quoted 1 line
Quoted 1 line
need to test that most of the macros do what they should but at the
same
Quoted 3 lines
Quoted 3 lines
time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that
work
Quoted 1 line
Quoted 1 line
correctly for msvc and where not possible provide some alternate
macros
Quoted 3 lines
Quoted 3 lines
to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>
[...]
Quoted 16 lines
Quoted 10 lines
lib/eal/include/rte_common.h line 72
Quoted 8 lines
/**
* Force alignment
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used foroptimization purposes, and is not required for DPDK to function properly.
so to expand on what i have in mind (and explain why i leave it expanded empty for now)
Quoted 7 lines
while msvc has a
__declspecfor align there is a mismatch between where gcc and msvc want it placed to control alignment of objects.msvc support won't be functional in 23.07 because of atomics. so once we reach the 23.11 cycle (where we can merge c11 changes) it means we can also use standard
_Alignaswhich can accomplish the same thing but portably.
That (C11 standard _Alignas) should be the roadmap for solving the alignment requirements.
This should be a general principle for DPDK... if the C standard offers something, don't reinvent our own. And as a consequence of the upgrade to C11, we should deprecate all our own now-obsolete substitutes for these.
Quoted 5 lines
full disclosure the catch is i still have to properly locate the <thing> that does the alignment and some small questions about the expansion and use of the existing macro.
Quoted 8 lines
on the subject of DPDK requiring proper alignment, you're right it is generally for performance but also for pre-c11 atomics.
one question i have been asking myself is would the community see value in more compile time assertions / testing of the size and alignment of structures and offset of structure fields? we have a few key
RTE_BUILD_BUG_ON()assertions but i've discovered they don't offer comprehensive protection.
Absolutely. Catching bugs at build time is much better than any alternative!
Quoted 30 lines
Quoted 10 lines
lib/eal/include/rte_common.h line 91
Quoted 8 lines
/**
* Force a structure to be packed
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider it morelikely that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
so interestingly i've discovered this is kind of a mess and as you note some places we can't just "fix" it for abi compatibility reasons.
in some instances the packing is being applied to structures where it is essentially a noop. i.e. natural alignment gets you the same thing so it is superfluous.
in some instances the packing is being applied to structures that are private and it appears to be completely unnecessary e.g. some structure that isn't nested into something else and
sizeof()oroffsetof()fields don't matter in the context of their use.in some instances it is completely necessary usually when type punning buffers containing network framing etc...
Quoted 8 lines
unfortunately the standard doesn't offer me an out here as there is an issue of placement of the pragma/attributes that do the packing.
for places it isn't needed it, whatever i just expand empty. for places it is superfluous again because msvc has no stable abi (we're not established yet) again i just expand empty. finally for the places where it is needed i'll probably need to expand conditionally but i think the instances are far fewer than current use.
Optimally, we will have a common macro (or other solution) to support both GCC/CLANG and MSVC to replace or supplement __rte_packed. However, the cost of this may be an API break if we replace __rte_packed.
Quoted 7 lines
Quoted 3 lines
The same risk applies to
__rte_aligned(), but with lower probability.so that's the long winded story of why they are both expanded empty for now for msvc. but when the time comes i want to submit patch series that focus on each specifically to generate robust discussion.
Sounds like the right path to take.
Now, I'm thinking ahead here...
We should be prepared to accept a major ABI/API break at one point in time, to replace our home-grown macros with C11 standard solutions and to fully support MSVC. This is not happening anytime soon, but the Techboard should acknowledge that this is going to happen (with an unspecified release), so it can be formally announced. The sooner it is announced, the more time developers will have to prepare for it.
All the details do not need to be known at the time of the announcement; they can be added along the way, based on the discussions from your future patches.
Quoted 2 lines
ty
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 59 lines · Morten Brørup
Quoted 20 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Friday, 14 April 2023 19.02Quoted 4 lines · Morten Brørup
Quoted 4 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here is
we
Quoted 1 line
Quoted 1 line
need to test that most of the macros do what they should but at the
same
Quoted 3 lines
Quoted 3 lines
time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that
work
Quoted 1 line
Quoted 1 line
correctly for msvc and where not possible provide some alternate
macros
Quoted 3 lines
Quoted 3 lines
to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>[...]
Quoted 16 lines
Quoted 10 lines
lib/eal/include/rte_common.h line 72
Quoted 8 lines
/**
* Force alignment
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used foroptimization purposes, and is not required for DPDK to function properly.
so to expand on what i have in mind (and explain why i leave it expanded empty for now)
Quoted 7 lines
while msvc has a
__declspecfor align there is a mismatch between where gcc and msvc want it placed to control alignment of objects.msvc support won't be functional in 23.07 because of atomics. so once we reach the 23.11 cycle (where we can merge c11 changes) it means we can also use standard
_Alignaswhich can accomplish the same thing but portably.That (C11 standard
_Alignas) should be the roadmap for solving the alignment requirements.This should be a general principle for DPDK... if the C standard offers something, don't reinvent our own. And as a consequence of the upgrade to C11, we should deprecate all our own now-obsolete substitutes for these.
Quoted 8 lines
full disclosure the catch is i still have to properly locate the <thing> that does the alignment and some small questions about the expansion and use of the existing macro.
on the subject of DPDK requiring proper alignment, you're right it is generally for performance but also for pre-c11 atomics.
Quoted 7 lines
Quoted 5 lines
one question i have been asking myself is would the community see value in more compile time assertions / testing of the size and alignment of structures and offset of structure fields? we have a few key
RTE_BUILD_BUG_ON()assertions but i've discovered they don't offer comprehensive protection.Absolutely. Catching bugs at build time is much better than any alternative!
that's handy feedback. i am now encouraged to include more compile time checks in advance of or along with changes related to structure abi. follow on question, once we do get to use c11 would something like _Static_assert be preferable over RTE_BUILD_BUG_ON? structures sensitive to layout could be co-located with the asserts right at the point of definition. or is there something extra RTE_BUILD_BUG_ON gives us?
Quoted 50 lines
Quoted 31 lines
Quoted 11 lines
lib/eal/include/rte_common.h line 91
Quoted 9 lines
/**
* Force a structure to be packed
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider it morelikely that structure packing is a functional requirement, and not just used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in DPDK applications.
so interestingly i've discovered this is kind of a mess and as you note some places we can't just "fix" it for abi compatibility reasons.
in some instances the packing is being applied to structures where it is essentially a noop. i.e. natural alignment gets you the same thing so it is superfluous.
in some instances the packing is being applied to structures that are private and it appears to be completely unnecessary e.g. some structure that isn't nested into something else and
sizeof()oroffsetof()fields don't matter in the context of their use.in some instances it is completely necessary usually when type punning buffers containing network framing etc...
Quoted 8 lines
unfortunately the standard doesn't offer me an out here as there is an issue of placement of the pragma/attributes that do the packing.
for places it isn't needed it, whatever i just expand empty. for places it is superfluous again because msvc has no stable abi (we're not established yet) again i just expand empty. finally for the places where it is needed i'll probably need to expand conditionally but i think the instances are far fewer than current use.
Optimally, we will have a common macro (or other solution) to support both GCC/CLANG and MSVC to replace or supplement
__rte_packed. However, the cost of this may be an API break if we replace__rte_packed.Quoted 7 lines
Quoted 3 lines
The same risk applies to
__rte_aligned(), but with lower probability.so that's the long winded story of why they are both expanded empty for now for msvc. but when the time comes i want to submit patch series that focus on each specifically to generate robust discussion.
Quoted 5 lines
Sounds like the right path to take.
Now, I'm thinking ahead here...
We should be prepared to accept a major ABI/API break at one point in time, to replace our home-grown macros with C11 standard solutions and to fully support MSVC. This is not happening anytime soon, but the Techboard should acknowledge that this is going to happen (with an unspecified release), so it can be formally announced. The sooner it is announced, the more time developers will have to prepare for it.
so, just to avoid any confusion i want to make it clear that i am not planning to submit changes that would change abi as a part of supporting msvc (aside from changing to standard atomics which we agreed on).
in general there are some cleanups we could make in the area of code maintainability and portability and we may want to discuss the advantages or disadvantages of making those changes. but i think those changes are a topic unrelated to windows or msvc specifically.
Quoted 6 lines
All the details do not need to be known at the time of the announcement; they can be added along the way, based on the discussions from your future patches.
Quoted 2 lines
ty
RE: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 84 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Saturday, 15 April 2023 22.52Quoted 8 lines · Morten Brørup
Quoted 8 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Friday, 14 April 2023 19.02Quoted 4 lines · Morten Brørup
Quoted 4 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Thursday, 13 April 2023 23.26For now expand a lot of common rte macros empty. The catch here
is
Quoted 2 lines
Quoted 2 lines
we
Quoted 1 line
Quoted 1 line
need to test that most of the macros do what they should but at
the
Quoted 2 lines
Quoted 2 lines
same
Quoted 1 line
Quoted 1 line
time they are blocking work needed to bootstrap of the unit
tests.
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
Later we will return and provide (where possible) expansions
that
Quoted 19 lines
Quoted 6 lines
work
Quoted 1 line
Quoted 1 line
correctly for msvc and where not possible provide some alternate
macros
Quoted 3 lines
Quoted 3 lines
to achieve the same outcome.
Signed-off-by Tyler Retzlaff <[email protected]>[...]
Quoted 10 lines
Quoted 10 lines
lib/eal/include/rte_common.h line 72
Quoted 8 lines
/**
* Force alignment
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_aligned (a) __attribute__((__aligned__(a))) +#else +#define __rte_aligned (a) +#endif It should be reviewed that
__rte_aligned()is only used forQuoted 4 lines
Quoted 4 lines
optimization purposes, and is not required for DPDK to function properly.
so to expand on what i have in mind (and explain why i leave it
expanded
Quoted 6 lines
Quoted 6 lines
empty for now)
while msvc has a
__declspecfor align there is a mismatch between where gcc and msvc want it placed to control alignment of objects.msvc support won't be functional in 23.07 because of atomics. so
once
Quoted 1 line
Quoted 1 line
we reach the 23.11 cycle (where we can merge c11 changes) it means
we
Quoted 4 lines
Quoted 2 lines
can also use standard
_Alignaswhich can accomplish the same thing but portably.That (C11 standard
_Alignas) should be the roadmap for solving thealignment requirements.
Quoted 2 lines
This should be a general principle for DPDK... if the C standard
offers something, don't reinvent our own. And as a consequence of the upgrade to C11, we should deprecate all our own now-obsolete substitutes for these.
Quoted 3 lines
Quoted 3 lines
full disclosure the catch is i still have to properly locate the
<thing>
Quoted 1 line
Quoted 1 line
that does the alignment and some small questions about the expansion
and
Quoted 6 lines
Quoted 6 lines
use of the existing macro.
on the subject of DPDK requiring proper alignment, you're right it is generally for performance but also for pre-c11 atomics.
one question i have been asking myself is would the community see
value
Quoted 1 line
Quoted 1 line
in more compile time assertions / testing of the size and alignment
of
Quoted 4 lines
Quoted 3 lines
structures and offset of structure fields? we have a few key
RTE_BUILD_BUG_ON()assertions but i've discovered they don't offer comprehensive protection.
Quoted 5 lines
Quoted 1 line
Absolutely. Catching bugs at build time is much better than any
alternative!
that's handy feedback. i am now encouraged to include more compile time checks in advance of or along with changes related to structure abi.
Sounds good.
Disclaimer: "Absolutely" was my personal response. But I seriously doubt that anyone in the DPDK community would object to more build time checks. Stability and code quality carries a lot of weight in DPDK community discussions.
With that said, please expect that maintainers might want you to split your patches, so the additional checks are separated from the MSVC changes.
Quoted 4 lines
follow on question, once we do get to use c11 would something like
_Static_assertbe preferable overRTE_BUILD_BUG_ON? structures sensitive to layout could be co-located with the asserts right at the point of definition. or is there something extraRTE_BUILD_BUG_ONgives us?
People may have different opinions on RTE_BUILD_BUG_ON vs. _Static_assert or static_assert.
Personally, I prefer static_assert/_Static_assert. It also has the advantage that it can be used in the global scope, directly following the structure definitions (like you mention), whereas RTE_BUILD_BUG_ON must be inside a code block (which can probably be worked around by making a dummy static inline function only containing the RTE_BUILD_BUG_ON).
And in the spirit of my proposal of not using home-grown macros as alternatives to what the C standard provides, I think we should deprecate and get rid of RTE_BUILD_BUG_ON in favor of static_assert/_Static_assert introduced by the C11 standard. (My personal opinion, no such principle decision has been made!)
If we want to keep RTE_BUILD_BUG_ON for some reason, we could change its implementation to use static_assert/_Static_assert instead of creating an invalid pointer to make the compilation fail.
Quoted 81 lines
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
lib/eal/include/rte_common.h line 91
Quoted 10 lines
/**
* Force a structure to be packed
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif Similar comment as for
__rte_aligned(); however, I consider itmore
Quoted 1 line
Quoted 1 line
likely that structure packing is a functional requirement, and not
just
Quoted 2 lines
Quoted 2 lines
used for optimization. Based on my experience, it may be used for packing network structures; perhaps not in DPDK itself but maybe in
DPDK
Quoted 3 lines
Quoted 3 lines
applications.
so interestingly i've discovered this is kind of a mess and as you
note
Quoted 3 lines
Quoted 3 lines
some places we can't just "fix" it for abi compatibility reasons.
in some instances the packing is being applied to structures where
it is
Quoted 1 line
Quoted 1 line
essentially a noop. i.e. natural alignment gets you the same thing
so it
Quoted 3 lines
Quoted 3 lines
is superfluous.
in some instances the packing is being applied to structures that
are
Quoted 1 line
Quoted 1 line
private and it appears to be completely unnecessary e.g. some
structure
Quoted 1 line
Quoted 1 line
that isn't nested into something else and
sizeof()oroffsetof()fields
Quoted 3 lines
Quoted 3 lines
don't matter in the context of their use.
in some instances it is completely necessary usually when type
punning
Quoted 3 lines
Quoted 3 lines
buffers containing network framing etc...
unfortunately the standard doesn't offer me an out here as there is
an
Quoted 3 lines
Quoted 3 lines
issue of placement of the pragma/attributes that do the packing.
for places it isn't needed it, whatever i just expand empty. for
places
Quoted 2 lines
Quoted 2 lines
it is superfluous again because msvc has no stable abi (we're not established yet) again i just expand empty. finally for the places
where
Quoted 1 line
Quoted 1 line
it is needed i'll probably need to expand conditionally but i think
the
Quoted 3 lines
Quoted 1 line
instances are far fewer than current use.
Optimally, we will have a common macro (or other solution) to support
both GCC/CLANG and MSVC to replace or supplement
__rte_packed. However, the cost of this may be an API break if we replace__rte_packed.Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
The same risk applies to
__rte_aligned(), but with lowerprobability.
Quoted 2 lines
Quoted 2 lines
so that's the long winded story of why they are both expanded empty
for
Quoted 1 line
Quoted 1 line
now for msvc. but when the time comes i want to submit patch series
that
Quoted 7 lines
Quoted 1 line
focus on each specifically to generate robust discussion.
Sounds like the right path to take.
Now, I'm thinking ahead here...
We should be prepared to accept a major ABI/API break at one point in
time, to replace our home-grown macros with C11 standard solutions and to fully support MSVC. This is not happening anytime soon, but the Techboard should acknowledge that this is going to happen (with an unspecified release), so it can be formally announced. The sooner it is announced, the more time developers will have to prepare for it.
Quoted 3 lines
so, just to avoid any confusion i want to make it clear that i am not planning to submit changes that would change abi as a part of supporting msvc (aside from changing to standard atomics which we agreed on).
Thank you for clarifying.
Quoted 5 lines
in general there are some cleanups we could make in the area of code maintainability and portability and we may want to discuss the advantages or disadvantages of making those changes. but i think those changes are a topic unrelated to windows or msvc specifically.
This was the point I was trying to make, when I proposed accepting a major ABI/API break. Sorry about my unclear wording.
If we collect a wish list of breaking changes, I would personally prefer a "big bang" major ABI/API break, rather than a series of incremental API/ABI breaks over multiple DPDK release. In this regard, we could mix both changes driven by the migration to pure C11 (e.g. getting rid of now-obsolete macros, such as RTE_BUILD_BUG_ON, and compiler intrinsics, such as __rte_aligned) and MSVC portability changes (e.g. an improved macro to support structure packing).
Quoted 9 lines
Quoted 3 lines
All the details do not need to be known at the time of the
announcement; they can be added along the way, based on the discussions from your future patches.
Quoted 3 lines
Quoted 3 lines
ty
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 8 lines · On Sun, 16 Apr 2023 00:41:54 +0200 Morten Brørup <[email protected]>…
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
lib/eal/include/rte_common.h line 91
Quoted 8 lines
/**
* Force a structure to be packed
*/lib/eal/include/rte_common.h +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endif
Could there be cases this gets used for protocol headers or interacting with HW memory map, And if not packed then the code will not function correctly?
Re: [PATCH v5 11/14] eal: expand most macros to empty when using MSVC
Quoted 14 lines · Stephen Hemminger
Quoted 8 lines · On Sun, 16 Apr 2023 00:41:54 +0200 Morten Brørup <[email protected]>…
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Review
Quoted 8 lines
/**
* Force a structure to be packed
*/(quoted diff) +4
-0+#ifndef RTE_TOOLCHAIN_MSVC #define __rte_packed __attribute__((__packed__)) +#else +#define __rte_packed +#endifCould there be cases this gets used for protocol headers or interacting with HW memory map, And if not packed then the code will not function correctly?
yes, that's one of the valid / correct use cases and it can't be avoided if the structs are nested in recursively composed layout.
there are a few instances where we don't need compiler generated static-stride. that is we don't need to force packing to get sizeof(T) == offsetof(T.lastfield) + sizeof(T.lastfield).
anyway, this is more of an evaluate on a case by case basis for candidates that aren't needed.
ty
PATCH v5 12/14 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -83,6 +83,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -279,6 +281,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v5 13/14 telemetry: avoid expanding versioned symbol macros on MSVC
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
PATCH v5 14/14 eal: always define MSVC as little endian
In reply to Tyler RetzlaffThe MSVC compiler does not target big endian platforms so define little endian always.
--- lib/eal/include/generic/rte_byteorder.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/generic/rte_byteorder.h +2 -0
@@ -45,6 +45,8 @@#define RTE_BYTE_ORDER RTE_BIG_ENDIAN#elif defined __LITTLE_ENDIAN__#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN +#elif definedRTE_TOOLCHAIN_MSVC +#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif #if !defined(RTE_BYTE_ORDER )#error Unknown endianness.
Signature · 1 line
1.8.3.1
v6 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v6:
* convert / expand likely/unlikely macros to _Bool type
* expand __extension__ empty it's cleaner to do this for now instead of modifying the whole tree
* provide msvc container_of not based on gcc expression statement extension
* add patch that stops defining typeof (C23 keyword) when building with msvc
v5:
* remove accidental line removal in barrier patch
* update prefetch patch to use intrinsics for all toolchains
* remove x86 specific changes for byte swap patch since msvc intrinsics are processor agnostic always use intrinsics from generic include
* expand __rte_packed empty for msvc packing will be addressed in a separate series
v4:
* update rdtsc patch to use gcc intrinsics
* update rtm patch to use gcc intrinsics
* drop patch disable json print formatting, we will utilize series removing VLAs from Bruce
* added patch using prefetch intrinsics for msvc
* added patch using byte swap intrinsics for msvc
* added patch hiding typdefs for msvc using gcc vector extension
* added patch defining MSVC as little endian always
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64
Tyler Retzlaff (15):
eal: use rdtsc intrinsic
eal: use rtm and xtest intrinsics
eal: use barrier intrinsics
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: use prefetch intrinsics
eal: use byte swap intrinsics
eal: typedef cpu flag enum as int
eal: hide GCC extension based alignment markers
eal: hide typedefs based on GCC vector extensions
eal: expand most macros to empty when using MSVC
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: avoid expanding versioned symbol macros on MSVC
eal: always define MSVC as little endian
eal: do not define typeof macro when building with MSVC
config/x86/meson.build | 6 ++++ lib/eal/include/generic/rte_atomic.h | 11 ++++++ lib/eal/include/generic/rte_byteorder.h | 13 +++++++ lib/eal/include/generic/rte_cpuflags.h | 12 ++++--- lib/eal/include/generic/rte_vect.h | 4 +++ lib/eal/include/rte_branch_prediction.h | 8 +++++ lib/eal/include/rte_common.h | 60 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++ lib/eal/x86/include/rte_atomic.h | 8 +++++ lib/eal/x86/include/rte_byteorder.h | 4 +++ lib/eal/x86/include/rte_cycles.h | 14 ++++---- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++--- lib/eal/x86/include/rte_rtm.h | 18 +++------- lib/eal/x86/rte_cpuflags.c | 4 +++ lib/eal/x86/rte_cpuid.h | 7 ++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 +++ lib/eal/x86/rte_power_intrinsics.c | 12 +++++++ lib/telemetry/telemetry_data.c | 16 +++++++++ 19 files changed, 254 insertions(+), 28 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v6 1/15 eal: use rdtsc intrinsic
Inline assembly is not supported for MSVC x64. Convert code to use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
lib/eal/x86/include/rte_cycles.h +8 -6
@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11
@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :
@@ -42,11 +48,7 @@return tsc.tsc_64; }#endif - - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH v6 2/15 eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64. Convert code to use _xend, _xabort and _xtest intrinsics.
--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)
config/x86/meson.build +6 -0
@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]
lib/eal/x86/include/rte_rtm.h +5 -13
@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v6 3/15 eal: use barrier intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 8 insertions(+)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -66,11 +66,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
PATCH v6 4/15 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v6 5/15 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
PATCH v6 6/15 eal: use prefetch intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _mm_prefetch and _mm_cldemote intrinsics.
--- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
lib/eal/x86/include/rte_prefetch.h +21 -4
@@ -9,30 +9,38 @@extern "C" {#endif +#include <emmintrin.h> +#include <rte_compat.h> #include <rte_common.h> #include "generic/rte_prefetch.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +static inline void rte_prefetch0 (const volatile void *p) { - asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T0); }static inline void rte_prefetch1 (const volatile void *p) { - asmvolatile ("prefetcht1 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T1); }static inline void rte_prefetch2 (const volatile void *p) { - asmvolatile ("prefetcht2 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T2); }static inline void rte_prefetch_non_temporal (const volatile void *p) { - asmvolatile ("prefetchnta %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_NTA); } +#pragma GCC diagnostic pop + +#ifndef RTE_TOOLCHAIN_MSVC /* * We use raw byte codes for now as only the newest compiler * versions support this instruction natively.
@@ -43,6 +51,15 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v6 7/15 eal: use byte swap intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand use _byteswap_u{ushort,ulong,uint64} intrinsics instead.
--- lib/eal/include/generic/rte_byteorder.h | 11 +++++++++++ lib/eal/x86/include/rte_byteorder.h | 4 ++++ 2 files changed, 15 insertions(+)
lib/eal/include/generic/rte_byteorder.h +11 -0
@@ -234,6 +234,7 @@#endif /* __DOXYGEN__ */ #ifdef RTE_FORCE_INTRINSICS +#ifndef RTE_TOOLCHAIN_MSVC #if __GNUC__ >4 || (__GNUC__ ==4 && __GNUC_MINOR__ >=8 )#define rte_bswap16 (x) __builtin_bswap16(x)#endif
@@ -241,6 +242,16 @@#define rte_bswap32 (x) __builtin_bswap32(x)#define rte_bswap64 (x) __builtin_bswap64(x) +#else +/* +* note: we may want to #pragma intrsinsic(_byteswap_u{short,long,uint64}) +*/ +#define rte_bswap16 (x) _byteswap_ushort(x) + +#define rte_bswap32 (x) _byteswap_ulong(x) + +#define rte_bswap64 (x) _byteswap_uint64(x) +#endif #endif
lib/eal/x86/include/rte_byteorder.h +4 -0
@@ -18,6 +18,7 @@#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif +#ifndef RTE_TOOLCHAIN_MSVC /* * An architecture-optimized byte swap for a 16-bit value. *
@@ -69,6 +70,7 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x) rte_arch_bswap16(x)))#endif #endif +#endif #define rte_cpu_to_le_16 (x) (x)#define rte_cpu_to_le_32 (x) (x)
@@ -86,11 +88,13 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x)#define rte_be_to_cpu_32 (x) rte_bswap32(x)#define rte_be_to_cpu_64 (x) rte_bswap64(x) +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 #include "rte_byteorder_32.h" #else #include "rte_byteorder_64.h" #endif +#endif #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v6 8/15 eal: typedef cpu flag enum as int
In reply to Tyler RetzlaffForward declaration of a enum is a non-standard extension and is not supported by MSVC. Use an int instead.
Abstract the use of the int/enum rte_cpu_flag_t in function parameter lists by re-typdefing the enum rte_cpu_flag_t to the rte_cpu_flag_t identifier.
Remove the use of __extension__ on function prototypes where rte_cpu_flag_t appeared in parameter lists, it is sufficient to have the conditionally compiled __extension__ at the non-standard forward declaration site.
--- lib/eal/include/generic/rte_cpuflags.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
lib/eal/include/generic/rte_cpuflags.h +7 -5
@@ -44,8 +44,12 @@ struct rte_cpu_intrinsics {/** * Enumeration of all CPU features supported */ +#ifndef RTE_TOOLCHAIN_MSVC __extension__ -enum rte_cpu_flag_t; +typedef enum rte_cpu_flag_t rte_cpu_flag_t ; +#else +typedef int rte_cpu_flag_t ; +#endif /** * Get name of CPU flag
@@ -56,9 +60,8 @@ struct rte_cpu_intrinsics {* flag name * NULL if flag ID is invalid */ -__extension__const char * -rte_cpu_get_flag_name (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_name (rte_cpu_flag_t feature);/** * Function for checking a CPU flag availability
@@ -70,9 +73,8 @@ struct rte_cpu_intrinsics {* 0 if flag is not available * -ENOENT if flag is invalid */ -__extension__int -rte_cpu_get_flag_enabled (enum rte_cpu_flag_t feature); +rte_cpu_get_flag_enabled (rte_cpu_flag_t feature);/** * This function checks that the currently used CPU supports the CPU features
Signature · 1 line
1.8.3.1
PATCH v6 9/15 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v6 10/15 eal: hide typedefs based on GCC vector extensions
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs based on GCC vector extensions.
--- lib/eal/include/generic/rte_vect.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/generic/rte_vect.h +4 -0
@@ -17,6 +17,8 @@#include <rte_compat.h> +#ifndef RTE_TOOLCHAIN_MSVC +/* Unsigned vector types */ /**
@@ -186,6 +188,8 @@*/ typedef int64_t rte_v256s64_t __attribute__((vector_size (32 ),aligned (32 ))); +#endif +/** * The max SIMD bitwidth value to limit vector path selection. */
Signature · 1 line
1.8.3.1
PATCH v6 11/15 eal: expand most macros to empty when using MSVC
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 +++++ lib/eal/include/rte_common.h | 54 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++ 3 files changed, 82 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x)) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x)) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +54 -0
144 lines not on this page · raw message
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
PATCH v6 12/15 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -83,6 +83,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -279,6 +281,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v6 13/15 telemetry: avoid expanding versioned symbol macros on MSVC
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
PATCH v6 14/15 eal: always define MSVC as little endian
In reply to Tyler RetzlaffThe MSVC compiler does not target big endian platforms so define little endian always.
--- lib/eal/include/generic/rte_byteorder.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/generic/rte_byteorder.h +2 -0
@@ -45,6 +45,8 @@#define RTE_BYTE_ORDER RTE_BIG_ENDIAN#elif defined __LITTLE_ENDIAN__#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN +#elif definedRTE_TOOLCHAIN_MSVC +#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif #if !defined(RTE_BYTE_ORDER )#error Unknown endianness.
Signature · 1 line
1.8.3.1
PATCH v6 15/15 eal: do not define typeof macro when building with MSVC
In reply to Tyler RetzlaffWhen building with MSVC do not assume typeof is a macro and don't define a typeof macro that conflicts with C23 typeof keyword.
--- lib/eal/include/rte_common.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/rte_common.h +2 -0
@@ -24,9 +24,11 @@/* OS specific include */ #include <rte_os.h> +#ifndef RTE_TOOLCHAIN_MSVC #ifndef typeof#define typeof __typeof__#endif +#endif #ifndef __cplusplus#ifndef asm
Signature · 1 line
1.8.3.1
Quoted 11 lines
From: Tyler Retzlaff [mailto:[email protected]]
Sent: Saturday, 15 April 2023 03.16In accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that_doesnot_require C99/C11 meaning it can be integrated now.This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Quoted 8 lines
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v7 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v7:
* remove patch typedef of rte_cpuflags_t as an int. for now we will just allow warning to be emitted to avoid adding conditional compilation
v6:
* convert / expand likely/unlikely macros to _Bool type
* expand __extension__ empty it's cleaner to do this for now instead of modifying the whole tree
* provide msvc container_of not based on gcc expression statement extension
* add patch that stops defining typeof (C23 keyword) when building with msvc
v5:
* remove accidental line removal in barrier patch
* update prefetch patch to use intrinsics for all toolchains
* remove x86 specific changes for byte swap patch since msvc intrinsics are processor agnostic always use intrinsics from generic include
* expand __rte_packed empty for msvc packing will be addressed in a separate series
v4:
* update rdtsc patch to use gcc intrinsics
* update rtm patch to use gcc intrinsics
* drop patch disable json print formatting, we will utilize series removing VLAs from Bruce
* added patch using prefetch intrinsics for msvc
* added patch using byte swap intrinsics for msvc
* added patch hiding typdefs for msvc using gcc vector extension
* added patch defining MSVC as little endian always
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64
Tyler Retzlaff (14):
eal: use rdtsc intrinsic
eal: use rtm and xtest intrinsics
eal: use barrier intrinsics
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: use prefetch intrinsics
eal: use byte swap intrinsics
eal: hide GCC extension based alignment markers
eal: hide typedefs based on GCC vector extensions
eal: expand most macros to empty when using MSVC
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: avoid expanding versioned symbol macros on MSVC
eal: always define MSVC as little endian
eal: do not define typeof macro when building with MSVC
config/x86/meson.build | 6 ++++ lib/eal/include/generic/rte_atomic.h | 11 ++++++ lib/eal/include/generic/rte_byteorder.h | 13 +++++++ lib/eal/include/generic/rte_vect.h | 4 +++ lib/eal/include/rte_branch_prediction.h | 8 +++++ lib/eal/include/rte_common.h | 60 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++ lib/eal/x86/include/rte_atomic.h | 8 +++++ lib/eal/x86/include/rte_byteorder.h | 4 +++ lib/eal/x86/include/rte_cycles.h | 14 ++++---- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++--- lib/eal/x86/include/rte_rtm.h | 18 +++------- lib/eal/x86/rte_cpuflags.c | 4 +++ lib/eal/x86/rte_cpuid.h | 7 ++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 +++ lib/eal/x86/rte_power_intrinsics.c | 12 +++++++ lib/telemetry/telemetry_data.c | 16 +++++++++ 18 files changed, 247 insertions(+), 23 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v7 1/14 eal: use rdtsc intrinsic
Inline assembly is not supported for MSVC x64. Convert code to use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
lib/eal/x86/include/rte_cycles.h +8 -6
@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11
@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :
@@ -42,11 +48,7 @@return tsc.tsc_64; }#endif - - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH v7 2/14 eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64. Convert code to use _xend, _xabort and _xtest intrinsics.
--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)
config/x86/meson.build +6 -0
@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]
lib/eal/x86/include/rte_rtm.h +5 -13
@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v7 3/14 eal: use barrier intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 8 insertions(+)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -66,11 +66,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
PATCH v7 4/14 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v7 5/14 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
Re: [PATCH v7 05/14] eal: use umonitor umwait and tpause intrinsics
Quoted 59 lines
Inline assembly is not supported for MSVC x64 instead use
_umonitor,_umwaitand_tpauseintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>Acked-by Morten Brørup <[email protected]>--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)lib/eal/x86/rte_power_intrinsics.c +12
-0@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#else +_umonitor (pmc->addr); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_umwait (tsc_l, tsc_h); +#endif end:/* erase sleep address */ @@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#ifndef RTE_TOOLCHAIN_MSVC asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#else +_tpause (tsc_l, tsc_h); +#endif return 0 ; }Signature · 1 line
1.8.3.1
AFAIK, with GCC (and CLANG?) these instrincts are controlled by __WAITPKG__ macro.
So might be it is possible to have sort of 'unite' code:
#if defined (RTE_TOOLCHAIN_MSVC) || defined (__WAITPKG__)
<use insrinct>
#else
<use inline asm>
#endif
Apart from that, LGTM
PATCH v7 6/14 eal: use prefetch intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _mm_prefetch and _mm_cldemote intrinsics.
--- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
lib/eal/x86/include/rte_prefetch.h +21 -4
@@ -9,30 +9,38 @@extern "C" {#endif +#include <emmintrin.h> +#include <rte_compat.h> #include <rte_common.h> #include "generic/rte_prefetch.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +static inline void rte_prefetch0 (const volatile void *p) { - asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T0); }static inline void rte_prefetch1 (const volatile void *p) { - asmvolatile ("prefetcht1 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T1); }static inline void rte_prefetch2 (const volatile void *p) { - asmvolatile ("prefetcht2 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T2); }static inline void rte_prefetch_non_temporal (const volatile void *p) { - asmvolatile ("prefetchnta %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_NTA); } +#pragma GCC diagnostic pop + +#ifndef RTE_TOOLCHAIN_MSVC /* * We use raw byte codes for now as only the newest compiler * versions support this instruction natively.
@@ -43,6 +51,15 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
Re: [PATCH v7 06/14] eal: use prefetch intrinsics
Quoted 64 lines
nline assembly is not supported for MSVC x64 instead use
_mm_prefetchand_mm_cldemoteintrinsics.Signed-off-by Tyler Retzlaff <[email protected]>Acked-by Bruce Richardson <[email protected]>Acked-by Morten Brørup <[email protected]>--- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)lib/eal/x86/include/rte_prefetch.h +14
-4@@ -9,30 +9,38 @@extern "C" {#endif +#include <emmintrin.h> +#include <rte_compat.h> #include <rte_common.h> #include "generic/rte_prefetch.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +static inline void rte_prefetch0 (const volatile void *p) { - asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T0); }static inline void rte_prefetch1 (const volatile void *p) { - asmvolatile ("prefetcht1 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T1); }static inline void rte_prefetch2 (const volatile void *p) { - asmvolatile ("prefetcht2 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T2); }static inline void rte_prefetch_non_temporal (const volatile void *p) { - asmvolatile ("prefetchnta %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_NTA); } +#pragma GCC diagnostic pop + +#ifndef RTE_TOOLCHAIN_MSVC /* * We use raw byte codes for now as only the newest compiler * versions support this instruction natively. @@ -43,6 +51,15 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +__rte_experimental
lib/eal/x86/include/rte_prefetch.h static inline void rte_prefetch_non_temporal(const volatile void *p) · line 65
Quoted 10 lines
lib/eal/x86/include/rte_prefetch.h +7
-0+static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Quoted 1 line
1.8.3.1
PATCH v7 7/14 eal: use byte swap intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand use _byteswap_u{ushort,ulong,uint64} intrinsics instead.
--- lib/eal/include/generic/rte_byteorder.h | 11 +++++++++++ lib/eal/x86/include/rte_byteorder.h | 4 ++++ 2 files changed, 15 insertions(+)
lib/eal/include/generic/rte_byteorder.h +11 -0
@@ -234,6 +234,7 @@#endif /* __DOXYGEN__ */ #ifdef RTE_FORCE_INTRINSICS +#ifndef RTE_TOOLCHAIN_MSVC #if __GNUC__ >4 || (__GNUC__ ==4 && __GNUC_MINOR__ >=8 )#define rte_bswap16 (x) __builtin_bswap16(x)#endif
@@ -241,6 +242,16 @@#define rte_bswap32 (x) __builtin_bswap32(x)#define rte_bswap64 (x) __builtin_bswap64(x) +#else +/* +* note: we may want to #pragma intrsinsic(_byteswap_u{short,long,uint64}) +*/ +#define rte_bswap16 (x) _byteswap_ushort(x) + +#define rte_bswap32 (x) _byteswap_ulong(x) + +#define rte_bswap64 (x) _byteswap_uint64(x) +#endif #endif
lib/eal/x86/include/rte_byteorder.h +4 -0
@@ -18,6 +18,7 @@#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif +#ifndef RTE_TOOLCHAIN_MSVC /* * An architecture-optimized byte swap for a 16-bit value. *
@@ -69,6 +70,7 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x) rte_arch_bswap16(x)))#endif #endif +#endif #define rte_cpu_to_le_16 (x) (x)#define rte_cpu_to_le_32 (x) (x)
@@ -86,11 +88,13 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x)#define rte_be_to_cpu_32 (x) rte_bswap32(x)#define rte_be_to_cpu_64 (x) rte_bswap64(x) +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 #include "rte_byteorder_32.h" #else #include "rte_byteorder_64.h" #endif +#endif #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v7 8/14 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v7 9/14 eal: hide typedefs based on GCC vector extensions
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs based on GCC vector extensions.
--- lib/eal/include/generic/rte_vect.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/generic/rte_vect.h +4 -0
@@ -17,6 +17,8 @@#include <rte_compat.h> +#ifndef RTE_TOOLCHAIN_MSVC +/* Unsigned vector types */ /**
@@ -186,6 +188,8 @@*/ typedef int64_t rte_v256s64_t __attribute__((vector_size (32 ),aligned (32 ))); +#endif +/** * The max SIMD bitwidth value to limit vector path selection. */
Signature · 1 line
1.8.3.1
PATCH v7 10/14 eal: expand most macros to empty when using MSVC
In reply to Tyler RetzlaffFor now expand a lot of common rte macros empty. The catch here is we need to test that most of the macros do what they should but at the same time they are blocking work needed to bootstrap of the unit tests.
Later we will return and provide (where possible) expansions that work correctly for msvc and where not possible provide some alternate macros to achieve the same outcome.
--- lib/eal/include/rte_branch_prediction.h | 8 +++++ lib/eal/include/rte_common.h | 54 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 ++++++++++++ 3 files changed, 82 insertions(+)
lib/eal/include/rte_branch_prediction.h +8 -0
@@ -25,7 +25,11 @@* */ #ifndef likely +#ifndef RTE_TOOLCHAIN_MSVC #define likely (x) __builtin_expect(!!(x), 1) +#else +#define likely (x) (!!(x)) +#endif #endif /* likely */ /**
@@ -39,7 +43,11 @@* */ #ifndef unlikely +#ifndef RTE_TOOLCHAIN_MSVC #define unlikely (x) __builtin_expect(!!(x), 0) +#else +#define unlikely (x) (!!(x)) +#endif #endif /* unlikely */ #ifdef __cplusplus
lib/eal/include/rte_common.h +54 -0
147 lines not on this page · raw message
lib/eal/include/rte_compat.h +20 -0
@@ -12,14 +12,22 @@#ifndef ALLOW_EXPERIMENTAL_API +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((deprecated("Symbol is not yet part of stable ABI"), \ section(".text.experimental"))) +#else +#define __rte_experimental +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_experimental \ __attribute__((section(".text.experimental"))) +#else +#define __rte_experimental +#endif #endif
@@ -30,23 +38,35 @@#if !definedALLOW_INTERNAL_API &&__has_attribute (error)/* For GCC */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((error("Symbol is not public ABI"), \ section(".text.internal"))) +#else +#define __rte_internal +#endif #elif !definedALLOW_INTERNAL_API &&__has_attribute (diagnose_if)/* For clang */ +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ _Pragma("GCC diagnostic push") \ _Pragma("GCC diagnostic ignored \"-Wgcc-compat\"") \ __attribute__((diagnose_if(1, "Symbol is not public ABI", "error"), \ section(".text.internal"))) \ _Pragma("GCC diagnostic pop") +#else +#define __rte_internal +#endif #else +#ifndef RTE_TOOLCHAIN_MSVC #define __rte_internal \ __attribute__((section(".text.internal"))) +#else +#define __rte_internal +#endif #endif
Signature · 1 line
1.8.3.1
PATCH v7 11/14 eal: exclude exposure of rte atomic APIs for MSVC builds
In reply to Tyler RetzlaffIt's discouraged to use rte_atomics APIs instead standard APIs should be used from C11. Since MSVC is a new toolchain/platform combination block visibility of the rte_atomic APIs from day 1.
--- lib/eal/include/generic/rte_atomic.h | 7 +++++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 11 insertions(+)
lib/eal/include/generic/rte_atomic.h +7 -0
@@ -131,6 +131,8 @@/*------------------------- 16 bit atomic operations -------------------------*/ +#ifndef RTE_TOOLCHAIN_MSVC +/** * Atomic compare and set. *
@@ -1038,8 +1040,11 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v) }#endif +#endif +/*------------------------ 128 bit atomic operations -------------------------*/ +/** * 128-bit integer structure. */
@@ -1049,8 +1054,10 @@ static inline void rte_atomic64_clear(rte_atomic64_t *v)union {uint64_t val[2 ];#ifdef RTE_ARCH_64 +#ifndef RTE_TOOLCHAIN_MSVC __extension____int128 int128;#endif +#endif }; } __rte_aligned(16) rte_int128_t;
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -83,6 +83,8 @@#define rte_io_rmb () rte_compiler_barrier() +#ifndef RTE_TOOLCHAIN_MSVC +/** * Synchronization fence between threads based on the specified memory order. *
@@ -279,6 +281,8 @@ static inline int rte_atomic32_dec_and_test(rte_atomic32_t *v)#include "rte_atomic_64.h" #endif +#endif + #ifdef __cplusplus }#endif
Signature · 1 line
1.8.3.1
PATCH v7 12/14 telemetry: avoid expanding versioned symbol macros on MSVC
In reply to Tyler RetzlaffWindows does not support versioned symbols. Fortunately Windows also doesn't have an exported stable ABI.
Export rte_tel_data_add_array_int -> rte_tel_data_add_array_int_24 and rte_tel_data_add_dict_int -> rte_tel_data_add_dict_int_v24 functions.
Windows does have a way to achieve similar versioning for symbols but it is not a simple #define so it will be done as a work package later.
--- lib/telemetry/telemetry_data.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
lib/telemetry/telemetry_data.c +16 -0
@@ -82,8 +82,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_array_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_array_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_array_int(struct rte_tel_data *d, int64_t x), rte_tel_data_add_array_int_v24); +#else +int +rte_tel_data_add_array_int (struct rte_tel_data *d,int64_t x) +{ +return rte_tel_data_add_array_int_v24 (d, x); +} +#endif int rte_tel_data_add_array_uint (struct rte_tel_data *d,uint64_t x)
@@ -220,8 +228,16 @@/* mark the v23 function as the older version, and v24 as the default version */ VERSION_SYMBOL (rte_tel_data_add_dict_int, _v23,23 );BIND_DEFAULT_SYMBOL (rte_tel_data_add_dict_int, _v24,24 ); +#ifndef RTE_TOOLCHAIN_MSVC MAP_STATIC_SYMBOL(int rte_tel_data_add_dict_int(struct rte_tel_data *d, const char *name, int64_t val), rte_tel_data_add_dict_int_v24); +#else +int +rte_tel_data_add_dict_int (struct rte_tel_data *d,const char *name,int64_t val) +{ +return rte_tel_data_add_dict_int_v24 (d, name, val); +} +#endif int rte_tel_data_add_dict_uint(struct rte_tel_data *d,
Signature · 1 line
1.8.3.1
PATCH v7 13/14 eal: always define MSVC as little endian
In reply to Tyler RetzlaffThe MSVC compiler does not target big endian platforms so define little endian always.
--- lib/eal/include/generic/rte_byteorder.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/generic/rte_byteorder.h +2 -0
@@ -45,6 +45,8 @@#define RTE_BYTE_ORDER RTE_BIG_ENDIAN#elif defined __LITTLE_ENDIAN__#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN +#elif definedRTE_TOOLCHAIN_MSVC +#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif #if !defined(RTE_BYTE_ORDER )#error Unknown endianness.
Signature · 1 line
1.8.3.1
PATCH v7 14/14 eal: do not define typeof macro when building with MSVC
In reply to Tyler RetzlaffWhen building with MSVC do not assume typeof is a macro and don't define a typeof macro that conflicts with C23 typeof keyword.
--- lib/eal/include/rte_common.h | 2 ++ 1 file changed, 2 insertions(+)
lib/eal/include/rte_common.h +2 -0
@@ -24,9 +24,11 @@/* OS specific include */ #include <rte_os.h> +#ifndef RTE_TOOLCHAIN_MSVC #ifndef typeof#define typeof __typeof__#endif +#endif #ifndef __cplusplus#ifndef asm
Signature · 1 line
1.8.3.1
v8 cover msvc integration changes
In reply to Tyler RetzlaffIn accordance with draft plan
http://mails.dpdk.org/archives/web/2023-February/002023.html
introduces conditionally compiled code to enable building with MSVC that _does not_ require C99/C11 meaning it can be integrated now.
This series covers minimal changes for item #2 in draft plan for EAL dependencies kvargs, telemetry and consumed EAL public headers.
Note if any patch in the series requires in-depth discussion I'll detach it from this series for separate submission & more focused discussion so it doesn't block the entire series.
Note other "common" intrinsics were investigated for viability but were not adopted either because they were not available on older versions of gcc or because they generate different code for msvc vs gcc.
v8:
* use waitpkg intrinsics if __WAITPKG__ is defined by the compiler
v7:
* remove patch typedef of rte_cpuflags_t as an int. for now we will just allow warning to be emitted to avoid adding conditional compilation
v6:
* convert / expand likely/unlikely macros to _Bool type
* expand __extension__ empty it's cleaner to do this for now instead of modifying the whole tree
* provide msvc container_of not based on gcc expression statement extension
* add patch that stops defining typeof (C23 keyword) when building with msvc
v5:
* remove accidental line removal in barrier patch
* update prefetch patch to use intrinsics for all toolchains
* remove x86 specific changes for byte swap patch since msvc intrinsics are processor agnostic always use intrinsics from generic include
* expand __rte_packed empty for msvc packing will be addressed in a separate series
v4:
* update rdtsc patch to use gcc intrinsics
* update rtm patch to use gcc intrinsics
* drop patch disable json print formatting, we will utilize series removing VLAs from Bruce
* added patch using prefetch intrinsics for msvc
* added patch using byte swap intrinsics for msvc
* added patch hiding typdefs for msvc using gcc vector extension
* added patch defining MSVC as little endian always
v3:
* v3 does not group together conditional blocks when experimented with it didn't reduce conditionals enough to make it worth while. once msvc tests are at a running point i suggest a narrow targeted discussion about code organization without blocking this series
* v3 does not attempt to refactor to use intrinsics for non-msvc compilers. again this should be done as a separate follow-up series later if desired
* fix expansion of likely and unlikely macros
* remove unnecessary define for rte_smp_{r,w}mb it is sufficient for these to be compiler barriers on x86
* add a new patch to use __cpuid and __cpuidex intrinsics when building with msvc
* add a new patch to use _umonitor, _umwait and _tpause intrinsics when building with msvc
v2:
* use _mm_{l,s,m}fence intrinsics for rte_smp_{r,w,}mb macros are intended to be memory barriers not compiler barriers on x86_64
Tyler Retzlaff (14):
eal: use rdtsc intrinsic
eal: use rtm and xtest intrinsics
eal: use barrier intrinsics
eal: use cpuid and cpuidex intrinsics
eal: use umonitor umwait and tpause intrinsics
eal: use prefetch intrinsics
eal: use byte swap intrinsics
eal: hide GCC extension based alignment markers
eal: hide typedefs based on GCC vector extensions
eal: expand most macros to empty when using MSVC
eal: exclude exposure of rte atomic APIs for MSVC builds
telemetry: avoid expanding versioned symbol macros on MSVC
eal: always define MSVC as little endian
eal: do not define typeof macro when building with MSVC
config/x86/meson.build | 6 ++++ lib/eal/include/generic/rte_atomic.h | 11 ++++++ lib/eal/include/generic/rte_byteorder.h | 13 +++++++ lib/eal/include/generic/rte_vect.h | 4 +++ lib/eal/include/rte_branch_prediction.h | 8 +++++ lib/eal/include/rte_common.h | 60 +++++++++++++++++++++++++++++++++ lib/eal/include/rte_compat.h | 20 +++++++++++ lib/eal/x86/include/rte_atomic.h | 8 +++++ lib/eal/x86/include/rte_byteorder.h | 4 +++ lib/eal/x86/include/rte_cycles.h | 14 ++++---- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++--- lib/eal/x86/include/rte_rtm.h | 18 +++------- lib/eal/x86/rte_cpuflags.c | 4 +++ lib/eal/x86/rte_cpuid.h | 7 ++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 +++ lib/eal/x86/rte_power_intrinsics.c | 12 +++++++ lib/telemetry/telemetry_data.c | 16 +++++++++ 18 files changed, 247 insertions(+), 23 deletions(-)
Signature · 1 line
1.8.3.1
PATCH v8 1/14 eal: use rdtsc intrinsic
Inline assembly is not supported for MSVC x64. Convert code to use __rdtsc intrinsic.
--- lib/eal/x86/include/rte_cycles.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
lib/eal/x86/include/rte_cycles.h +8 -6
@@ -6,6 +6,12 @@ #ifndef _RTE_CYCLES_X86_64_H_ #define _RTE_CYCLES_X86_64_H_ +#ifndef RTE_TOOLCHAIN_MSVC +#include <x86intrin.h> +#else +#include <intrin.h> +#endif + #ifdef __cplusplus extern "C" { #endif
@@ -23,6 +29,7 @@static inline uint64_t rte_rdtsc (void ) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT union { uint64_t tsc_64; RTE_STD_C11
@@ -32,7 +39,6 @@ }; } tsc; -#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT if (unlikely (rte_cycles_vmware_tsc_map)) {/* ecx = 0x10000 corresponds to the physical TSC for VMware */ asm volatile("rdpmc" :
@@ -42,11 +48,7 @@return tsc.tsc_64; }#endif - - asmvolatile ("rdtsc" : -"=a" (tsc.lo_32), -"=d" (tsc.hi_32)); -return tsc.tsc_64; +return __rdtsc (); } static inline uint64_t
Signature · 1 line
1.8.3.1
PATCH v8 2/14 eal: use rtm and xtest intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64. Convert code to use _xend, _xabort and _xtest intrinsics.
--- config/x86/meson.build | 6 ++++++ lib/eal/x86/include/rte_rtm.h | 18 +++++------------- 2 files changed, 11 insertions(+), 13 deletions(-)
config/x86/meson.build +6 -0
@@ -30,6 +30,12 @@ if cc.get_define('__SSE4_2__', args: machine_args) == '' machine_args += '-msse4' endif +# enable restricted transactional memory intrinsics +# https://gcc.gnu.org/onlinedocs/gcc/x86-transactional-memory-intrinsics.html +if cc.get_id() != 'msvc' + machine_args += '-mrtm' +endif + base_flags = ['SSE', 'SSE2', 'SSE3','SSSE3', 'SSE4_1', 'SSE4_2'] foreach f:base_flags compile_time_cpuflags += ['RTE_CPUFLAG_' + f]
lib/eal/x86/include/rte_rtm.h +5 -13
@@ -5,6 +5,7 @@#ifndef _RTE_RTM_H_#define _RTE_RTM_H_ 1 +#include <immintrin.h> /* Official RTM intrinsics interface matching gcc/icc, but works on older gcc compatible compilers and binutils. */
@@ -28,31 +29,22 @@static __rte_always_inline unsigned int rte_xbegin(void) { -unsigned int ret =RTE_XBEGIN_STARTED ; - - asmvolatile (".byte 0xc7,0xf8 ; .long 0" :"+a" (ret) ::"memory" ); -return ret; +return _xbegin (); }static __rte_always_inline void rte_xend(void) { - asmvolatile (".byte 0x0f,0x01,0xd5" :::"memory" ); +_xend (); }/* not an inline function to workaround a clang bug with -O0 */ -#define rte_xabort (status) do { \ - asm volatile(".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory"); \ -} while (0) +#define rte_xabort (status) _xabort(status)static __rte_always_inline int rte_xtest(void) { -unsigned char out; - - asmvolatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : -"=r" (out) ::"memory" ); -return out; +return _xtest (); }#ifdef __cplusplus
Signature · 1 line
1.8.3.1
PATCH v8 3/14 eal: use barrier intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand rte_compiler_barrier as _ReadWriteBarrier and for rte_smp_mb _m_mfence intrinsics.
--- lib/eal/include/generic/rte_atomic.h | 4 ++++ lib/eal/x86/include/rte_atomic.h | 4 ++++ 2 files changed, 8 insertions(+)
lib/eal/include/generic/rte_atomic.h +4 -0
@@ -116,9 +116,13 @@* Guarantees that operation reordering does not occur at compile time * for operations directly before and after the barrier. */ +#ifndef RTE_TOOLCHAIN_MSVC #define rte_compiler_barrier () do { \ asm volatile ("" : : : "memory"); \ } while(0) +#else +#define rte_compiler_barrier () _ReadWriteBarrier() +#endif /** * Synchronization fence between threads based on the specified memory order.
lib/eal/x86/include/rte_atomic.h +4 -0
@@ -66,11 +66,15 @@ static __rte_always_inline voidrte_smp_mb (void ) { +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 asmvolatile ("lock addl $0, -128(%%esp); " :::"memory" );#else asmvolatile ("lock addl $0, -128(%%rsp); " :::"memory" );#endif +#else +_mm_mfence (); +#endif }#define rte_io_mb () rte_mb()
Signature · 1 line
1.8.3.1
PATCH v8 4/14 eal: use cpuid and cpuidex intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use __cpuid and __cpuidex intrinsics.
--- lib/eal/x86/rte_cpuflags.c | 4 ++++ lib/eal/x86/rte_cpuid.h | 7 +++++++ lib/eal/x86/rte_cycles.c | 36 ++++++++++++++++++++++++++++++++++++ lib/eal/x86/rte_hypervisor.c | 4 ++++ 4 files changed, 51 insertions(+)
lib/eal/x86/rte_cpuflags.c +4 -0
@@ -165,9 +165,13 @@ struct feature_entry {if (maxleaf < feat->leaf)return 0 ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid_count (feat->leaf, feat->subleaf, regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuidex (regs, feat->leaf, feat->subleaf); +#endif /* check if the feature is enabled */ return (regs[feat->reg] >> feat->bit) &1 ;
lib/eal/x86/rte_cpuid.h +7 -0
@@ -5,7 +5,9 @@#ifndef RTE_CPUID_H #define RTE_CPUID_H +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#endif enum cpu_register_t { RTE_REG_EAX = 0,
@@ -16,4 +18,9 @@ enum cpu_register_t {typedef uint32_t cpuid_registers_t [4 ]; +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s); +#endif +#endif /* RTE_CPUID_H */
lib/eal/x86/rte_cycles.c +36 -0
@@ -4,7 +4,11 @@#include <fcntl.h> #include <unistd.h> +#ifndef RTE_TOOLCHAIN_MSVC #include <cpuid.h> +#else +#define bit_AVX (1 << 28) +#endif #include "eal_private.h"
@@ -82,9 +86,25 @@return 0 ; } +#ifdef RTE_TOOLCHAIN_MSVC +int +__get_cpuid_max (unsigned int e,unsigned int *s) +{ +uint32_t cpuinfo[4 ]; + +__cpuid (cpuinfo, e); +if (s) + *s = cpuinfo[1 ]; +return cpuinfo[0 ]; +} +#endif +uint64_t get_tsc_freq_arch (void ) { +#ifdef RTE_TOOLCHAIN_MSVC +int cpuinfo[4 ]; +#endif uint64_t tsc_hz =0 ;uint32_t a, b, c, d, maxleaf;uint8_t mult, model;
@@ -97,14 +117,30 @@ maxleaf =__get_cpuid_max (0 ,NULL );if (maxleaf >=0x15 ) { +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x15 , a, b, c, d); +#else +__cpuid (cpuinfo,0x15 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c)return c * (b / a); } +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (0x1 , a, b, c, d); +#else +__cpuid (cpuinfo,0x1 ); + a = cpuinfo[0 ]; + b = cpuinfo[1 ]; + c = cpuinfo[2 ]; + d = cpuinfo[3 ]; +#endif model =rte_cpu_get_model (a);if (check_model_wsm_nhm (model))
lib/eal/x86/rte_hypervisor.c +4 -0
@@ -23,9 +23,13 @@ enum rte_hypervisorif (!rte_cpu_get_flag_enabled (RTE_CPUFLAG_HYPERVISOR ))return RTE_HYPERVISOR_NONE ; +#ifndef RTE_TOOLCHAIN_MSVC __cpuid (HYPERVISOR_INFO_LEAF , regs[RTE_REG_EAX ], regs[RTE_REG_EBX ], regs[RTE_REG_ECX ], regs[RTE_REG_EDX ]); +#else +__cpuid (regs,HYPERVISOR_INFO_LEAF ); +#endif for (reg =1 ; reg <4 ; reg++)memcpy (name + (reg -1 ) *4 , ®s[reg],4 ); name[12 ] ='\0' ;
Signature · 1 line
1.8.3.1
PATCH v8 5/14 eal: use umonitor umwait and tpause intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _umonitor, _umwait and _tpause intrinsics.
--- lib/eal/x86/rte_power_intrinsics.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
lib/eal/x86/rte_power_intrinsics.c +12 -0
@@ -109,9 +109,13 @@*/ /* set address for UMONITOR */ +#if defined(RTE_TOOLCHAIN_MSVC ) || defined(__WAITPKG__) +_umonitor (pmc->addr); +#else asmvolatile (".byte 0xf3, 0x0f, 0xae, 0xf7;" : :"D" (pmc->addr)); +#endif /* now that we've put this address into monitor, we can unlock */ rte_spinlock_unlock (&s->lock);
@@ -123,10 +127,14 @@ goto end;/* execute UMWAIT */ +#if defined(RTE_TOOLCHAIN_MSVC ) || defined(__WAITPKG__) +_umwait (tsc_l, tsc_h); +#else asmvolatile (".byte 0xf2, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#endif end:/* erase sleep address */
@@ -153,10 +161,14 @@return -ENOTSUP ;/* execute TPAUSE */ +#if defined(RTE_TOOLCHAIN_MSVC ) || defined(__WAITPKG__) +_tpause (tsc_l, tsc_h); +#else asmvolatile (".byte 0x66, 0x0f, 0xae, 0xf7;" :/* ignore rflags */ :"D" (0 ),/* enter C0.2 */ "a" (tsc_l),"d" (tsc_h)); +#endif return 0 ; }
Signature · 1 line
1.8.3.1
PATCH v8 6/14 eal: use prefetch intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead use _mm_prefetch and _mm_cldemote intrinsics.
--- lib/eal/x86/include/rte_prefetch.h | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-)
lib/eal/x86/include/rte_prefetch.h +21 -4
@@ -9,30 +9,38 @@extern "C" {#endif +#include <emmintrin.h> +#include <rte_compat.h> #include <rte_common.h> #include "generic/rte_prefetch.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +static inline void rte_prefetch0 (const volatile void *p) { - asmvolatile ("prefetcht0 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T0); }static inline void rte_prefetch1 (const volatile void *p) { - asmvolatile ("prefetcht1 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T1); }static inline void rte_prefetch2 (const volatile void *p) { - asmvolatile ("prefetcht2 %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_T2); }static inline void rte_prefetch_non_temporal (const volatile void *p) { - asmvolatile ("prefetchnta %[p]" : : [p]"m" (*(const volatile char *)p)); +_mm_prefetch ((const void *)p, _MM_HINT_NTA); } +#pragma GCC diagnostic pop + +#ifndef RTE_TOOLCHAIN_MSVC /* * We use raw byte codes for now as only the newest compiler * versions support this instruction natively.
@@ -43,6 +51,15 @@ static inline void rte_prefetch_non_temporal(const volatile void *p) { asmvolatile (".byte 0x0f, 0x1c, 0x06" ::"S" (p)); } +#else +__rte_experimental +static inline void +rte_cldemote (const volatile void *p) +{ +_mm_cldemote (p); +} +#endif + #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v8 7/14 eal: use byte swap intrinsics
In reply to Tyler RetzlaffInline assembly is not supported for MSVC x64 instead expand use _byteswap_u{ushort,ulong,uint64} intrinsics instead.
--- lib/eal/include/generic/rte_byteorder.h | 11 +++++++++++ lib/eal/x86/include/rte_byteorder.h | 4 ++++ 2 files changed, 15 insertions(+)
lib/eal/include/generic/rte_byteorder.h +11 -0
@@ -234,6 +234,7 @@#endif /* __DOXYGEN__ */ #ifdef RTE_FORCE_INTRINSICS +#ifndef RTE_TOOLCHAIN_MSVC #if __GNUC__ >4 || (__GNUC__ ==4 && __GNUC_MINOR__ >=8 )#define rte_bswap16 (x) __builtin_bswap16(x)#endif
@@ -241,6 +242,16 @@#define rte_bswap32 (x) __builtin_bswap32(x)#define rte_bswap64 (x) __builtin_bswap64(x) +#else +/* +* note: we may want to #pragma intrsinsic(_byteswap_u{short,long,uint64}) +*/ +#define rte_bswap16 (x) _byteswap_ushort(x) + +#define rte_bswap32 (x) _byteswap_ulong(x) + +#define rte_bswap64 (x) _byteswap_uint64(x) +#endif #endif
lib/eal/x86/include/rte_byteorder.h +4 -0
@@ -18,6 +18,7 @@#define RTE_BYTE_ORDER RTE_LITTLE_ENDIAN#endif +#ifndef RTE_TOOLCHAIN_MSVC /* * An architecture-optimized byte swap for a 16-bit value. *
@@ -69,6 +70,7 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x) rte_arch_bswap16(x)))#endif #endif +#endif #define rte_cpu_to_le_16 (x) (x)#define rte_cpu_to_le_32 (x) (x)
@@ -86,11 +88,13 @@ static inline uint32_t rte_arch_bswap32(uint32_t _x)#define rte_be_to_cpu_32 (x) rte_bswap32(x)#define rte_be_to_cpu_64 (x) rte_bswap64(x) +#ifndef RTE_TOOLCHAIN_MSVC #ifdef RTE_ARCH_I686 #include "rte_byteorder_32.h" #else #include "rte_byteorder_64.h" #endif +#endif #ifdef __cplusplus }
Signature · 1 line
1.8.3.1
PATCH v8 8/14 eal: hide GCC extension based alignment markers
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs used as alignment markers.
--- lib/eal/include/rte_common.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/rte_common.h +4 -0
@@ -460,6 +460,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/*********** Structure alignment markers ********/ +#ifndef RTE_TOOLCHAIN_MSVC +/** Generic marker for any place in a structure. */ __extension__typedef void *RTE_MARKER [0 ];/** Marker for 1B alignment in a structure. */
@@ -471,6 +473,8 @@ static void __attribute__((destructor(RTE_PRIO(prio)), used)) func(void)/** Marker for 8B alignment in a structure. */ __extension__typedef uint64_t RTE_MARKER64 [0 ]; +#endif +/** * Combines 32b inputs most significant set bits into the least * significant bits to construct a value with the same MSBs as x
Signature · 1 line
1.8.3.1
PATCH v8 9/14 eal: hide typedefs based on GCC vector extensions
In reply to Tyler RetzlaffWhen compiling with MSVC don't expose typedefs based on GCC vector extensions.
--- lib/eal/include/generic/rte_vect.h | 4 ++++ 1 file changed, 4 insertions(+)
lib/eal/include/generic/rte_vect.h +4 -0
@@ -17,6 +17,8 @@#include <rte_compat.h> +#ifndef RTE_TOOLCHAIN_MSVC +/* Unsigned vector types */ /**
@@ -186,6 +188,8 @@*/ typedef int64_t rte_v256s64_t __attribute__((vector_size (32 ),aligned (32 ))); +#endif +/** * The max SIMD bitwidth value to limit vector path selection. */
Signature · 1 line
1.8.3.1