Details
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
So I think I understand. Suppose you wanted to sleep for 1.5 seconds. In sbintime_t that should ideally be 0x180000000. The old method for 1500 milliseconds, 1500000 microseconds, and 1500000000 nanoseconds gives:
(gdb) p/x ((1ull << 32) / 1000) * 1500 $23 = 0x17ffffe44 (gdb) p/x ((1ull << 32) / 1000000) * 1500000 $24 = 0x17fe9dc40 (gdb) p/x ((1ull << 32) / 1000000000) * 1500000000 $26 = 0x165a0bc00
With the new math, I always get the same result:
(gdb) p/x (500 * (((1ull << 63) / 500)) >> 32) | (1ull << 32) $20 = 0x17fffffff (gdb) p/x (500000 * (((1ull << 63) / 500000)) >> 32) | (1ull << 32) $25 = 0x17fffffff (gdb) p/x (500000000 * (((1ull << 63) / 500000000)) >> 32) | (1ull << 32) $27 = 0x17fffffff
In the worst case (nanoseconds), the old code is off by about 103 milliseconds. It might be worth noting that the bintime code also explicitly handles the fractional second separate from the second when doing conversions, though it has to do that anyway. Hmm, the new logic also matches what tstosbt(), etc. do. That is a big argument in favor of this change. In fact, to reduce code duplication, I would suggest using tstosbt() and tvtosbt() directly. E.g.:
case NOTE_USECONDS: struct timeval tv; int64_t secs; secs = data / 1000000; #ifdef __LP64__ if (secs > (SBT_MAX / SBT_1S)) return (SBT_MAX); #endif tv.secs = secs; tv.usec = data % 1000000; return (tvtosbt(&tv));
However, the new logic is clearly sounder regardless of which way you choose to fix it. There isn't an equivalent 'footosbt' for something taking milliseconds.
This does almost beg for axeing SBT_1MS entirely and having '*stosbt()' methods in <sys/time.h> instead.