[1/6] eal: add portable way to check for math overflow
Checks
Commit Message
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 <stephen@networkplumber.org>
---
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
Comments
> +#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
Excessive underline after RTE results in RTE_HAVE_BUILTIN_OVERFLOW not being
defined.
@@ -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
new file mode 100644
@@ -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_ */