Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Jul 2013 14:40:17 +1000 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Andriy Gapon <avg@FreeBSD.org>
Cc:        attilio@FreeBSD.org, svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org
Subject:   Re: should_yield problem [Was: svn commit: r251322 - head/sys/kern]
Message-ID:  <20130703134115.C1064@besplex.bde.org>
In-Reply-To: <51D31724.6090807@FreeBSD.org>
References:  <201306031736.r53Hain5093431@svn.freebsd.org> <51D30463.50608@FreeBSD.org> <CAJ-FndD5tCxe-L8V73MFtk_4xr0Wq3MHasKY4O_tcA3uYouKAw@mail.gmail.com> <51D30CE8.7030803@FreeBSD.org> <CAJ-FndATxzTwCkZGXw4jD_8O4KbnHbsjk4DwHwbp%2B0gd3VGTCQ@mail.gmail.com> <51D31724.6090807@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 2 Jul 2013, Andriy Gapon wrote:

> on 02/07/2013 20:52 Attilio Rao said the following:
>> I was just pointing out that the real bug is not in the subtraction
>> itself but on the hogticks comparison.
>> This is because hogticks is not an absolute measurement but it
>> represents really a ticks difference.
>> In my opinion we should define hogticks as an unsigned int and add a
>> small comment saying that it is a differential.
>> This will fix the issue.

This is sort of backwards.  hogticks is a small positive integer.  Making
it unsigned just asks for sign extension bugs when it is compared with
signed values.  However, the tick counters are circular counters.  Making
them signed asks for undefined behaviour when they overflow.

> I think that my original suggestion is equivalently well if not more obvious.
> This is a common knowledge:
> http://en.wikipedia.org/wiki/Serial_number_arithmetic#General_Solution
>
> distance = (signed)( i1 - i2 )

With 2's complement and benign overflow, this is no different from
'distance = i1 - i2'.  But signed counters are not wanted here.  A
negative distance, or equivalently with 32-bit unsigned ints, an unsigned
difference of >= 0x80000000 means overflow or an initialization error.
Your bug is an initialization error.

BTW, -ftrapv is broken in gcc-4.2.1.  It seems to have worked in
gcc-3.3, but gcc-3.3 generates pessimal code for it, with a call to
an extern function even for adding ints.  gcc-4.2.1 still generates
an declaration of the extern function, but never calls it.  The
declaration is unnecessary even when it is used.

These bugs seem to be fixed in clang, at least on amd64.  clang
generates an explicit inline check for overflow and executes an
unsupported instruction on overflow.  The code for the check is good
with -O but bad (large and slow) with -O0.

These bugs are still large at the hardware level.  Overflow checking
is handled correctly on x86 only for floating point.  In floating
point, you can set or clear the mode bit for trapping on overflow, so
that programs can be tested without recompiling them and without adding
slow runtime checks (the hardware has to pipleline the checks well so
that they have low cost).  Hardware support for trapping on integer
overflow keeps getting worse since programmers never check for overflow.
i386 has an "into" instruction that should have been used instead of
"jo foo" to check for overflow.  It should have been easier for hardware
to optimize than the branch.  But AFAIK, "into" has never been optimized
and has always been slower than the branch, so programmers never used
it, so AMD removed it in 64-bit mode.

Speed tests for incrementing a volatile local variable on corei7 in
32-bit mode:
- -fno-trapv:     6.2 cycles  (clang bug: warn about -fno-trapv being unused)
- add into:      12.3 cycles  (error handling is SIGBUS)
- -ftrapv:        6.7 cycles  (error handling is SIGILL)
- mod jo to into: 7.3 cycles  (error handling is SIGBUS).

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20130703134115.C1064>