[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250614222633.77a7d242@pumpkin>
Date: Sat, 14 Jun 2025 22:26:33 +0100
From: David Laight <david.laight.linux@...il.com>
To: Nicolas Pitre <nico@...xnic.net>
Cc: Andrew Morton <akpm@...ux-foundation.org>, linux-kernel@...r.kernel.org,
u.kleine-koenig@...libre.com, Oleg Nesterov <oleg@...hat.com>, Peter
Zijlstra <peterz@...radead.org>, Biju Das <biju.das.jz@...renesas.com>,
Nicolas Pitre <npitre@...libre.com>
Subject: Re: [PATCH v3 next 02/10] lib: mul_u64_u64_div_u64() Use
WARN_ONCE() for divide errors.
On Sat, 14 Jun 2025 11:17:33 -0400 (EDT)
Nicolas Pitre <nico@...xnic.net> wrote:
> On Sat, 14 Jun 2025, David Laight wrote:
>
> > Do an explicit WARN_ONCE(!divisor) instead of hoping the 'undefined
> > behaviour' the compiler generates for a compile-time 1/0 is in any
> > way useful.
> >
> > Return 0 (rather than ~(u64)0) because it is less likely to cause
> > further serious issues.
>
> I still disagree with this patch. Whether or not what the compiler
> produces is useful is beside the point. What's important here is to have
> a coherent behavior across all division flavors and what's proposed here
> is not.
>
> Arguably, a compile time 1/0 might not be what we want either. The
> compiler forces an "illegal instruction" exception when what we want is
> a "floating point" exception (strange to have floating point exceptions
> for integer divisions but that's what it is).
>
> So I'd suggest the following instead:
>
> ----- >8
> From Nicolas Pitre <npitre@...libre.com>
> Subject: [PATCH] mul_u64_u64_div_u64(): improve division-by-zero handling
>
> Forcing 1/0 at compile time makes the compiler (on x86 at least) to emit
> an undefined instruction to trigger the exception. But that's not what
> we want. Modify the code so that an actual runtime div-by-0 exception
> is triggered to be coherent with the behavior of all the other division
> flavors.
>
> And don't use 1 for the dividend as the compiler would convert the
> actual division into a simple compare.
The alternative would be BUG() or BUG_ON() - but Linus really doesn't
like those unless there is no alternative.
I'm pretty sure that both divide overflow (quotient too large) and
divide by zero are 'Undefined behaviour' in C.
Unless the compiler detects and does something 'strange' it becomes
cpu architecture defined.
It is actually a right PITA that many cpu trap for overflow
and/or divide by zero (x86 traps for both, m68k traps for divide by
zero but sets the overflow flag for overflow (with unchanged outputs),
can't find my arm book, sparc doesn't have divide).
David
>
> Signed-off-by: Nicolas Pitre <npitre@...libre.com>
>
> diff --git a/lib/math/div64.c b/lib/math/div64.c
> index 5faa29208bdb..e6839b40e271 100644
> --- a/lib/math/div64.c
> +++ b/lib/math/div64.c
> @@ -212,12 +212,12 @@ u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c)
>
> #endif
>
> - /* make sure c is not zero, trigger exception otherwise */
> -#pragma GCC diagnostic push
> -#pragma GCC diagnostic ignored "-Wdiv-by-zero"
> - if (unlikely(c == 0))
> - return 1/0;
> -#pragma GCC diagnostic pop
> + /* make sure c is not zero, trigger runtime exception otherwise */
> + if (unlikely(c == 0)) {
> + unsigned long zero = 0;
> + asm ("" : "+r" (zero)); /* hide actual value from the compiler */
> + return ~0UL/zero;
> + }
>
> int shift = __builtin_ctzll(c);
>
Powered by blists - more mailing lists