|
@@ -792,41 +792,58 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
|
|
|
#endif /* CONFIG_TRACING */
|
|
|
|
|
|
/*
|
|
|
- * min()/max()/clamp() macros that also do
|
|
|
- * strict type-checking.. See the
|
|
|
- * "unnecessary" pointer comparison.
|
|
|
+ * min()/max()/clamp() macros must accomplish three things:
|
|
|
+ *
|
|
|
+ * - avoid multiple evaluations of the arguments (so side-effects like
|
|
|
+ * "x++" happen only once) when non-constant.
|
|
|
+ * - perform strict type-checking (to generate warnings instead of
|
|
|
+ * nasty runtime surprises). See the "unnecessary" pointer comparison
|
|
|
+ * in __typecheck().
|
|
|
+ * - retain result as a constant expressions when called with only
|
|
|
+ * constant expressions (to avoid tripping VLA warnings in stack
|
|
|
+ * allocation usage).
|
|
|
+ */
|
|
|
+#define __typecheck(x, y) \
|
|
|
+ (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
|
|
|
+
|
|
|
+/*
|
|
|
+ * This returns a constant expression while determining if an argument is
|
|
|
+ * a constant expression, most importantly without evaluating the argument.
|
|
|
+ * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
|
|
|
*/
|
|
|
-#define __min(t1, t2, min1, min2, x, y) ({ \
|
|
|
- t1 min1 = (x); \
|
|
|
- t2 min2 = (y); \
|
|
|
- (void) (&min1 == &min2); \
|
|
|
- min1 < min2 ? min1 : min2; })
|
|
|
+#define __is_constexpr(x) \
|
|
|
+ (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
|
|
|
+
|
|
|
+#define __no_side_effects(x, y) \
|
|
|
+ (__is_constexpr(x) && __is_constexpr(y))
|
|
|
+
|
|
|
+#define __safe_cmp(x, y) \
|
|
|
+ (__typecheck(x, y) && __no_side_effects(x, y))
|
|
|
+
|
|
|
+#define __cmp(x, y, op) ((x) op (y) ? (x) : (y))
|
|
|
+
|
|
|
+#define __cmp_once(x, y, op) ({ \
|
|
|
+ typeof(x) __x = (x); \
|
|
|
+ typeof(y) __y = (y); \
|
|
|
+ __cmp(__x, __y, op); })
|
|
|
+
|
|
|
+#define __careful_cmp(x, y, op) \
|
|
|
+ __builtin_choose_expr(__safe_cmp(x, y), \
|
|
|
+ __cmp(x, y, op), __cmp_once(x, y, op))
|
|
|
|
|
|
/**
|
|
|
* min - return minimum of two values of the same or compatible types
|
|
|
* @x: first value
|
|
|
* @y: second value
|
|
|
*/
|
|
|
-#define min(x, y) \
|
|
|
- __min(typeof(x), typeof(y), \
|
|
|
- __UNIQUE_ID(min1_), __UNIQUE_ID(min2_), \
|
|
|
- x, y)
|
|
|
-
|
|
|
-#define __max(t1, t2, max1, max2, x, y) ({ \
|
|
|
- t1 max1 = (x); \
|
|
|
- t2 max2 = (y); \
|
|
|
- (void) (&max1 == &max2); \
|
|
|
- max1 > max2 ? max1 : max2; })
|
|
|
+#define min(x, y) __careful_cmp(x, y, <)
|
|
|
|
|
|
/**
|
|
|
* max - return maximum of two values of the same or compatible types
|
|
|
* @x: first value
|
|
|
* @y: second value
|
|
|
*/
|
|
|
-#define max(x, y) \
|
|
|
- __max(typeof(x), typeof(y), \
|
|
|
- __UNIQUE_ID(max1_), __UNIQUE_ID(max2_), \
|
|
|
- x, y)
|
|
|
+#define max(x, y) __careful_cmp(x, y, >)
|
|
|
|
|
|
/**
|
|
|
* min3 - return minimum of three values
|
|
@@ -878,10 +895,7 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
|
|
|
* @x: first value
|
|
|
* @y: second value
|
|
|
*/
|
|
|
-#define min_t(type, x, y) \
|
|
|
- __min(type, type, \
|
|
|
- __UNIQUE_ID(min1_), __UNIQUE_ID(min2_), \
|
|
|
- x, y)
|
|
|
+#define min_t(type, x, y) __careful_cmp((type)(x), (type)(y), <)
|
|
|
|
|
|
/**
|
|
|
* max_t - return maximum of two values, using the specified type
|
|
@@ -889,10 +903,7 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
|
|
|
* @x: first value
|
|
|
* @y: second value
|
|
|
*/
|
|
|
-#define max_t(type, x, y) \
|
|
|
- __max(type, type, \
|
|
|
- __UNIQUE_ID(min1_), __UNIQUE_ID(min2_), \
|
|
|
- x, y)
|
|
|
+#define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >)
|
|
|
|
|
|
/**
|
|
|
* clamp_t - return a value clamped to a given range using a given type
|