Skip to content

Commit c576b09

Browse files
fabiobaltiericfriedt
authored andcommitted
sys: util: add support for nested min/max
Add support for nested min/max by using unique automatic variables. This is heavily inspired by the Linux implementation, just reimplemented from scratch using the Zephyr internal APIs. Link: https://elixir.bootlin.com/linux/v6.16.8/source/include/linux/minmax.h#L314-L315 Signed-off-by: Fabio Baltieri <[email protected]>
1 parent 37717b2 commit c576b09

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

include/zephyr/sys/util.h

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,21 @@ extern "C" {
372372
? ((n) - ((d) / 2)) / (d) \
373373
: ((n) + ((d) / 2)) / (d))
374374

375+
/**
376+
* @cond INTERNAL_HIDDEN
377+
*/
378+
#define _minmax_unique(op, a, b, ua, ub) ({ \
379+
__typeof__(a) ua = (a); \
380+
__typeof__(b) ub = (b); \
381+
op(ua, ub); \
382+
})
383+
384+
#define _minmax_cnt(op, a, b, cnt) \
385+
_minmax_unique(op, a, b, UTIL_CAT(_value_a_, cnt), UTIL_CAT(_value_b_, cnt))
386+
/**
387+
* @endcond
388+
*/
389+
375390
#ifndef MAX
376391
/**
377392
* @brief Obtain the maximum of two values.
@@ -397,12 +412,7 @@ extern "C" {
397412
* - to generate constant integer, e.g. __aligned(max(4,5))
398413
* - static variable, e.g. array like static uint8_t array[max(...)];
399414
*/
400-
#define max(a, b) ({ \
401-
/* random suffix to avoid naming conflict */ \
402-
__typeof__(a) _value_a_ = (a); \
403-
__typeof__(b) _value_b_ = (b); \
404-
(_value_a_ > _value_b_) ? _value_a_ : _value_b_; \
405-
})
415+
#define max(a, b) _minmax_cnt(MAX, a, b, __COUNTER__)
406416
#endif
407417

408418
#ifndef MIN
@@ -426,12 +436,7 @@ extern "C" {
426436
* Macro ensures that expressions are evaluated only once. See @ref max for
427437
* macro limitations.
428438
*/
429-
#define min(a, b) ({ \
430-
/* random suffix to avoid naming conflict */ \
431-
__typeof__(a) _value_a_ = (a); \
432-
__typeof__(b) _value_b_ = (b); \
433-
(_value_a_ < _value_b_) ? _value_a_ : _value_b_; \
434-
})
439+
#define min(a, b) _minmax_cnt(MIN, a, b, __COUNTER__)
435440
#endif
436441

437442
#ifndef MAX_FROM_LIST

tests/unit/util/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,13 @@ ZTEST(util, test_max_min_clamp) {
269269
"Unexpected macro result");
270270
/* clamp should have call inc_func only once */
271271
zassert_equal(inc_func(false), 8, "Unexpected return value");
272+
273+
/* Nested calls do not generate build warnings */
274+
zassert_equal(max(inc_func(false),
275+
max(inc_func(false),
276+
min(inc_func(false),
277+
inc_func(false)))), 11, "Unexpected macro result");
278+
zassert_equal(inc_func(false), 13, "Unexpected return value");
272279
#endif
273280
}
274281

0 commit comments

Comments
 (0)