svn commit: r346176 - head/sys/sys

Bruce Evans brde at optusnet.com.au
Sat Apr 13 08:14:10 UTC 2019


On Sat, 13 Apr 2019, Bruce Evans wrote:

> On Sat, 13 Apr 2019, Warner Losh wrote:
>
>>  Fix sbttons for values > 2s
>> 
>>  Add test against negative times. Add code to cope with larger values
>>  properly.
>> 
>>  Discussed with: bde@ (quite some time ago, for an earlier version)
>
> I am unhappy with previous attempted fixes in this area, and still have large
> local patches.
> ...
>> Modified: head/sys/sys/time.h
>> ==============================================================================
>> --- head/sys/sys/time.h	Sat Apr 13 04:42:17 2019	(r346175)
>> +++ head/sys/sys/time.h	Sat Apr 13 04:46:35 2019	(r346176)
>> @@ -184,8 +184,18 @@ sbttobt(sbintime_t _sbt)
>> static __inline int64_t
>> sbttons(sbintime_t _sbt)
>> {
>> +	uint64_t ns;
>> 
>> -	return ((1000000000 * _sbt) >> 32);
>* ...
>> +	ns = _sbt;
>> +	if (ns >= SBT_1S)
>> +		ns = (ns >> 32) * 1000000000;
>> +	else
>> +		ns = 0;
>> +
>...
>> +	return (ns + (1000000000 * (_sbt & 0xffffffffu) >> 32));

Another style bug: extra parentheses moved from a useful place to a non-
useful place.  '*' has precedence over '>>', but this combination is
unusual so the old code emphasized it using parentheses.  '*' has
precedence over '+', and this combination is usual so it shouldn't be
emphasized using parentheses, but the new code does that and removes the
more useful parentheses.

>> }

sbttous() and sbttoms() are still broken.  sbtots() might be pessimized
since it calls sbttons with a 32-bit arg that doesn't need the above
complications (the compiler would be doing well to see that and replace
ns by 0 in the above calculations.

Another bug in the above and previous changes: ns is in the application
namespace.  Adding it defeats the care taken with naming the arg with
an underscore.  All inline functions in standard and sys headers have this
problem.  These are under __BSD_VISIBLE, but of course there is no
documentation that this reserves the names ns, etc.

Better fix based on looking at sbtots(): split _sbt into seconds and
nanoseconds unconditially and reassemble using simple expressions.
This is almost as efficient on 32-bit arches, since the seconds and
nanoseconds fit in 32 bits so reassembly uses 2 32x32 -> 64-bit
multiplications instead of 1 64x32 -> 64-bit multiplication.

static __inline int64_t
sbttons(sbintime_t _sbt)
{

#ifdef __tooslow
 	if (__predict_false(_sbt == INT64_MIN)
 		return (-1);		/* round towards +-Inf to keep non-0 */
#endif
#ifdef __maybenottooslow
 	if (__predict_false(_sbt < 0))
 		return sbttons(-sbt);
#endif
 	return (1000000000 * (_sbt >> 32) +
 	    (1000000000 * (_sbt & 0xffffffffU)) >> 32);	/* XXX rounding? */
}

Handling negative values makes it about as messy and slow as the committed
version :-(.

Rounding is also a problem.  It is normal to round times down, but that
turns nonzero into zero which is bad for timeouts.  The version in my
previous reply always adds 1 mainly to avoid this.  Conversion to a
different representation and back gives double rounding down if rounding
is always done, so rarely gives the original value.  The file still has
phk's comment about rounding down being required, and the changes to the
sbintime conversion functions still ignore this.

Bruce


More information about the svn-src-all mailing list