Clang and recent versions of GCC has builtin functions to do most math operations and check for wraparound. On most architectures this is a just a math operation followed by a branch on carry set.
But DPDK needs to be able to handle older GCC versions, and other compilers so a wrapper macro is needed. Chose to use a macro instead of inline functions to avoid having to write lots of variants for each numeric type. Signed-off-by: Stephen Hemminger <[email protected]> --- lib/librte_eal/common/Makefile | 2 +- lib/librte_eal/common/include/rte_overflow.h | 74 ++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 lib/librte_eal/common/include/rte_overflow.h diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile index c2c6d92cd377..3794128b75b7 100644 --- a/lib/librte_eal/common/Makefile +++ b/lib/librte_eal/common/Makefile @@ -13,7 +13,7 @@ INC += rte_tailq.h rte_interrupts.h rte_alarm.h INC += rte_string_fns.h rte_version.h INC += rte_eal_memconfig.h INC += rte_hexdump.h rte_devargs.h rte_bus.h rte_dev.h rte_class.h -INC += rte_option.h +INC += rte_option.h rte_overflow.h INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h INC += rte_malloc.h rte_keepalive.h rte_time.h INC += rte_service.h rte_service_component.h diff --git a/lib/librte_eal/common/include/rte_overflow.h b/lib/librte_eal/common/include/rte_overflow.h new file mode 100644 index 000000000000..d61791371029 --- /dev/null +++ b/lib/librte_eal/common/include/rte_overflow.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Microsoft Corp + */ +#ifndef RTE_OVERFLOW_H_ +#define RTE_OVERFLOW_H_ +/** + * @file + * + * Math functions with overflow checking. + * Wrappers for the __builtin_XXX_overflow functions that exist + * in recent versions of GCC and CLANG but may not exist + * in older compilers. They are macros to allow use with any + * size of unsigned number. + * + * See: + * https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html + * https://github.com/nemequ/portable-snippets/tree/master/safe-math + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdbool.h> + +#if defined(__has_builtin) +# if __has_builtin(__builtin_add_overflow) +# define RTE_HAVE_BUILTIN_OVERFLOW +# endif +#elif defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION >= 5000) +# define RTE__HAVE_BUILTIN_OVERFLOW +#endif + +/** + * Safely add two bit unsigned numbers + * @param a + * One operand + * @param b + * Other operand + * @param res + * Pointer to the where result of a + b is stored. + * Must not be NULL + * @return + * return true if the result overflows and is therefore truncated. + */ +#ifdef RTE_HAVE_BUILTIN_OVERFLOW +#define rte_add_overflow(a, b, res) __builtin_add_overflow(a, b, res) +#else +#define rte_add_overflow(a, b, res) ({ *res = a + b; *res < a; }) +#endif + +/** + * Safely multiply two unsigned numbers + * @param a + * One operand + * @param b + * Other operand + * @param res + * Pointer to the where result of a + b is stored. + * Must not be NULL + * @return + * return true if the result overflows and is therefore truncated. + */ +#ifdef RTE_HAVE_BUILTIN_OVERFLOW +#define rte_mul_overflow(a, b, res) __builtin_mul_overflow(a, b, res) +#else +#define rte_mul_overflow(a, b, res) ({ *res = a * b; *res < a; }) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* RTE_OVERFLOW_H_ */ -- 2.20.1

