[U-Boot] [PATCH v7 03/23] Add abs() macro to return absolute value

Simon Glass sjg at chromium.org
Fri May 11 23:08:27 CEST 2012


Hi Wolfgang,

On Fri, May 11, 2012 at 1:13 PM, Wolfgang Denk <wd at denx.de> wrote:

> Dear Simon Glass,
>
> In message <CAPnjgZ2hep7ApaNMakKrAEpCPffQ74BogGo=
> GnWTy47akewXTQ at mail.gmail.com> you wrote:
> >
> > So I will go back to the more complicated way, and this time just copy
> what
> > the kernel does. The difference is that it doesn't use typeof().
>
> I have to admit that I tend to prefer the typeof() version, and I
> wonder why the kernel doesn;t use that.  I guess there are reasons for
> that.  Does anybody know what these might be?
>

Not me, but:

commit 71a9048448de302d1e968f336de01060d02fae71
Author: Andrew Morton <akpm at linux-foundation.org>
Date:   Wed Jan 12 16:59:35 2011 -0800

    include/linux/kernel.h: abs(): fix handling of 32-bit unsigneds on
64-bit

    Michal reports:

    In the framebuffer subsystem the abs() macro is often used as a part of
    the calculation of a Manhattan metric, which in turn is used as a
measure
    of similarity between video modes.  The arguments of abs() are sometimes
    unsigned numbers.  This worked fine until commit a49c59c0 ("Make sure
the
    value in abs() does not get truncated if it is greater than 2^32:) ,
which
    changed the definition of abs() to prevent truncation.  As a result of
    this change, in the following piece of code:

    u32 a = 0, b = 1;
    u32 c = abs(a - b);

    'c' will end up with a value of 0xffffffff instead of the expected 0x1.

    A problem caused by this change and visible by the end user is that
    framebuffer drivers relying on functions from modedb.c will fail to find
    high resolution video modes similar to that explicitly requested by the
    user if an exact match cannot be found (see e.g.

    Fix this by special-casing `long' types within abs().

    This patch reduces x86_64 code size a bit - drivers/video/uvesafb.o
shrunk
    by 15 bytes, presumably because it is doing abs() on 4-byte quantities,
    and expanding those to 8-byte longs adds code.

    testcase:

    #define oldabs(x) ({                                \
                long __x = (x);                 \
                (__x < 0) ? -__x : __x;         \
        })

    #define newabs(x) ({                                                \
                long ret;                                       \
                if (sizeof(x) == sizeof(long)) {                \
                        long __x = (x);                         \
                        ret = (__x < 0) ? -__x : __x;           \
                } else {                                        \
                        int __x = (x);                          \
                        ret = (__x < 0) ? -__x : __x;           \
                }                                               \
                ret;                                            \
        })

    typedef unsigned int u32;

    main()
    {
        u32 a = 0;
        u32 b = 1;
        u32 oldc = oldabs(a - b);
        u32 newc = newabs(a - b);

        printf("%u %u\n", oldc, newc);
    }

    akpm:/home/akpm> gcc t.c
    akpm:/home/akpm> ./a.out
    4294967295 1

    Reported-by: Michal Januszewski <michalj at gmail.com>
    Cc: Rolf Eike Beer <eike-kernel at sf-tec.de
    Cc: Geert Uytterhoeven <geert at linux-m68k.org>
    Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>

Regards,
Simon



>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> Reader, suppose you were an idiot. And suppose you were a  member  of
> Congress. But I repeat myself.                           - Mark Twain
>


More information about the U-Boot mailing list