diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 3fd291503576..f83658a4f15d 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -819,6 +819,49 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { } __UNIQUE_ID(max1_), __UNIQUE_ID(max2_), \ x, y) +size_t __error_not_const_arg(void) \ +__compiletime_error("const_max() used with non-compile-time constant arg"); +size_t __error_too_big(void) \ +__compiletime_error("const_max() used with an arg too big"); + +#define INTMAXT_MAX LLONG_MAX +typedef int64_t intmax_t; + +#define const_cmp(x, y, op) \ + __builtin_choose_expr( \ + !__builtin_constant_p(x) || !__builtin_constant_p(y), \ + __error_not_const_arg(), \ + __builtin_choose_expr( \ + (x) > INTMAXT_MAX || (y) > INTMAXT_MAX, \ + __error_too_big(), \ + __builtin_choose_expr( \ + (intmax_t)(x) op (intmax_t)(y), \ + (x), \ + (y) \ + ) \ + ) \ + ) + +/** + * const_min - returns minimum of two compile-time constant values + * @x: first compile-time constant value + * @y: second compile-time constant value + * + * The result has the type of the winner of the comparison. Works for any + * value up to LLONG_MAX. + */ +#define const_min(x, y) const_cmp((x), (y), <=) + +/** + * const_max - returns maximum of two compile-time constant values + * @x: first compile-time constant value + * @y: second compile-time constant value + * + * The result has the type of the winner of the comparison. Works for any + * value up to LLONG_MAX. + */ +#define const_max(x, y) const_cmp((x), (y), >=) + /** * min3 - return minimum of three values * @x: first value