Provide build option to have functions in <rte_memcpy.h> delegate to the standard compiler/libc memcpy(), instead of using the various traditional, handcrafted, per-architecture rte_memcpy() implementations.
A new meson build option 'use_cc_memcpy' is added. The default is true. It's not obvious what should be the default, but compiler memcpy() is enabled by default in this RFC so any tests run with this patch use the new approach. One purpose of this RFC is to make it easy to evaluate the costs and benefits of a switch. Only ARM and x86 is implemented. Signed-off-by: Mattias Rönnblom <mattias.ronnb...@ericsson.com> --- config/meson.build | 1 + lib/eal/arm/include/rte_memcpy.h | 10 +++++ lib/eal/include/generic/rte_memcpy.h | 62 ++++++++++++++++++++++++---- lib/eal/x86/include/meson.build | 6 ++- lib/eal/x86/include/rte_memcpy.h | 11 ++++- meson_options.txt | 2 + 6 files changed, 83 insertions(+), 9 deletions(-) diff --git a/config/meson.build b/config/meson.build index 8c8b019c25..456056628e 100644 --- a/config/meson.build +++ b/config/meson.build @@ -353,6 +353,7 @@ endforeach # set other values pulled from the build options dpdk_conf.set('RTE_MAX_ETHPORTS', get_option('max_ethports')) dpdk_conf.set('RTE_LIBEAL_USE_HPET', get_option('use_hpet')) +dpdk_conf.set('RTE_USE_CC_MEMCPY', get_option('use_cc_memcpy')) dpdk_conf.set('RTE_ENABLE_STDATOMIC', get_option('enable_stdatomic')) dpdk_conf.set('RTE_ENABLE_TRACE_FP', get_option('enable_trace_fp')) dpdk_conf.set('RTE_PKTMBUF_HEADROOM', get_option('pkt_mbuf_headroom')) diff --git a/lib/eal/arm/include/rte_memcpy.h b/lib/eal/arm/include/rte_memcpy.h index 47dea9a8cc..e8aff722df 100644 --- a/lib/eal/arm/include/rte_memcpy.h +++ b/lib/eal/arm/include/rte_memcpy.h @@ -5,10 +5,20 @@ #ifndef _RTE_MEMCPY_ARM_H_ #define _RTE_MEMCPY_ARM_H_ +#include <rte_config.h> + +#ifdef RTE_USE_CC_MEMCPY + +#include <generic/rte_memcpy.h> + +#else + #ifdef RTE_ARCH_64 #include <rte_memcpy_64.h> #else #include <rte_memcpy_32.h> #endif +#endif /* RTE_USE_CC_MEMCPY */ + #endif /* _RTE_MEMCPY_ARM_H_ */ diff --git a/lib/eal/include/generic/rte_memcpy.h b/lib/eal/include/generic/rte_memcpy.h index e7f0f8eaa9..f2f66f372d 100644 --- a/lib/eal/include/generic/rte_memcpy.h +++ b/lib/eal/include/generic/rte_memcpy.h @@ -5,12 +5,20 @@ #ifndef _RTE_MEMCPY_H_ #define _RTE_MEMCPY_H_ +#ifdef __cplusplus +extern "C" { +#endif + /** * @file * * Functions for vectorised implementation of memcpy(). */ +#include <stdint.h> +#include <string.h> +#include <rte_vect.h> + /** * Copy 16 bytes from one location to another using optimised * instructions. The locations should not overlap. @@ -35,8 +43,6 @@ rte_mov16(uint8_t *dst, const uint8_t *src); static inline void rte_mov32(uint8_t *dst, const uint8_t *src); -#ifdef __DOXYGEN__ - /** * Copy 48 bytes from one location to another using optimised * instructions. The locations should not overlap. @@ -49,8 +55,6 @@ rte_mov32(uint8_t *dst, const uint8_t *src); static inline void rte_mov48(uint8_t *dst, const uint8_t *src); -#endif /* __DOXYGEN__ */ - /** * Copy 64 bytes from one location to another using optimised * instructions. The locations should not overlap. @@ -87,8 +91,6 @@ rte_mov128(uint8_t *dst, const uint8_t *src); static inline void rte_mov256(uint8_t *dst, const uint8_t *src); -#ifdef __DOXYGEN__ - /** * Copy bytes from one location to another. The locations must not overlap. * @@ -111,6 +113,52 @@ rte_mov256(uint8_t *dst, const uint8_t *src); static void * rte_memcpy(void *dst, const void *src, size_t n); -#endif /* __DOXYGEN__ */ +#ifdef RTE_USE_CC_MEMCPY +static inline void +rte_mov16(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 16); +} + +static inline void +rte_mov32(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 32); +} + +static inline void +rte_mov48(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 48); +} + +static inline void +rte_mov64(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 64); +} + +static inline void +rte_mov128(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 128); +} + +static inline void +rte_mov256(uint8_t *dst, const uint8_t *src) +{ + memcpy(dst, src, 256); +} + +static inline void * +rte_memcpy(void *dst, const void *src, size_t n) +{ + return memcpy(dst, src, n); +} +#endif /* RTE_USE_CC_MEMCPY */ + +#ifdef __cplusplus +} +#endif #endif /* _RTE_MEMCPY_H_ */ diff --git a/lib/eal/x86/include/meson.build b/lib/eal/x86/include/meson.build index 52d2f8e969..cf851df60d 100644 --- a/lib/eal/x86/include/meson.build +++ b/lib/eal/x86/include/meson.build @@ -7,7 +7,6 @@ arch_headers = files( 'rte_cpuflags.h', 'rte_cycles.h', 'rte_io.h', - 'rte_memcpy.h', 'rte_pause.h', 'rte_power_intrinsics.h', 'rte_prefetch.h', @@ -16,6 +15,11 @@ arch_headers = files( 'rte_spinlock.h', 'rte_vect.h', ) + +if not get_option('use_cc_memcpy') + arch_headers += 'rte_memcpy.h' +endif + arch_indirect_headers = files( 'rte_atomic_32.h', 'rte_atomic_64.h', diff --git a/lib/eal/x86/include/rte_memcpy.h b/lib/eal/x86/include/rte_memcpy.h index 72a92290e0..c5ba74d2ed 100644 --- a/lib/eal/x86/include/rte_memcpy.h +++ b/lib/eal/x86/include/rte_memcpy.h @@ -11,12 +11,19 @@ * Functions for SSE/AVX/AVX2/AVX512 implementation of memcpy(). */ +#include <rte_config.h> + +#ifdef RTE_USE_CC_MEMCPY + +#include <generic/rte_memcpy.h> + +#else + #include <stdio.h> #include <stdint.h> #include <string.h> #include <rte_vect.h> #include <rte_common.h> -#include <rte_config.h> #ifdef __cplusplus extern "C" { @@ -878,4 +885,6 @@ rte_memcpy(void *dst, const void *src, size_t n) } #endif +#endif /* RTE_USE_CC_MEMCPY */ + #endif /* _RTE_MEMCPY_X86_64_H_ */ diff --git a/meson_options.txt b/meson_options.txt index e49b2fc089..263b0e7882 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -60,3 +60,5 @@ option('tests', type: 'boolean', value: true, description: 'build unit tests') option('use_hpet', type: 'boolean', value: false, description: 'use HPET timer in EAL') +option('use_cc_memcpy', type: 'boolean', value: true, description: + 'Have rte_memcpy() delegate to compiler/libc memcpy() instead of using custom implementation.') -- 2.34.1