diff mbox series

[1/2] selftests: Provide local define of min() and max()

Message ID 20230819195005.99387-2-mahmoudmatook.mm@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Netdev Maintainers
Headers show
Series selftests: Introduce common min()/max() and apply them in net tests | expand

Checks

Context Check Description
netdev/tree_selection success Guessing tree name failed - patch did not apply

Commit Message

Mahmoud Matook Aug. 19, 2023, 7:50 p.m. UTC
to avoid manual calculation of min and max values
and fix coccinelle warnings such WARNING opportunity for min()/max()
adding one common definition that could be used in multiple files
under selftests.
there are also some defines for min/max scattered locally inside sources
under selftests.
this also prepares for cleaning up those redundant defines and include
kselftest.h instead.

Signed-off-by: Mahmoud Maatuq <mahmoudmatook.mm@gmail.com>
---
 tools/testing/selftests/kselftest.h | 7 +++++++
 1 file changed, 7 insertions(+)

Comments

Willem de Bruijn Aug. 20, 2023, 3:15 p.m. UTC | #1
Mahmoud Maatuq wrote:
> to avoid manual calculation of min and max values
> and fix coccinelle warnings such WARNING opportunity for min()/max()
> adding one common definition that could be used in multiple files
> under selftests.
> there are also some defines for min/max scattered locally inside sources
> under selftests.
> this also prepares for cleaning up those redundant defines and include
> kselftest.h instead.
> 
> Signed-off-by: Mahmoud Maatuq <mahmoudmatook.mm@gmail.com>
> ---
>  tools/testing/selftests/kselftest.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
> index 829be379545a..e8eb7e9afbc6 100644
> --- a/tools/testing/selftests/kselftest.h
> +++ b/tools/testing/selftests/kselftest.h
> @@ -55,6 +55,13 @@
>  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
>  #endif
>  
> +#ifndef min
> +# define min(x, y) ((x) < (y) ? (x) : (y))
> +#endif
> +#ifndef max
> +# define max(x, y) ((x) < (y) ? (y) : (x))
> +#endif
> +

Should this more closely follow include/linux/minmax.h, which is a lot
more strict?

I'm fine with this simpler, more relaxed, version for testing, but
calling it out for people to speak up.

Only the first two of these comments in minmax.h apply to this
userspace code.

/*
 * min()/max()/clamp() macros must accomplish three things:
 *
 * - avoid multiple evaluations of the arguments (so side-effects like
 *   "x++" happen only once) when non-constant.
 * - perform strict type-checking (to generate warnings instead of
 *   nasty runtime surprises). See the "unnecessary" pointer comparison
 *   in __typecheck().
 * - retain result as a constant expressions when called with only
 *   constant expressions (to avoid tripping VLA warnings in stack
 *   allocation usage).
 */

Note that a more strict version that includes __typecheck would
warn on the type difference between total_len and cfg_mss. Fine
with changing the type of cfg_mss in the follow-on patch to address
that.
David Laight Aug. 21, 2023, 1:04 p.m. UTC | #2
From: Willem de Bruijn
> Sent: Sunday, August 20, 2023 4:15 PM
> 
> Mahmoud Maatuq wrote:
> > to avoid manual calculation of min and max values
> > and fix coccinelle warnings such WARNING opportunity for min()/max()
> > adding one common definition that could be used in multiple files
> > under selftests.
> > there are also some defines for min/max scattered locally inside sources
> > under selftests.
> > this also prepares for cleaning up those redundant defines and include
> > kselftest.h instead.
> >
> > Signed-off-by: Mahmoud Maatuq <mahmoudmatook.mm@gmail.com>
> > ---
> >  tools/testing/selftests/kselftest.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
> > index 829be379545a..e8eb7e9afbc6 100644
> > --- a/tools/testing/selftests/kselftest.h
> > +++ b/tools/testing/selftests/kselftest.h
> > @@ -55,6 +55,13 @@
> >  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> >  #endif
> >
> > +#ifndef min
> > +# define min(x, y) ((x) < (y) ? (x) : (y))
> > +#endif
> > +#ifndef max
> > +# define max(x, y) ((x) < (y) ? (y) : (x))
> > +#endif
> > +
> 
> Should this more closely follow include/linux/minmax.h, which is a lot
> more strict?
> 
> I'm fine with this simpler, more relaxed, version for testing, but
> calling it out for people to speak up.
> 
> Only the first two of these comments in minmax.h apply to this
> userspace code.
> 
> /*
>  * min()/max()/clamp() macros must accomplish three things:
>  *
>  * - avoid multiple evaluations of the arguments (so side-effects like
>  *   "x++" happen only once) when non-constant.
>  * - perform strict type-checking (to generate warnings instead of
>  *   nasty runtime surprises). See the "unnecessary" pointer comparison
>  *   in __typecheck().
>  * - retain result as a constant expressions when called with only
>  *   constant expressions (to avoid tripping VLA warnings in stack
>  *   allocation usage).
>  */
> 
> Note that a more strict version that includes __typecheck would
> warn on the type difference between total_len and cfg_mss. Fine
> with changing the type of cfg_mss in the follow-on patch to address
> that.

