svn commit: r340450 - head/sys/sys

Warner Losh imp at bsdimp.com
Mon Nov 19 07:53:40 UTC 2018


On Mon, Nov 19, 2018 at 12:31 AM Andriy Gapon <avg at freebsd.org> wrote:

> On 19/11/2018 03:38, Warner Losh wrote:
> > I'll talk to Allan to see if he can test that. the bare 1 should be
> handled
> > properly because of C's promotion rules. 1ull << 32 is an unsigned long
> long.
> > What I really wanted was "~(uint32_t)0" but that construct has bit me in
> the past.
>
> I think that you could just do (unsigned int)-1 or UINT_MAX.
>

Perhaps.


> As a side note, I wonder if those functions are ever used on negative
> values,
> given the type of the argument, and if anyone checked their correctness in
> that
> case.
>

I don't think so, but an assert would be good to make sure.

But I think I understand the problem now.

mstosbt(1000) is overflowing with my change, but not without because we're
adding 2^32 to a number that's ~900 away from overflowing changing a very
large sleep of 1 second to a tiny sleep of 0 (which is 1ms at the default
Hz). I think we get this in the mlx code because there's a msleep(1000) in
at least one place. msleep(1001) would have failed before my change. Now I
think msleep(999) works, but msleep(1000) fails. Since the code is waiting
a second for hardware to initialize, a 1ms instead is likely to catch the
hardware before it's finished. I think this will cause problems no matter
cold or not, since it's all pause_sbt() under the covers and a delay of 0
is still 0 either way.

The fix I think is something like:

diff --git a/sys/sys/time.h b/sys/sys/time.h
index 2207767813f2..00c6bb4a20fb 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -204,8 +204,12 @@ sbttoms(sbintime_t _sbt)
 static __inline sbintime_t
 mstosbt(int64_t _ms)
 {
+       sbintime_t sb;

-       return ((_ms * (((uint64_t)1 << 63) / 500) + (1ull << 32) - 1) >>
32);
+       sb = (_ms / 1000) * SBT_1S;
+       _ms = _ms % 1000;
+       sb += (_ms * (((uint64_t)1 << 42) / 1000) + 1023) >> 10;
+       return (sb);
 }

 /*-

so we add the whole number of seconds first, then with the remainder we do
the math so we have enough precision to represent 1000 correctly. This lets
us then do the math with plenty of bits to spare. I need to reevaluate this
in the morning when I'm not so tired. It might be safe to not do the whole
seconds first, and I might need 11 bits instead of 10 to be safe, so I'll
hold off committing until I can probe the edge cases more thoroughly. I
thought long and hard about the tiny part of the edge case and never
stopped to think about what 1000ms would do...

Warner


More information about the svn-src-head mailing list