Backport minmax.h updates from v6.17-rc7
Subsystems (14)
v4 cover Backport minmax.h updates from v6.17-rc7
This series backports 11 patches to update minmax.h in the 6.1.y branch, aligning it with v6.17-rc7.
The ultimate goal is to synchronize all longterm branches so that they include the full set of minmax.h changes (6.12.y and 6.6.y were already backported by me and are now aligned).
The key motivation is to bring in commit d03eba99f5bf ("minmax: allow min()/max()/clamp() if the arguments have the same signedness"), which is missing in older kernels.
In mainline, this change enables min()/max()/clamp() to accept mixed argument types, provided both have the same signedness. Without it, backported patches that use these forms may trigger compiler warnings, which escalate to build failures when -Werror is enabled.
Changes in v4:
- Just swap the order of the first 2 patches in this chain, because commit cb04e8b1d2f2 ("minmax: don't use max() in situations that want a C constant expression") should come before commit dc1c8034e31b ("minmax: simplify min()/max()/clamp() implementation").
Changes in v3:
- v2 included 13 patches:
https://lore.kernel.org/stable/[email protected]/
- First 2 were accepted and are part of 6.1.155.
- 3rd caused build in drivers/md/ to fail:
In file included from ./include/linux/container_of.h:5,
from ./include/linux/list.h:5,
from ./include/linux/wait.h:7,
from ./include/linux/mempool.h:8,
from ./include/linux/bio.h:8,
from drivers/md/dm-bio-record.h:10,
from drivers/md/dm-integrity.c:9:drivers/md/dm-integrity.c: In function ‘integrity_metadata’:drivers/md/dm-integrity.c:131:105: error: ISO C90 forbids variable length array ‘checksums_onstack’ [-Werror=vla]
131 | #define MAX_TAG_SIZE (JOURNAL_SECTOR_DATA - JOURNAL_MAC_PER_SECTOR - offsetof(struct journal_entry, last_bytes[MAX_SECTORS_PER_BLOCK]))
| ^~~~~~~~~~~~~./include/linux/build_bug.h:78:56: note: in definition of macro ‘__static_assert’
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~./include/linux/minmax.h:56:9: note: in expansion of macro ‘static_assert’
56 | static_assert(__types_ok(x, y, ux, uy), \
| ^~~~~~~~~~~~~
./include/linux/minmax.h:41:31: note: in expansion of macro ‘__is_noneg_int’
41 | __is_noneg_int(x) || __is_noneg_int(y))
| ^~~~~~~~~~~~~~
./include/linux/minmax.h:56:23: note: in expansion of macro ‘__types_ok’
56 | static_assert(__types_ok(x, y, ux, uy), \
| ^~~~~~~~~~
./include/linux/minmax.h:61:9: note: in expansion of macro ‘__careful_cmp_once’
61 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
| ^~~~~~~~~~~~~~~~~~
./include/linux/minmax.h:92:25: note: in expansion of macro ‘__careful_cmp’
92 | #define max(x, y) __careful_cmp(max, x, y)
| ^~~~~~~~~~~~~drivers/md/dm-integrity.c:1797:40: note: in expansion of macro ‘max’
1797 | char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
| ^~~drivers/md/dm-integrity.c:131:89: note: in expansion of macro ‘offsetof’
131 | #define MAX_TAG_SIZE (JOURNAL_SECTOR_DATA - JOURNAL_MAC_PER_SECTOR - offsetof(struct journal_entry, last_bytes[MAX_SECTORS_PER_BLOCK]))
| ^~~~~~~~drivers/md/dm-integrity.c:1797:73: note: in expansion of macro ‘MAX_TAG_SIZE’
1797 | char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
| ^~~~~~~~~~~~
- The build was fixed in the second patch of this series.
Changes in v2:
- v1 included 19 patches:
https://lore.kernel.org/stable/[email protected]/
- First 6 were pushed to the stable-tree.
- 7th cauded amd driver's build to fail.
- This change fixes it.
- Modified files:
drivers/gpu/drm/amd/amdgpu/amdgpu.h drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
David Laight (7):
minmax.h: add whitespace around operators and after commas minmax.h: update some comments
minmax.h: reduce the #define expansion of min(), max() and clamp() minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp() minmax.h: move all the clamp() definitions after the min/max() ones minmax.h: simplify the variants of clamp()
minmax.h: remove some #defines that are only expanded once
Linus Torvalds (4):
minmax: don't use max() in situations that want a C constant
expression
minmax: simplify min()/max()/clamp() implementation
minmax: improve macro expansion and type checking
minmax: fix up min3() and max3() too
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 +- drivers/input/touchscreen/cyttsp4_core.c | 2 +- drivers/irqchip/irq-sun6i-r.c | 2 +- drivers/md/dm-integrity.c | 2 +- fs/btrfs/tree-checker.c | 2 +- include/linux/compiler.h | 9 + include/linux/minmax.h | 222 +++++++++++++---------- lib/vsprintf.c | 2 +- 8 files changed, 143 insertions(+), 100 deletions(-)
Signature · 1 line
2.47.3
PATCH v4 1/11 minmax: don't use max() in situations that want a C constant expression
From: Linus Torvalds <[email protected]>
[ Upstream commit cb04e8b1d2f24c4c2c92f7b7529031fc35a16fed ]
We only had a couple of array[] declarations, and changing them to just use 'MAX()' instead of 'max()' fixes the issue.
This will allow us to simplify our min/max macros enormously, since they can now unconditionally use temporary variables to avoid using the argument values multiple times.
--- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 +- drivers/input/touchscreen/cyttsp4_core.c | 2 +- drivers/irqchip/irq-sun6i-r.c | 2 +- drivers/md/dm-integrity.c | 2 +- fs/btrfs/tree-checker.c | 2 +- lib/vsprintf.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +1 -1
@@ -700,7 +700,7 @@ static const char *smu_get_feature_name(struct smu_context *smu,size_t smu_cmn_get_pp_feature_mask (struct smu_context *smu,char *buf) { -int8_t sort_feature[max (SMU_FEATURE_COUNT ,SMU_FEATURE_MAX )]; +int8_t sort_feature[MAX (SMU_FEATURE_COUNT ,SMU_FEATURE_MAX )];uint64_t feature_mask;int i, feature_index;uint32_t count =0 ;
drivers/input/touchscreen/cyttsp4_core.c +1 -1
@@ -871,7 +871,7 @@ static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch)struct cyttsp4_touch tch;int sig;int i, j, t =0 ; -int ids[max (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )]; +int ids[MAX (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )];memset (ids,0 , si->si_ofs.tch_abs[CY_TCH_T ].max *sizeof (int ));for (i =0 ; i < num_cur_tch; i++) {
drivers/irqchip/irq-sun6i-r.c +1 -1
@@ -270,7 +270,7 @@ static const struct irq_domain_ops sun6i_r_intc_domain_ops = {static int sun6i_r_intc_suspend (void ) { -u32 buf[BITS_TO_U32 (max (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))]; +u32 buf[BITS_TO_U32 (MAX (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))];int i;/* Wake IRQs are enabled during system sleep and shutdown. */
drivers/md/dm-integrity.c +1 -1
@@ -1794,7 +1794,7 @@ static void integrity_metadata(struct work_struct *w)struct bio *bio =dm_bio_from_per_bio_data (dio,sizeof (struct dm_integrity_io ));char *checksums;unsigned int extra_space =unlikely (digest_size > ic->tag_size) ? digest_size - ic->tag_size :0 ; -char checksums_onstack[max ((size_t )HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )]; +char checksums_onstack[MAX (HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )];sector_t sector;unsigned int sectors_to_process;
fs/btrfs/tree-checker.c +1 -1
@@ -608,7 +608,7 @@ static int check_dir_item(struct extent_buffer *leaf,*/ if (key->type ==BTRFS_DIR_ITEM_KEY || key->type ==BTRFS_XATTR_ITEM_KEY ) { -char namebuf[max (BTRFS_NAME_LEN ,XATTR_NAME_MAX )]; +char namebuf[MAX (BTRFS_NAME_LEN ,XATTR_NAME_MAX )];read_extent_buffer (leaf, namebuf, (unsigned long )(di +1 ), name_len);
lib/vsprintf.c +1 -1
@@ -1082,7 +1082,7 @@ char *resource_string(char *buf, char *end, struct resource *res,#define FLAG_BUF_SIZE (2 * sizeof(res->flags))#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")#define RAW_BUF_SIZE sizeof("[mem - flags 0x]") -char sym[max (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE , +char sym[MAX (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE ,2 *RSRC_BUF_SIZE +FLAG_BUF_SIZE +RAW_BUF_SIZE )];char *p = sym, *pend = sym +sizeof (sym);
Signature · 1 line
2.47.3
Patch "minmax: don't use max() in situations that want a C constant expression" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax: don't use max() in situations that want a C constant expression
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:16:33 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:10 +0000
Subject: minmax: don't use max() in situations that want a C constant expression
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Linus Torvalds <[email protected]>, David Laight <[email protected]>, Lorenzo Stoakes <[email protected]>
Message-ID: <[email protected]>
From: Linus Torvalds <[email protected]>
[ Upstream commit cb04e8b1d2f24c4c2c92f7b7529031fc35a16fed ]
We only had a couple of array[] declarations, and changing them to just use 'MAX()' instead of 'max()' fixes the issue.
This will allow us to simplify our min/max macros enormously, since they can now unconditionally use temporary variables to avoid using the argument values multiple times.
--- drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 2 +- drivers/input/touchscreen/cyttsp4_core.c | 2 +- drivers/irqchip/irq-sun6i-r.c | 2 +- drivers/md/dm-integrity.c | 2 +- fs/btrfs/tree-checker.c | 2 +- lib/vsprintf.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c +1 -1
@@ -700,7 +700,7 @@ static const char *smu_get_feature_name(size_t smu_cmn_get_pp_feature_mask (struct smu_context *smu,char *buf) { -int8_t sort_feature[max (SMU_FEATURE_COUNT ,SMU_FEATURE_MAX )]; +int8_t sort_feature[MAX (SMU_FEATURE_COUNT ,SMU_FEATURE_MAX )];uint64_t feature_mask;int i, feature_index;uint32_t count =0 ;
drivers/input/touchscreen/cyttsp4_core.c +1 -1
@@ -871,7 +871,7 @@ static void cyttsp4_get_mt_touches(strucstruct cyttsp4_touch tch;int sig;int i, j, t =0 ; -int ids[max (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )]; +int ids[MAX (CY_TMA1036_MAX_TCH ,CY_TMA4XX_MAX_TCH )];memset (ids,0 , si->si_ofs.tch_abs[CY_TCH_T ].max *sizeof (int ));for (i =0 ; i < num_cur_tch; i++) {
drivers/irqchip/irq-sun6i-r.c +1 -1
@@ -270,7 +270,7 @@ static const struct irq_domain_ops sun6istatic int sun6i_r_intc_suspend (void ) { -u32 buf[BITS_TO_U32 (max (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))]; +u32 buf[BITS_TO_U32 (MAX (SUN6I_NR_TOP_LEVEL_IRQS ,SUN6I_NR_MUX_BITS ))];int i;/* Wake IRQs are enabled during system sleep and shutdown. */
drivers/md/dm-integrity.c +1 -1
@@ -1794,7 +1794,7 @@ static void integrity_metadata(struct wostruct bio *bio =dm_bio_from_per_bio_data (dio,sizeof (struct dm_integrity_io ));char *checksums;unsigned int extra_space =unlikely (digest_size > ic->tag_size) ? digest_size - ic->tag_size :0 ; -char checksums_onstack[max ((size_t )HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )]; +char checksums_onstack[MAX (HASH_MAX_DIGESTSIZE ,MAX_TAG_SIZE )];sector_t sector;unsigned int sectors_to_process;
fs/btrfs/tree-checker.c +1 -1
@@ -608,7 +608,7 @@ static int check_dir_item(struct extent_*/ if (key->type ==BTRFS_DIR_ITEM_KEY || key->type ==BTRFS_XATTR_ITEM_KEY ) { -char namebuf[max (BTRFS_NAME_LEN ,XATTR_NAME_MAX )]; +char namebuf[MAX (BTRFS_NAME_LEN ,XATTR_NAME_MAX )];read_extent_buffer (leaf, namebuf, (unsigned long )(di +1 ), name_len);
lib/vsprintf.c +1 -1
@@ -1082,7 +1082,7 @@ char *resource_string(char *buf, char *e#define FLAG_BUF_SIZE (2 * sizeof(res->flags))#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")#define RAW_BUF_SIZE sizeof("[mem - flags 0x]") -char sym[max (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE , +char sym[MAX (2 *RSRC_BUF_SIZE +DECODED_BUF_SIZE ,2 *RSRC_BUF_SIZE +FLAG_BUF_SIZE +RAW_BUF_SIZE )];char *p = sym, *pend = sym +sizeof (sym);
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 2/11 minmax: simplify min()/max()/clamp() implementation
In reply to Eliav FarberFrom: Linus Torvalds <[email protected]>
[ Upstream commit dc1c8034e31b14a2e5e212104ec508aec44ce1b9 ]
Now that we no longer have any C constant expression contexts (ie array size declarations or static initializers) that use min() or max(), we can simpify the implementation by not having to worry about the result staying as a C constant expression.
So now we can unconditionally just use temporary variables of the right type, and get rid of the excessive expansion that used to come from the use of
__builtin_choose_expr(__is_constexpr(...), ..
to pick the specialized code for constant expressions.
Another expansion simplification is to pass the temporary variables (in addition to the original expression) to our __types_ok() macro. That may superficially look like it complicates the macro, but when we only want the type of the expression, expanding the temporary variable names is much simpler and smaller than expanding the potentially complicated original expression.
As a result, on my machine, doing a
$ time make drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.i
goes from
real 0m16.621s user 0m15.360s sys 0m1.221s
to
real 0m2.532s user 0m2.091s sys 0m0.452s
because the token expansion goes down dramatically.
In particular, the longest line expansion (which was line 71 of that 'ia_css_ynr.host.c' file) shrinks from 23,338kB (yes, 23MB for one single line) to "just" 1,444kB (now "only" 1.4MB).
And yes, that line is still the line from hell, because it's doing multiple levels of "min()/max()" expansion thanks to some of them being hidden inside the uDIGIT_FITTING() macro.
Lorenzo has a nice cleanup patch that makes that driver use inline functions instead of macros for sDIGIT_FITTING() and uDIGIT_FITTING(), which will fix that line once and for all, but the 16-fold reduction in this case does show why we need to simplify these helpers.
--- include/linux/minmax.h | 43 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-)
include/linux/minmax.h +20 -23
@@ -35,10 +35,10 @@#define __is_noneg_int (x) \ (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0) -#define __types_ok (x, y) \ - (__is_signed(x) == __is_signed(y) || \ - __is_signed((x) + 0) == __is_signed((y) + 0) || \ - __is_noneg_int(x) || __is_noneg_int(y)) +#define __types_ok (x, y, ux, uy) \ + (__is_signed(ux) == __is_signed(uy) || \ + __is_signed((ux) + 0) == __is_signed((uy) + 0) || \ + __is_noneg_int(x) || __is_noneg_int(y))#define __cmp_op_min <#define __cmp_op_max >
@@ -51,34 +51,31 @@#define __cmp_once (op, type, x, y) \ __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __careful_cmp_once (op, x, y) ({ \ - static_assert(__types_ok(x, y), \ +#define __careful_cmp_once (op, x, y, ux, uy) ({ \ + __auto_type ux = (x); __auto_type uy = (y); \ + static_assert(__types_ok(x, y, ux, uy), \ #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp_once(op, __auto_type, x, y); }) + __cmp(op, ux, uy); }) -#define __careful_cmp (op, x, y) \ - __builtin_choose_expr(__is_constexpr((x) - (y)), \ - __cmp(op, x, y), __careful_cmp_once(op, x, y)) +#define __careful_cmp (op, x, y) \ + __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ - typeof(val) unique_val = (val); \ - typeof(lo) unique_lo = (lo); \ - typeof(hi) unique_hi = (hi); \ +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ - static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ - __clamp(unique_val, unique_lo, unique_hi); }) - -#define __careful_clamp (val, lo, hi) ({ \ - __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \ - __clamp(val, lo, hi), \ - __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \ - __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); }) + static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \ + static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** * min - return minimum of two values of the same or compatible types
Signature · 1 line
2.47.3
Patch "minmax: simplify min()/max()/clamp() implementation" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax: simplify min()/max()/clamp() implementation
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax-simplify-min-max-clamp-implementation.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:17:00 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:11 +0000
Subject: minmax: simplify min()/max()/clamp() implementation
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Linus Torvalds <[email protected]>, David Laight <[email protected]>, Lorenzo Stoakes <[email protected]>
Message-ID: <[email protected]>
From: Linus Torvalds <[email protected]>
[ Upstream commit dc1c8034e31b14a2e5e212104ec508aec44ce1b9 ]
Now that we no longer have any C constant expression contexts (ie array size declarations or static initializers) that use min() or max(), we can simpify the implementation by not having to worry about the result staying as a C constant expression.
So now we can unconditionally just use temporary variables of the right type, and get rid of the excessive expansion that used to come from the use of
__builtin_choose_expr(__is_constexpr(...), ..
to pick the specialized code for constant expressions.
Another expansion simplification is to pass the temporary variables (in addition to the original expression) to our __types_ok() macro. That may superficially look like it complicates the macro, but when we only want the type of the expression, expanding the temporary variable names is much simpler and smaller than expanding the potentially complicated original expression.
As a result, on my machine, doing a
$ time make drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.i
goes from
real 0m16.621s user 0m15.360s sys 0m1.221s
to
real 0m2.532s user 0m2.091s sys 0m0.452s
because the token expansion goes down dramatically.
In particular, the longest line expansion (which was line 71 of that 'ia_css_ynr.host.c' file) shrinks from 23,338kB (yes, 23MB for one single line) to "just" 1,444kB (now "only" 1.4MB).
And yes, that line is still the line from hell, because it's doing multiple levels of "min()/max()" expansion thanks to some of them being hidden inside the uDIGIT_FITTING() macro.
Lorenzo has a nice cleanup patch that makes that driver use inline functions instead of macros for sDIGIT_FITTING() and uDIGIT_FITTING(), which will fix that line once and for all, but the 16-fold reduction in this case does show why we need to simplify these helpers.
--- include/linux/minmax.h | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-)
include/linux/minmax.h +20 -23
@@ -35,10 +35,10 @@#define __is_noneg_int (x) \ (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0) -#define __types_ok (x, y) \ - (__is_signed(x) == __is_signed(y) || \ - __is_signed((x) + 0) == __is_signed((y) + 0) || \ - __is_noneg_int(x) || __is_noneg_int(y)) +#define __types_ok (x, y, ux, uy) \ + (__is_signed(ux) == __is_signed(uy) || \ + __is_signed((ux) + 0) == __is_signed((uy) + 0) || \ + __is_noneg_int(x) || __is_noneg_int(y))#define __cmp_op_min <#define __cmp_op_max >
@@ -51,34 +51,31 @@#define __cmp_once (op, type, x, y) \ __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __careful_cmp_once (op, x, y) ({ \ - static_assert(__types_ok(x, y), \ +#define __careful_cmp_once (op, x, y, ux, uy) ({ \ + __auto_type ux = (x); __auto_type uy = (y); \ + static_assert(__types_ok(x, y, ux, uy), \ #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \ - __cmp_once(op, __auto_type, x, y); }) + __cmp(op, ux, uy); }) -#define __careful_cmp (op, x, y) \ - __builtin_choose_expr(__is_constexpr((x) - (y)), \ - __cmp(op, x, y), __careful_cmp_once(op, x, y)) +#define __careful_cmp (op, x, y) \ + __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ - typeof(val) unique_val = (val); \ - typeof(lo) unique_lo = (lo); \ - typeof(hi) unique_hi = (hi); \ +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \ - static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \ - __clamp(unique_val, unique_lo, unique_hi); }) - -#define __careful_clamp (val, lo, hi) ({ \ - __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \ - __clamp(val, lo, hi), \ - __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \ - __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); }) + static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \ + static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** * min - return minimum of two values of the same or compatible types
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 3/11 minmax: improve macro expansion and type checking
In reply to Eliav FarberFrom: Linus Torvalds <[email protected]>
[ Upstream commit 22f5468731491e53356ba7c028f0fdea20b18e2c ]
This clarifies the rules for min()/max()/clamp() type checking and makes them a much more efficient macro expansion.
In particular, we now look at the type and range of the inputs to see whether they work together, generating a mask of acceptable comparisons, and then just verifying that the inputs have a shared case:
- an expression with a signed type can be used for
(1) signed comparisons
(2) unsigned comparisons if it is statically known to have a non-negative value
- an expression with an unsigned type can be used for
(3) unsigned comparison
(4) signed comparisons if the type is smaller than 'int' and thus the C integer promotion rules will make it signed anyway
Here rule (1) and (3) are obvious, and rule (2) is important in order to allow obvious trivial constants to be used together with unsigned values.
Rule (4) is not necessarily a good idea, but matches what we used to do, and we have extant cases of this situation in the kernel. Notably with bcachefs having an expression like
min(bch2_bucket_sectors_dirty(a), ca->mi.bucket_size)
where bch2_bucket_sectors_dirty() returns an 's64', and 'ca->mi.bucket_size' is of type 'u16'.
Technically that bcachefs comparison is clearly sensible on a C type level, because the 'u16' will go through the normal C integer promotion, and become 'int', and then we're comparing two signed values and everything looks sane.
However, it's not entirely clear that a 'min(s64,u16)' operation makes a lot of conceptual sense, and it's possible that we will remove rule (4). After all, the _reason_ we have these complicated type checks is exactly that the C type promotion rules are not very intuitive.
But at least for now the rule is in place for backwards compatibility.
Also note that rule (2) existed before, but is hugely relaxed by this commit. It used to be true only for the simplest compile-time non-negative integer constants. The new macro model will allow cases where the compiler can trivially see that an expression is non-negative even if it isn't necessarily a constant.
For example, the amdgpu driver does
min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
because our old 'min()' macro would see that 'pia[addr] & 0x3F' is of type 'int' and clearly not a C constant expression, so doing a 'min()' with a 'size_t' is a signedness violation.
Our new 'min()' macro still sees that 'pia[addr] & 0x3F' is of type 'int', but is smart enough to also see that it is clearly non-negative, and thus would allow that case without any complaints.
--- include/linux/compiler.h | 9 +++++ include/linux/minmax.h | 74 ++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 15 deletions(-)
include/linux/compiler.h +9 -0
@@ -244,6 +244,15 @@ static inline void *offset_to_ptr(const int *off)*/ #define is_signed_type (type) (((type)(-1)) < (__force type)1) +/* +* Useful shorthand for "is this condition known at compile-time?" +* +* Note that the condition may involve non-constant values, +* but the compiler may know enough about the details of the +* values to determine that the condition is statically true. +*/ +#define statically_true (x) (__builtin_constant_p(x) && (x)) +/* * This is needed in functions which generate the stack canary, see * arch/x86/kernel/smpboot.c::start_secondary() for an example.
include/linux/minmax.h +59 -15
94 lines not on this page · raw message
Signature · 1 line
2.47.3
Patch "minmax: improve macro expansion and type checking" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax: improve macro expansion and type checking
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax-improve-macro-expansion-and-type-checking.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:17:23 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:12 +0000
Subject: minmax: improve macro expansion and type checking
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Linus Torvalds <[email protected]>, Arnd Bergmann <[email protected]>, David Laight <[email protected]>, Lorenzo Stoakes <[email protected]>
Message-ID: <[email protected]>
From: Linus Torvalds <[email protected]>
[ Upstream commit 22f5468731491e53356ba7c028f0fdea20b18e2c ]
This clarifies the rules for min()/max()/clamp() type checking and makes them a much more efficient macro expansion.
In particular, we now look at the type and range of the inputs to see whether they work together, generating a mask of acceptable comparisons, and then just verifying that the inputs have a shared case:
- an expression with a signed type can be used for
(1) signed comparisons
(2) unsigned comparisons if it is statically known to have a non-negative value
- an expression with an unsigned type can be used for
(3) unsigned comparison
(4) signed comparisons if the type is smaller than 'int' and thus the C integer promotion rules will make it signed anyway
Here rule (1) and (3) are obvious, and rule (2) is important in order to allow obvious trivial constants to be used together with unsigned values.
Rule (4) is not necessarily a good idea, but matches what we used to do, and we have extant cases of this situation in the kernel. Notably with bcachefs having an expression like
min(bch2_bucket_sectors_dirty(a), ca->mi.bucket_size)
where bch2_bucket_sectors_dirty() returns an 's64', and 'ca->mi.bucket_size' is of type 'u16'.
Technically that bcachefs comparison is clearly sensible on a C type level, because the 'u16' will go through the normal C integer promotion, and become 'int', and then we're comparing two signed values and everything looks sane.
However, it's not entirely clear that a 'min(s64,u16)' operation makes a lot of conceptual sense, and it's possible that we will remove rule (4). After all, the _reason_ we have these complicated type checks is exactly that the C type promotion rules are not very intuitive.
But at least for now the rule is in place for backwards compatibility.
Also note that rule (2) existed before, but is hugely relaxed by this commit. It used to be true only for the simplest compile-time non-negative integer constants. The new macro model will allow cases where the compiler can trivially see that an expression is non-negative even if it isn't necessarily a constant.
For example, the amdgpu driver does
min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
because our old 'min()' macro would see that 'pia[addr] & 0x3F' is of type 'int' and clearly not a C constant expression, so doing a 'min()' with a 'size_t' is a signedness violation.
Our new 'min()' macro still sees that 'pia[addr] & 0x3F' is of type 'int', but is smart enough to also see that it is clearly non-negative, and thus would allow that case without any complaints.
--- include/linux/compiler.h | 9 +++++ include/linux/minmax.h | 78 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 17 deletions(-)
include/linux/compiler.h +9 -0
@@ -245,6 +245,15 @@ static inline void *offset_to_ptr(const#define is_signed_type (type) (((type)(-1)) < (__force type)1)/* +* Useful shorthand for "is this condition known at compile-time?" +* +* Note that the condition may involve non-constant values, +* but the compiler may know enough about the details of the +* values to determine that the condition is statically true. +*/ +#define statically_true (x) (__builtin_constant_p(x) && (x)) + +/* * This is needed in functions which generate the stack canary, see * arch/x86/kernel/smpboot.c::start_secondary() for an example. */
include/linux/minmax.h +61 -17
96 lines not on this page · raw message
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 4/11 minmax: fix up min3() and max3() too
In reply to Eliav FarberFrom: Linus Torvalds <[email protected]>
[ Upstream commit 21b136cc63d2a9ddd60d4699552b69c214b32964 ]
David Laight pointed out that we should deal with the min3() and max3() mess too, which still does excessive expansion.
And our current macros are actually rather broken.
In particular, the macros did this:
#define min3(x, y, z) min((typeof(x))min(x, y), z) #define max3(x, y, z) max((typeof(x))max(x, y), z)
and that not only is a nested expansion of possibly very complex arguments with all that involves, the typing with that "typeof()" cast is completely wrong.
For example, imagine what happens in max3() if 'x' happens to be a 'unsigned char', but 'y' and 'z' are 'unsigned long'. The types are compatible, and there's no warning - but the result is just random garbage.
No, I don't think we've ever hit that issue in practice, but since we now have sane infrastructure for doing this right, let's just use it. It fixes any excessive expansion, and also avoids these kinds of broken type issues.
--- include/linux/minmax.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
include/linux/minmax.h +10 -2
@@ -152,13 +152,20 @@#define umax (x, y) \ __careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull) +#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ + __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ + BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + #op"3("#x", "#y", "#z") signedness error"); \ + __cmp(op, ux, __cmp(op, uy, uz)); }) +/** * min3 - return minimum of three values * @x: first value * @y: second value * @z: third value */ -#define min3 (x, y, z) min((typeof(x))min(x, y), z) +#define min3 (x, y, z) \ + __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * max3 - return maximum of three values
@@ -166,7 +173,8 @@* @y: second value * @z: third value */ -#define max3 (x, y, z) max((typeof(x))max(x, y), z) +#define max3 (x, y, z) \ + __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero
Signature · 1 line
2.47.3
Patch "minmax: fix up min3() and max3() too" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax: fix up min3() and max3() too
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax-fix-up-min3-and-max3-too.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:17:52 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:13 +0000
Subject: minmax: fix up min3() and max3() too
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Linus Torvalds <[email protected]>, David Laight <[email protected]>, Arnd Bergmann <[email protected]>
Message-ID: <[email protected]>
From: Linus Torvalds <[email protected]>
[ Upstream commit 21b136cc63d2a9ddd60d4699552b69c214b32964 ]
David Laight pointed out that we should deal with the min3() and max3() mess too, which still does excessive expansion.
And our current macros are actually rather broken.
In particular, the macros did this:
#define min3(x, y, z) min((typeof(x))min(x, y), z) #define max3(x, y, z) max((typeof(x))max(x, y), z)
and that not only is a nested expansion of possibly very complex arguments with all that involves, the typing with that "typeof()" cast is completely wrong.
For example, imagine what happens in max3() if 'x' happens to be a 'unsigned char', but 'y' and 'z' are 'unsigned long'. The types are compatible, and there's no warning - but the result is just random garbage.
No, I don't think we've ever hit that issue in practice, but since we now have sane infrastructure for doing this right, let's just use it. It fixes any excessive expansion, and also avoids these kinds of broken type issues.
--- include/linux/minmax.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
include/linux/minmax.h +10 -2
@@ -152,13 +152,20 @@#define umax (x, y) \ __careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull) +#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ + __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ + BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + #op"3("#x", "#y", "#z") signedness error"); \ + __cmp(op, ux, __cmp(op, uy, uz)); }) +/** * min3 - return minimum of three values * @x: first value * @y: second value * @z: third value */ -#define min3 (x, y, z) min((typeof(x))min(x, y), z) +#define min3 (x, y, z) \ + __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * max3 - return maximum of three values
@@ -166,7 +173,8 @@* @y: second value * @z: third value */ -#define max3 (x, y, z) max((typeof(x))max(x, y), z) +#define max3 (x, y, z) \ + __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 5/11 minmax.h: add whitespace around operators and after commas
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit 71ee9b16251ea4bf7c1fe222517c82bdb3220acc ]
Patch series "minmax.h: Cleanups and minor optimisations".
Some tidyups and minor changes to minmax.h.
This patch (of 7):
--- include/linux/minmax.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
include/linux/minmax.h +17 -17
@@ -51,10 +51,10 @@* only need to be careful to not cause warnings for * pointer use. */ -#define __signed_type_use (x,ux) (2+__is_nonneg(x,ux)) -#define __unsigned_type_use (x,ux) (1+2*(sizeof(ux)<4)) -#define __sign_use (x,ux) (is_signed_type(typeof(ux))? \ - __signed_type_use(x,ux):__unsigned_type_use(x,ux)) +#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) +#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* * To avoid warnings about casting pointers to integers
@@ -74,15 +74,15 @@#ifdef CONFIG_64BIT #define __signed_type (ux) long#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) +#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x,ux) statically_true((__signed_type(ux))(x)>=0) +#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) -#define __types_ok (x,y,ux,uy) \ - (__sign_use(x,ux) & __sign_use(y,uy)) +#define __types_ok (x, y, ux, uy) \ + (__sign_use(x, ux) & __sign_use(y, uy)) -#define __types_ok3 (x,y,z,ux,uy,uz) \ - (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz)) +#define __types_ok3 (x, y, z, ux, uy, uz) \ + (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -97,7 +97,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ + BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -114,7 +114,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -154,7 +154,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
@@ -326,9 +326,9 @@ static inline bool in_range32(u32 val, u32 start, u32 len)* Use these carefully: no type checking, and uses the arguments * multiple times. Use for obvious constants only. */ -#define MIN (a,b) __cmp(min,a,b) -#define MAX (a,b) __cmp(max,a,b) -#define MIN_T (type,a,b) __cmp(min,(type)(a),(type)(b)) -#define MAX_T (type,a,b) __cmp(max,(type)(a),(type)(b)) +#define MIN (a, b) __cmp(min, a, b) +#define MAX (a, b) __cmp(max, a, b) +#define MIN_T (type, a, b) __cmp(min, (type)(a), (type)(b)) +#define MAX_T (type, a, b) __cmp(max, (type)(a), (type)(b))#endif /* _LINUX_MINMAX_H */
Signature · 1 line
2.47.3
Patch "minmax.h: add whitespace around operators and after commas" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: add whitespace around operators and after commas
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-add-whitespace-around-operators-and-after-commas.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:18:18 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:14 +0000
Subject: minmax.h: add whitespace around operators and after commas
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit 71ee9b16251ea4bf7c1fe222517c82bdb3220acc ]
Patch series "minmax.h: Cleanups and minor optimisations".
Some tidyups and minor changes to minmax.h.
This patch (of 7):
--- include/linux/minmax.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
include/linux/minmax.h +17 -17
@@ -51,10 +51,10 @@* only need to be careful to not cause warnings for * pointer use. */ -#define __signed_type_use (x,ux) (2+__is_nonneg(x,ux)) -#define __unsigned_type_use (x,ux) (1+2*(sizeof(ux)<4)) -#define __sign_use (x,ux) (is_signed_type(typeof(ux))? \ - __signed_type_use(x,ux):__unsigned_type_use(x,ux)) +#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) +#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* * To avoid warnings about casting pointers to integers
@@ -74,15 +74,15 @@#ifdef CONFIG_64BIT #define __signed_type (ux) long#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L)) +#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x,ux) statically_true((__signed_type(ux))(x)>=0) +#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) -#define __types_ok (x,y,ux,uy) \ - (__sign_use(x,ux) & __sign_use(y,uy)) +#define __types_ok (x, y, ux, uy) \ + (__sign_use(x, ux) & __sign_use(y, uy)) -#define __types_ok3 (x,y,z,ux,uy,uz) \ - (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz)) +#define __types_ok3 (x, y, z, ux, uy, uz) \ + (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -97,7 +97,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \ + BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -114,7 +114,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -154,7 +154,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
@@ -326,9 +326,9 @@ static inline bool in_range32(u32 val, u* Use these carefully: no type checking, and uses the arguments * multiple times. Use for obvious constants only. */ -#define MIN (a,b) __cmp(min,a,b) -#define MAX (a,b) __cmp(max,a,b) -#define MIN_T (type,a,b) __cmp(min,(type)(a),(type)(b)) -#define MAX_T (type,a,b) __cmp(max,(type)(a),(type)(b)) +#define MIN (a, b) __cmp(min, a, b) +#define MAX (a, b) __cmp(max, a, b) +#define MIN_T (type, a, b) __cmp(min, (type)(a), (type)(b)) +#define MAX_T (type, a, b) __cmp(max, (type)(a), (type)(b))#endif /* _LINUX_MINMAX_H */
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 6/11 minmax.h: update some comments
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit 10666e99204818ef45c702469488353b5bb09ec7 ]
- Change three to several.
- Remove the comment about retaining constant expressions, no longer true.
- Realign to nearer 80 columns and break on major punctiation.
- Add a leading comment to the block before __signed_type() and __is_nonneg() Otherwise the block explaining the cast is a bit 'floating'. Reword the rest of that comment to improve readability.
--- include/linux/minmax.h | 53 +++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 29 deletions(-)
include/linux/minmax.h +24 -29
@@ -8,13 +8,10 @@#include <linux/types.h> /* -* min()/max()/clamp() macros must accomplish three things: +* min()/max()/clamp() macros must accomplish several things: * * - Avoid multiple evaluations of the arguments (so side-effects like * "x++" happen only once) when non-constant. -* - Retain result as a constant expressions when called with only -* constant expressions (to avoid tripping VLA warnings in stack -* allocation usage). * - Perform signed v unsigned type-checking (to generate compile * errors instead of nasty runtime surprises). * - Unsigned char/short are always promoted to signed int and can be
@@ -31,25 +28,23 @@* bit #0 set if ok for unsigned comparisons * bit #1 set if ok for signed comparisons * -* In particular, statically non-negative signed integer -* expressions are ok for both. +* In particular, statically non-negative signed integer expressions +* are ok for both. * -* NOTE! Unsigned types smaller than 'int' are implicitly -* converted to 'int' in expressions, and are accepted for -* signed conversions for now. This is debatable. +* NOTE! Unsigned types smaller than 'int' are implicitly converted to 'int' +* in expressions, and are accepted for signed conversions for now. +* This is debatable. * -* Note that 'x' is the original expression, and 'ux' is -* the unique variable that contains the value. +* Note that 'x' is the original expression, and 'ux' is the unique variable +* that contains the value. * -* We use 'ux' for pure type checking, and 'x' for when -* we need to look at the value (but without evaluating -* it for side effects! Careful to only ever evaluate it -* with sizeof() or __builtin_constant_p() etc). +* We use 'ux' for pure type checking, and 'x' for when we need to look at the +* value (but without evaluating it for side effects! +* Careful to only ever evaluate it with sizeof() or __builtin_constant_p() etc). * -* Pointers end up being checked by the normal C type -* rules at the actual comparison, and these expressions -* only need to be careful to not cause warnings for -* pointer use. +* Pointers end up being checked by the normal C type rules at the actual +* comparison, and these expressions only need to be careful to not cause +* warnings for pointer use. */ #define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux))#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4))
@@ -57,19 +52,19 @@ __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* -* To avoid warnings about casting pointers to integers -* of different sizes, we need that special sign type. +* Check whether a signed value is always non-negative. * -* On 64-bit we can just always use 'long', since any -* integer or pointer type can just be cast to that. +* A cast is needed to avoid any warnings from values that aren't signed +* integer types (in which case the result doesn't matter). * -* This does not work for 128-bit signed integers since -* the cast would truncate them, but we do not use s128 -* types in the kernel (we do use 'u128', but they will -* be handled by the !is_signed_type() case). +* On 64-bit any integer or pointer type can safely be cast to 'long'. +* But on 32-bit we need to avoid warnings about casting pointers to integers +* of different sizes without truncating 64-bit values so 'long' or 'long long' +* must be used depending on the size of the value. * -* NOTE! The cast is there only to avoid any warnings -* from when values that aren't signed integer types. +* This does not work for 128-bit signed integers since the cast would truncate +* them, but we do not use s128 types in the kernel (we do use 'u128', +* but they are handled by the !is_signed_type() case). */ #ifdef CONFIG_64BIT #define __signed_type (ux) long
Signature · 1 line
2.47.3
Patch "minmax.h: update some comments" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: update some comments
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-update-some-comments.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:18:49 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:15 +0000
Subject: minmax.h: update some comments
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit 10666e99204818ef45c702469488353b5bb09ec7 ]
- Change three to several.
- Remove the comment about retaining constant expressions, no longer true.
- Realign to nearer 80 columns and break on major punctiation.
- Add a leading comment to the block before __signed_type() and __is_nonneg() Otherwise the block explaining the cast is a bit 'floating'. Reword the rest of that comment to improve readability.
--- include/linux/minmax.h | 61 ++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 33 deletions(-)
include/linux/minmax.h +28 -33
@@ -8,13 +8,10 @@#include <linux/types.h> /* -* min()/max()/clamp() macros must accomplish three things: +* min()/max()/clamp() macros must accomplish several things: * * - Avoid multiple evaluations of the arguments (so side-effects like * "x++" happen only once) when non-constant. -* - Retain result as a constant expressions when called with only -* constant expressions (to avoid tripping VLA warnings in stack -* allocation usage). * - Perform signed v unsigned type-checking (to generate compile * errors instead of nasty runtime surprises). * - Unsigned char/short are always promoted to signed int and can be
@@ -31,25 +28,23 @@* bit #0 set if ok for unsigned comparisons * bit #1 set if ok for signed comparisons * -* In particular, statically non-negative signed integer -* expressions are ok for both. +* In particular, statically non-negative signed integer expressions +* are ok for both. * -* NOTE! Unsigned types smaller than 'int' are implicitly -* converted to 'int' in expressions, and are accepted for -* signed conversions for now. This is debatable. -* -* Note that 'x' is the original expression, and 'ux' is -* the unique variable that contains the value. -* -* We use 'ux' for pure type checking, and 'x' for when -* we need to look at the value (but without evaluating -* it for side effects! Careful to only ever evaluate it -* with sizeof() or __builtin_constant_p() etc). -* -* Pointers end up being checked by the normal C type -* rules at the actual comparison, and these expressions -* only need to be careful to not cause warnings for -* pointer use. +* NOTE! Unsigned types smaller than 'int' are implicitly converted to 'int' +* in expressions, and are accepted for signed conversions for now. +* This is debatable. +* +* Note that 'x' is the original expression, and 'ux' is the unique variable +* that contains the value. +* +* We use 'ux' for pure type checking, and 'x' for when we need to look at the +* value (but without evaluating it for side effects! +* Careful to only ever evaluate it with sizeof() or __builtin_constant_p() etc). +* +* Pointers end up being checked by the normal C type rules at the actual +* comparison, and these expressions only need to be careful to not cause +* warnings for pointer use. */ #define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux))#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4))
@@ -57,19 +52,19 @@ __signed_type_use(x, ux) : __unsigned_type_use(x, ux))/* -* To avoid warnings about casting pointers to integers -* of different sizes, we need that special sign type. +* Check whether a signed value is always non-negative. * -* On 64-bit we can just always use 'long', since any -* integer or pointer type can just be cast to that. +* A cast is needed to avoid any warnings from values that aren't signed +* integer types (in which case the result doesn't matter). * -* This does not work for 128-bit signed integers since -* the cast would truncate them, but we do not use s128 -* types in the kernel (we do use 'u128', but they will -* be handled by the !is_signed_type() case). -* -* NOTE! The cast is there only to avoid any warnings -* from when values that aren't signed integer types. +* On 64-bit any integer or pointer type can safely be cast to 'long'. +* But on 32-bit we need to avoid warnings about casting pointers to integers +* of different sizes without truncating 64-bit values so 'long' or 'long long' +* must be used depending on the size of the value. +* +* This does not work for 128-bit signed integers since the cast would truncate +* them, but we do not use s128 types in the kernel (we do use 'u128', +* but they are handled by the !is_signed_type() case). */ #ifdef CONFIG_64BIT #define __signed_type (ux) long
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 7/11 minmax.h: reduce the #define expansion of min(), max() and clamp()
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit b280bb27a9f7c91ddab730e1ad91a9c18a051f41 ]
Since the test for signed values being non-negative only relies on __builtion_constant_p() (not is_constexpr()) it can use the 'ux' variable instead of the caller supplied expression. This means that the #define parameters are only expanded twice. Once in the code and once quoted in the error message.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -46,10 +46,10 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) -#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) -#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(x, ux) : __unsigned_type_use(x, ux)) +#define __signed_type_use (ux) (2 + __is_nonneg(ux)) +#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(ux) : __unsigned_type_use(ux))/* * Check whether a signed value is always non-negative.
@@ -71,13 +71,13 @@#else #define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) +#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0) -#define __types_ok (x, y, ux, uy) \ - (__sign_use(x, ux) & __sign_use(y, uy)) +#define __types_ok (ux, uy) \ + (__sign_use(ux) & __sign_use(uy)) -#define __types_ok3 (x, y, z, ux, uy, uz) \ - (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz)) +#define __types_ok3 (ux, uy, uz) \ + (__sign_use(ux) & __sign_use(uy) & __sign_use(uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -92,7 +92,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ + BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -109,7 +109,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -149,7 +149,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
Signature · 1 line
2.47.3
Patch "minmax.h: reduce the #define expansion of min(), max() and clamp()" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: reduce the #define expansion of min(), max() and clamp()
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:19:15 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:16 +0000
Subject: minmax.h: reduce the #define expansion of min(), max() and clamp()
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit b280bb27a9f7c91ddab730e1ad91a9c18a051f41 ]
Since the test for signed values being non-negative only relies on __builtion_constant_p() (not is_constexpr()) it can use the 'ux' variable instead of the caller supplied expression. This means that the #define parameters are only expanded twice. Once in the code and once quoted in the error message.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -46,10 +46,10 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (x, ux) (2 + __is_nonneg(x, ux)) -#define __unsigned_type_use (x, ux) (1 + 2 * (sizeof(ux) < 4)) -#define __sign_use (x, ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(x, ux) : __unsigned_type_use(x, ux)) +#define __signed_type_use (ux) (2 + __is_nonneg(ux)) +#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4)) +#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ + __signed_type_use(ux) : __unsigned_type_use(ux))/* * Check whether a signed value is always non-negative.
@@ -71,13 +71,13 @@#else #define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))#endif -#define __is_nonneg (x, ux) statically_true((__signed_type(ux))(x) >= 0) +#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0) -#define __types_ok (x, y, ux, uy) \ - (__sign_use(x, ux) & __sign_use(y, uy)) +#define __types_ok (ux, uy) \ + (__sign_use(ux) & __sign_use(uy)) -#define __types_ok3 (x, y, z, ux, uy, uz) \ - (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz)) +#define __types_ok3 (ux, uy, uz) \ + (__sign_use(ux) & __sign_use(uy) & __sign_use(uz))#define __cmp_op_min <#define __cmp_op_max >
@@ -92,7 +92,7 @@#define __careful_cmp_once (op, x, y, ux, uy) ({ \ __auto_type ux = (x); __auto_type uy = (y); \ - BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \ + BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \ #op"("#x", "#y") signedness error"); \ __cmp(op, ux, uy); })
@@ -109,7 +109,7 @@ static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ (lo) <= (hi), true), \ "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); })
@@ -149,7 +149,7 @@#define __careful_op3 (op, x, y, z, ux, uy, uz) ({ \ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ - BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \ + BUILD_BUG_ON_MSG(!__types_ok3(ux, uy, uz), \ #op"3("#x", "#y", "#z") signedness error"); \ __cmp(op, ux, __cmp(op, uy, uz)); })
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 8/11 minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit a5743f32baec4728711bbc01d6ac2b33d4c67040 ]
Use BUILD_BUG_ON_MSG(statically_true(ulo > uhi), ...) for the sanity check of the bounds in clamp(). Gives better error coverage and one less expansion of the arguments.
--- include/linux/minmax.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
include/linux/minmax.h +1 -2
@@ -106,8 +106,7 @@__auto_type uval = (val); \__auto_type ulo = (lo); \__auto_type uhi = (hi); \ - static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ - (lo) <= (hi), true), \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \
Signature · 1 line
2.47.3
Patch "minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:27:07 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:17 +0000
Subject: minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit a5743f32baec4728711bbc01d6ac2b33d4c67040 ]
Use BUILD_BUG_ON_MSG(statically_true(ulo > uhi), ...) for the sanity check of the bounds in clamp(). Gives better error coverage and one less expansion of the arguments.
--- include/linux/minmax.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
include/linux/minmax.h +1 -2
@@ -106,8 +106,7 @@__auto_type uval = (val); \__auto_type ulo = (lo); \__auto_type uhi = (hi); \ - static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \ - (lo) <= (hi), true), \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 9/11 minmax.h: move all the clamp() definitions after the min/max() ones
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit c3939872ee4a6b8bdcd0e813c66823b31e6e26f7 ]
At some point the definitions for clamp() got added in the middle of the ones for min() and max(). Re-order the definitions so they are more sensibly grouped.
--- include/linux/minmax.h | 109 +++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 58 deletions(-)
include/linux/minmax.h +51 -58
@@ -99,22 +99,6 @@#define __careful_cmp (op, x, y) \ __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __clamp (val, lo, hi) \ - ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) - -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ - BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ - "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ - "clamp("#val", "#lo", "#hi") signedness error"); \ - __clamp(uval, ulo, uhi); }) - -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) -/** * min - return minimum of two values of the same or compatible types * @x: first value
@@ -170,6 +154,22 @@#define max3 (x, y, z) \ __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_)) +/** +* min_t - return minimum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value +*/ +#define min_t (type, x, y) __cmp_once(min, type, x, y) + +/** +* max_t - return maximum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value +*/ +#define max_t (type, x, y) __cmp_once(max, type, x, y) +/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero * @x: value1
@@ -180,6 +180,22 @@typeof (y) __y = (y); \ __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) +#define __clamp (val, lo, hi) \ + ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) + +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ + "clamp() low limit " #lo " greater than high limit " #hi); \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ + "clamp("#val", "#lo", "#hi") signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +/** * clamp - return a value clamped to a given range with strict typechecking * @val: current value
@@ -191,28 +207,30 @@*/ #define clamp (val, lo, hi) __careful_clamp(val, lo, hi) -/* -* ..and if you can't take the strict -* types, you can specify one yourself. -* -* Or not use min/max/clamp at all, of course. -*/ -/** -* min_t - return minimum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_t - return a value clamped to a given range using a given type +* @type: the type of variable to use +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of type +* @type to make all the comparisons. */ -#define min_t (type, x, y) __cmp_once(min, type, x, y) +#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))/** -* max_t - return maximum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_val - return a value clamped to a given range using val's type +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of whatever +* type the input argument @val is. This is useful when @val is an unsigned +* type and @lo and @hi are literals that will otherwise be assigned a signed +* integer type. */ -#define max_t (type, x, y) __cmp_once(max, type, x, y) +#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
@@ -257,31 +275,6 @@*/ #define max_array (array, len) __minmax_array(max, array, len) -/** -* clamp_t - return a value clamped to a given range using a given type -* @type: the type of variable to use -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of type -* @type to make all the comparisons. -*/ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) - -/** -* clamp_val - return a value clamped to a given range using val's type -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of whatever -* type the input argument @val is. This is useful when @val is an unsigned -* type and @lo and @hi are literals that will otherwise be assigned a signed -* integer type. -*/ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) -static inline bool in_range64 (u64 val,u64 start,u64 len) {return (val - start) < len;
Signature · 1 line
2.47.3
Patch "minmax.h: move all the clamp() definitions after the min/max() ones" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: move all the clamp() definitions after the min/max() ones
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:29:47 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:18 +0000
Subject: minmax.h: move all the clamp() definitions after the min/max() ones
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit c3939872ee4a6b8bdcd0e813c66823b31e6e26f7 ]
At some point the definitions for clamp() got added in the middle of the ones for min() and max(). Re-order the definitions so they are more sensibly grouped.
--- include/linux/minmax.h | 109 ++++++++++++++++++++++--------------------------- 1 file changed, 51 insertions(+), 58 deletions(-)
include/linux/minmax.h +51 -58
@@ -99,22 +99,6 @@#define __careful_cmp (op, x, y) \ __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) -#define __clamp (val, lo, hi) \ - ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) - -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ - BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ - "clamp() low limit " #lo " greater than high limit " #hi); \ - BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ - "clamp("#val", "#lo", "#hi") signedness error"); \ - __clamp(uval, ulo, uhi); }) - -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) -/** * min - return minimum of two values of the same or compatible types * @x: first value
@@ -171,6 +155,22 @@__careful_op3 (max, x, y, z,__UNIQUE_ID (x_),__UNIQUE_ID (y_),__UNIQUE_ID (z_))/** +* min_t - return minimum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value + */ +#define min_t (type, x, y) __cmp_once(min, type, x, y) + +/** +* max_t - return maximum of two values, using the specified type +* @type: data type to use +* @x: first value +* @y: second value +*/ +#define max_t (type, x, y) __cmp_once(max, type, x, y) + +/** * min_not_zero - return the minimum that is _not_ zero, unless both are zero * @x: value1 * @y: value2
@@ -180,6 +180,22 @@typeof (y) __y = (y); \ __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) +#define __clamp (val, lo, hi) \ + ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) + +#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ + __auto_type uval = (val); \ + __auto_type ulo = (lo); \ + __auto_type uhi = (hi); \ + BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ + "clamp() low limit " #lo " greater than high limit " #hi); \ + BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ + "clamp("#val", "#lo", "#hi") signedness error"); \ + __clamp(uval, ulo, uhi); }) + +#define __careful_clamp (val, lo, hi) \ + __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +/** * clamp - return a value clamped to a given range with strict typechecking * @val: current value
@@ -191,28 +207,30 @@*/ #define clamp (val, lo, hi) __careful_clamp(val, lo, hi) -/* -* ..and if you can't take the strict -* types, you can specify one yourself. -* -* Or not use min/max/clamp at all, of course. -*/ -/** -* min_t - return minimum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_t - return a value clamped to a given range using a given type +* @type: the type of variable to use +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of type +* @type to make all the comparisons. */ -#define min_t (type, x, y) __cmp_once(min, type, x, y) +#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))/** -* max_t - return maximum of two values, using the specified type -* @type: data type to use -* @x: first value -* @y: second value +* clamp_val - return a value clamped to a given range using val's type +* @val: current value +* @lo: minimum allowable value +* @hi: maximum allowable value +* +* This macro does no typechecking and uses temporary variables of whatever +* type the input argument @val is. This is useful when @val is an unsigned +* type and @lo and @hi are literals that will otherwise be assigned a signed +* integer type. */ -#define max_t (type, x, y) __cmp_once(max, type, x, y) +#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
@@ -257,31 +275,6 @@*/ #define max_array (array, len) __minmax_array(max, array, len) -/** -* clamp_t - return a value clamped to a given range using a given type -* @type: the type of variable to use -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of type -* @type to make all the comparisons. -*/ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) - -/** -* clamp_val - return a value clamped to a given range using val's type -* @val: current value -* @lo: minimum allowable value -* @hi: maximum allowable value -* -* This macro does no typechecking and uses temporary variables of whatever -* type the input argument @val is. This is useful when @val is an unsigned -* type and @lo and @hi are literals that will otherwise be assigned a signed -* integer type. -*/ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) -static inline bool in_range64 (u64 val,u64 start,u64 len) {return (val - start) < len;
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 10/11 minmax.h: simplify the variants of clamp()
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit 495bba17cdf95e9703af1b8ef773c55ef0dfe703 ]
Always pass a 'type' through to __clamp_once(), pass '__auto_type' from clamp() itself.
The expansion of __types_ok3() is reasonable so it isn't worth the added complexity of avoiding it when a fixed type is used for all three values.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -183,29 +183,29 @@#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ +#define __clamp_once (type, val, lo, hi, uval, ulo, uhi) ({ \ + type uval = (val); \ + type ulo = (lo); \ + type uhi = (hi); \ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); }) -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +#define __careful_clamp (type, val, lo, hi) \ + __clamp_once(type, val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** -* clamp - return a value clamped to a given range with strict typechecking +* clamp - return a value clamped to a given range with typechecking * @val: current value * @lo: lowest allowable value * @hi: highest allowable value * -* This macro does strict typechecking of @lo/@hi to make sure they are of the -* same type as @val. See the unnecessary pointer comparisons. +* This macro checks @val/@lo/@hi to make sure they have compatible +* signedness. */ -#define clamp (val, lo, hi) __careful_clamp(val, lo, hi) +#define clamp (val, lo, hi) __careful_clamp(__auto_type, val, lo, hi)/** * clamp_t - return a value clamped to a given range using a given type
@@ -217,7 +217,7 @@* This macro does no typechecking and uses temporary variables of type * @type to make all the comparisons. */ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) +#define clamp_t (type, val, lo, hi) __careful_clamp(type, val, lo, hi)/** * clamp_val - return a value clamped to a given range using val's type
@@ -230,7 +230,7 @@* type and @lo and @hi are literals that will otherwise be assigned a signed * integer type. */ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) +#define clamp_val (val, lo, hi) __careful_clamp(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
Signature · 1 line
2.47.3
Patch "minmax.h: simplify the variants of clamp()" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: simplify the variants of clamp()
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-simplify-the-variants-of-clamp.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:28:17 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:19 +0000
Subject: minmax.h: simplify the variants of clamp()
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit 495bba17cdf95e9703af1b8ef773c55ef0dfe703 ]
Always pass a 'type' through to __clamp_once(), pass '__auto_type' from clamp() itself.
The expansion of __types_ok3() is reasonable so it isn't worth the added complexity of avoiding it when a fixed type is used for all three values.
--- include/linux/minmax.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-)
include/linux/minmax.h +12 -12
@@ -183,29 +183,29 @@#define __clamp (val, lo, hi) \ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) -#define __clamp_once (val, lo, hi, uval, ulo, uhi) ({ \ - __auto_type uval = (val); \ - __auto_type ulo = (lo); \ - __auto_type uhi = (hi); \ +#define __clamp_once (type, val, lo, hi, uval, ulo, uhi) ({ \ + type uval = (val); \ + type ulo = (lo); \ + type uhi = (hi); \ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \ "clamp() low limit " #lo " greater than high limit " #hi); \ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \ "clamp("#val", "#lo", "#hi") signedness error"); \ __clamp(uval, ulo, uhi); }) -#define __careful_clamp (val, lo, hi) \ - __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_)) +#define __careful_clamp (type, val, lo, hi) \ + __clamp_once(type, val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))/** -* clamp - return a value clamped to a given range with strict typechecking +* clamp - return a value clamped to a given range with typechecking * @val: current value * @lo: lowest allowable value * @hi: highest allowable value * -* This macro does strict typechecking of @lo/@hi to make sure they are of the -* same type as @val. See the unnecessary pointer comparisons. +* This macro checks @val/@lo/@hi to make sure they have compatible +* signedness. */ -#define clamp (val, lo, hi) __careful_clamp(val, lo, hi) +#define clamp (val, lo, hi) __careful_clamp(__auto_type, val, lo, hi)/** * clamp_t - return a value clamped to a given range using a given type
@@ -217,7 +217,7 @@* This macro does no typechecking and uses temporary variables of type * @type to make all the comparisons. */ -#define clamp_t (type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) +#define clamp_t (type, val, lo, hi) __careful_clamp(type, val, lo, hi)/** * clamp_val - return a value clamped to a given range using val's type
@@ -230,7 +230,7 @@* type and @lo and @hi are literals that will otherwise be assigned a signed * integer type. */ -#define clamp_val (val, lo, hi) clamp_t(typeof(val), val, lo, hi) +#define clamp_val (val, lo, hi) __careful_clamp(typeof(val), val, lo, hi)/* * Do not check the array parameter using __must_be_array().
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch
PATCH v4 11/11 minmax.h: remove some #defines that are only expanded once
In reply to Eliav FarberFrom: David Laight <[email protected]>
[ Upstream commit 2b97aaf74ed534fb838d09867d09a3ca5d795208 ]
The bodies of __signed_type_use() and __unsigned_type_use() are much the same size as their names - so put the bodies in the only line that expands them.
Similarly __signed_type() is defined separately for 64bit and then used exactly once just below.
Change the test for __signed_type from CONFIG_64BIT to one based on gcc defined macros so that the code is valid if it gets used outside of a kernel build.
--- include/linux/minmax.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
include/linux/minmax.h +6 -8
@@ -46,10 +46,8 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (ux) (2 + __is_nonneg(ux)) -#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4))#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(ux) : __unsigned_type_use(ux)) + (2 + __is_nonneg(ux)) : (1 + 2 * (sizeof(ux) < 4)))/* * Check whether a signed value is always non-negative.
@@ -57,7 +55,7 @@* A cast is needed to avoid any warnings from values that aren't signed * integer types (in which case the result doesn't matter). * -* On 64-bit any integer or pointer type can safely be cast to 'long'. +* On 64-bit any integer or pointer type can safely be cast to 'long long'. * But on 32-bit we need to avoid warnings about casting pointers to integers * of different sizes without truncating 64-bit values so 'long' or 'long long' * must be used depending on the size of the value.
@@ -66,12 +64,12 @@* them, but we do not use s128 types in the kernel (we do use 'u128', * but they are handled by the !is_signed_type() case). */ -#ifdef CONFIG_64BIT -#define __signed_type (ux) long +#if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__ +#define __is_nonneg (ux) statically_true((long long)(ux) >= 0)#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)) +#define __is_nonneg (ux) statically_true( \ + (typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)))(ux) >= 0)#endif -#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0)#define __types_ok (ux, uy) \ (__sign_use(ux) & __sign_use(uy))
Signature · 1 line
2.47.3
Patch "minmax.h: remove some #defines that are only expanded once" has been added to the 6.1-stable tree
This is a note to let you know that I've just added the patch titled
minmax.h: remove some #defines that are only expanded once
to the 6.1-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
minmax.h-remove-some-defines-that-are-only-expanded-once.patch
and it can be found in the queue-6.1 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
From [email protected] Fri Oct 3 14:27:55 2025
From: Eliav Farber <[email protected]>
Date: Fri, 3 Oct 2025 12:15:20 +0000
Subject: minmax.h: remove some #defines that are only expanded once
To: <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>, <[email protected]>
Cc: Arnd Bergmann <[email protected]>, Christoph Hellwig <[email protected]>, Dan Carpenter <[email protected]>, "Jason A. Donenfeld" <[email protected]>, Jens Axboe <[email protected]>, Lorenzo Stoakes <[email protected]>, Mateusz Guzik <[email protected]>, "Matthew Wilcox" <[email protected]>, Pedro Falcato <[email protected]>
Message-ID: <[email protected]>
From: David Laight <[email protected]>
[ Upstream commit 2b97aaf74ed534fb838d09867d09a3ca5d795208 ]
The bodies of __signed_type_use() and __unsigned_type_use() are much the same size as their names - so put the bodies in the only line that expands them.
Similarly __signed_type() is defined separately for 64bit and then used exactly once just below.
Change the test for __signed_type from CONFIG_64BIT to one based on gcc defined macros so that the code is valid if it gets used outside of a kernel build.
--- include/linux/minmax.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
include/linux/minmax.h +6 -8
@@ -46,10 +46,8 @@* comparison, and these expressions only need to be careful to not cause * warnings for pointer use. */ -#define __signed_type_use (ux) (2 + __is_nonneg(ux)) -#define __unsigned_type_use (ux) (1 + 2 * (sizeof(ux) < 4))#define __sign_use (ux) (is_signed_type(typeof(ux)) ? \ - __signed_type_use(ux) : __unsigned_type_use(ux)) + (2 + __is_nonneg(ux)) : (1 + 2 * (sizeof(ux) < 4)))/* * Check whether a signed value is always non-negative.
@@ -57,7 +55,7 @@* A cast is needed to avoid any warnings from values that aren't signed * integer types (in which case the result doesn't matter). * -* On 64-bit any integer or pointer type can safely be cast to 'long'. +* On 64-bit any integer or pointer type can safely be cast to 'long long'. * But on 32-bit we need to avoid warnings about casting pointers to integers * of different sizes without truncating 64-bit values so 'long' or 'long long' * must be used depending on the size of the value.
@@ -66,12 +64,12 @@* them, but we do not use s128 types in the kernel (we do use 'u128', * but they are handled by the !is_signed_type() case). */ -#ifdef CONFIG_64BIT -#define __signed_type (ux) long +#if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__ +#define __is_nonneg (ux) statically_true((long long)(ux) >= 0)#else -#define __signed_type (ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)) +#define __is_nonneg (ux) statically_true( \ + (typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)))(ux) >= 0)#endif -#define __is_nonneg (ux) statically_true((__signed_type(ux))(ux) >= 0)#define __types_ok (ux, uy) \ (__sign_use(ux) & __sign_use(uy))
Patches currently in stable-queue which might be from [email protected] are
queue-6.1/minmax-improve-macro-expansion-and-type-checking.patch queue-6.1/minmax.h-simplify-the-variants-of-clamp.patch queue-6.1/minmax.h-move-all-the-clamp-definitions-after-the-min-max-ones.patch queue-6.1/minmax-don-t-use-max-in-situations-that-want-a-c-constant-expression.patch queue-6.1/minmax.h-remove-some-defines-that-are-only-expanded-once.patch queue-6.1/minmax.h-use-build_bug_on_msg-for-the-lo-hi-test-in-clamp.patch queue-6.1/minmax-simplify-min-max-clamp-implementation.patch queue-6.1/minmax.h-add-whitespace-around-operators-and-after-commas.patch queue-6.1/minmax-fix-up-min3-and-max3-too.patch queue-6.1/minmax.h-reduce-the-define-expansion-of-min-max-and-clamp.patch queue-6.1/minmax.h-update-some-comments.patch