That typecheck() is horrid.
It may well have caused more bugs due to incorrect casts that
it actually detected.

I'd suggest the version that just avoids multiple evaluations.
Or just error signed v unsigned comparisons.
See  https://lore.kernel.org/all/b4ce9dad748e489f9314a2dc95615033@AcuMS.aculab.com/
for an example patch set.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Willem de Bruijn Aug. 22, 2023, 2:34 p.m. UTC | #3
On Mon, Aug 21, 2023 at 9:05 AM David Laight <David.Laight@aculab.com> wrote:
>
> From: Willem de Bruijn
> > Sent: Sunday, August 20, 2023 4:15 PM
> >
> > Mahmoud Maatuq wrote:
> > > to avoid manual calculation of min and max values
> > > and fix coccinelle warnings such WARNING opportunity for min()/max()
> > > adding one common definition that could be used in multiple files
> > > under selftests.
> > > there are also some defines for min/max scattered locally inside sources
> > > under selftests.
> > > this also prepares for cleaning up those redundant defines and include
> > > kselftest.h instead.
> > >
> > > Signed-off-by: Mahmoud Maatuq <mahmoudmatook.mm@gmail.com>
> > > ---
> > >  tools/testing/selftests/kselftest.h | 7 +++++++
> > >  1 file changed, 7 insertions(+)
> > >
> > > diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
> > > index 829be379545a..e8eb7e9afbc6 100644
> > > --- a/tools/testing/selftests/kselftest.h
> > > +++ b/tools/testing/selftests/kselftest.h
> > > @@ -55,6 +55,13 @@
> > >  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
> > >  #endif
> > >
> > > +#ifndef min
> > > +# define min(x, y) ((x) < (y) ? (x) : (y))
> > > +#endif
> > > +#ifndef max
> > > +# define max(x, y) ((x) < (y) ? (y) : (x))
> > > +#endif
> > > +
> >
> > Should this more closely follow include/linux/minmax.h, which is a lot
> > more strict?
> >
> > I'm fine with this simpler, more relaxed, version for testing, but
> > calling it out for people to speak up.
> >
> > Only the first two of these comments in minmax.h apply to this
> > userspace code.
> >
> > /*
> >  * min()/max()/clamp() macros must accomplish three things:
> >  *
> >  * - avoid multiple evaluations of the arguments (so side-effects like
> >  *   "x++" happen only once) when non-constant.
> >  * - perform strict type-checking (to generate warnings instead of
> >  *   nasty runtime surprises). See the "unnecessary" pointer comparison
> >  *   in __typecheck().
> >  * - retain result as a constant expressions when called with only
> >  *   constant expressions (to avoid tripping VLA warnings in stack
> >  *   allocation usage).
> >  */
> >
> > Note that a more strict version that includes __typecheck would
> > warn on the type difference between total_len and cfg_mss. Fine
> > with changing the type of cfg_mss in the follow-on patch to address
> > that.
>
> That typecheck() is horrid.
> It may well have caused more bugs due to incorrect casts that
> it actually detected.
>
> I'd suggest the version that just avoids multiple evaluations.
> Or just error signed v unsigned comparisons.
> See  https://lore.kernel.org/all/b4ce9dad748e489f9314a2dc95615033@AcuMS.aculab.com/
> for an example patch set.

Interesting, thanks. That is also simpler.

Also, the existing patch is no worse than the open coded code today,
so even without code to avoid multiple evaluations, I guess it's okay
to merge.

