Skip to content

Commit

Permalink
toolchain: Add single arguments evaluation macros for min and max
Browse files Browse the repository at this point in the history
MAX() and MIN() were evaluating arguments twice. If arguments are
functions they were called twice which resulted in bigger code
and potential misbehavior.

Added alternative macros (Z_MAX, Z_MIN) which can be used instead.
Macros have usage limitations thus they are not replacements. They
are also relying on GCC extension thus placed in gcc.h

Signed-off-by: Krzysztof Chruscinski <[email protected]>
  • Loading branch information
nordic-krch authored and carlescufi committed Sep 25, 2019
1 parent 6768148 commit bea966d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
10 changes: 10 additions & 0 deletions include/sys/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,20 @@ constexpr size_t ARRAY_SIZE(T(&)[N]) { return N; }
#define INLINE
#endif

/** @brief Return larger value of two provided expressions.
*
* @note Arguments are evaluated twice. See Z_MAX for GCC only, single
* evaluation version.
*/
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

/** @brief Return smaller value of two provided expressions.
*
* @note Arguments are evaluated twice. See Z_MIN for GCC only, single
* evaluation version.
*/
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
Expand Down
28 changes: 28 additions & 0 deletions include/toolchain/gcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,4 +415,32 @@ do { \
__asm__ __volatile__ ("" ::: "memory"); \
} while (false)

/** @brief Return larger value of two provided expressions.
*
* Macro ensures that expressions are evaluated only once.
*
* @note Macro has limited usage compared to the standard macro as it cannot be
* used:
* - to generate constant integer, e.g. __aligned(Z_MAX(4,5))
* - static variable, e.g. array like static u8_t array[Z_MAX(...)];
*/
#define Z_MAX(a, b) ({ \
/* random suffix to avoid naming conflict */ \
__typeof__(a) _value_a_ = (a); \
__typeof__(b) _value_b_ = (b); \
_value_a_ > _value_b_ ? _value_a_ : _value_b_; \
})

/** @brief Return smaller value of two provided expressions.
*
* Macro ensures that expressions are evaluated only once. See @ref Z_MAX for
* macro limitations.
*/
#define Z_MIN(a, b) ({ \
/* random suffix to avoid naming conflict */ \
__typeof__(a) _value_a_ = (a); \
__typeof__(b) _value_b_ = (b); \
_value_a_ < _value_b_ ? _value_a_ : _value_b_; \
})

#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_GCC_H_ */

0 comments on commit bea966d

Please sign in to comment.