The coccinelle warnings are arguably false positives, using checks for
kernel code, but being run against userspace code that has no access
to those helpers. But fine to silence them.
David Laight Aug. 22, 2023, 2:48 p.m. UTC | #4
...
> > That typecheck() is horrid.
> > It may well have caused more bugs due to incorrect casts that
> > it actually detected.
> >
> > I'd suggest the version that just avoids multiple evaluations.
> > Or just error signed v unsigned comparisons.
> > See  https://lore.kernel.org/all/b4ce9dad748e489f9314a2dc95615033@AcuMS.aculab.com/
> > for an example patch set.
> 
> Interesting, thanks. That is also simpler.
> 
> Also, the existing patch is no worse than the open coded code today,
> so even without code to avoid multiple evaluations, I guess it's okay
> to merge.
> 
> The coccinelle warnings are arguably false positives, using checks for
> kernel code, but being run against userspace code that has no access
> to those helpers. But fine to silence them.

You can't use is_constexpr() unless 'sizeof *(void *)' is valid.
And builtin_constant() isn't good enough for builtin_choose_expr().

That might be ok for selftests and tools, but not for generaluserspace.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Mahmoud Matook Aug. 23, 2023, 7:35 p.m. UTC | #5
On 08/22, David Laight wrote:

> ...
> > > That typecheck() is horrid.
> > > It may well have caused more bugs due to incorrect casts that
> > > it actually detected.
> > >
> > > I'd suggest the version that just avoids multiple evaluations.
> > > Or just error signed v unsigned comparisons.
> > > See  https://lore.kernel.org/all/b4ce9dad748e489f9314a2dc95615033@AcuMS.aculab.com/
> > > for an example patch set.
> > 
> > Interesting, thanks. That is also simpler.
> > 
> > Also, the existing patch is no worse than the open coded code today,
> > so even without code to avoid multiple evaluations, I guess it's okay
> > to merge.
> > 
> > The coccinelle warnings are arguably false positives, using checks for
> > kernel code, but being run against userspace code that has no access
> > to those helpers. But fine to silence them.
> 
> You can't use is_constexpr() unless 'sizeof *(void *)' is valid.
> And builtin_constant() isn't good enough for builtin_choose_expr().
> 
> That might be ok for selftests and tools, but not for generaluserspace.
> 
> 	David
> 
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)
I tried to use the relaxed version provided in the shared patchset link 
besides not able to use is_constexpr(), I'm not able to use
__UNIQUE_ID() also. It's definded inside include/linux/compiler-gcc.h
and it uses another macro __PASTE() which is defined inside
include/linux/compiler_types.h. 
not sure what to do next
- bring those macros definitions to able to use the relaxed version.
- if the most important point for min/max defines inside selftests is to
  avoid multiple evaluation is the below version acceptable?
  /*
  #define min(x, y) ({ \
    typeof(x) _x = (x); \
    typeof(y) _y = (y); \
    _x < _y ? _x : _y; \
})

#define max(x, y) ({ \
    typeof(x) _x = (x); \
    typeof(y) _y = (y); \
    _x > _y ? _x : _y; \
})
*/
David Laight Aug. 24, 2023, 8:53 a.m. UTC | #6
From: Mahmoud Matook
> Sent: Wednesday, August 23, 2023 8:36 PM
...
> I tried to use the relaxed version provided in the shared patchset link
> besides not able to use is_constexpr(), I'm not able to use
> __UNIQUE_ID() also. It's definded inside include/linux/compiler-gcc.h
> and it uses another macro __PASTE() which is defined inside
> include/linux/compiler_types.h.
> not sure what to do next
>
> - bring those macros definitions to able to use the relaxed version.
> - if the most important point for min/max defines inside selftests is to
>   avoid multiple evaluation is the below version acceptable?
>
>   #define min(x, y) ({ \
>     typeof(x) _x = (x); \
>     typeof(y) _y = (y); \
>     _x < _y ? _x : _y; \
> })
> 
> #define max(x, y) ({ \
>     typeof(x) _x = (x); \
>     typeof(y) _y = (y); \
>     _x > _y ? _x : _y; \
> })

Those are a reasonable pair.

If you want a signed-ness check the:
	_Static_assert(is_signed_type(typeof(a)) == is_signed_type(typeof(b)), "min/max signednesss")
check should just drop into the above.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
diff mbox series

Patch

diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
index 829be379545a..e8eb7e9afbc6 100644
--- a/tools/testing/selftests/kselftest.h
+++ b/tools/testing/selftests/kselftest.h
@@ -55,6 +55,13 @@ 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 #endif
 
+#ifndef min
+# define min(x, y) ((x) < (y) ? (x) : (y))
+#endif
+#ifndef max
+# define max(x, y) ((x) < (y) ? (y) : (x))
+#endif
+
 /*
  * gcc cpuid.h provides __cpuid_count() since v4.4.
  * Clang/LLVM cpuid.h provides  __cpuid_count() since v3.4.0.