svn commit: r363384 - stable/12/sys/sys
Andriy Gapon
avg at FreeBSD.org
Tue Jul 21 07:58:40 UTC 2020
Author: avg
Date: Tue Jul 21 07:58:39 2020
New Revision: 363384
URL: https://svnweb.freebsd.org/changeset/base/363384
Log:
MFC r340450,r340664,r346176 by imp: fix time conversions to and from sbt
Note that the PR is for a change elsewhere (ZFS) that expected the sane
behavior of nstosbt().
PR: 247829
Reported by: gbe, others
Tested by: gbe, others
Modified:
stable/12/sys/sys/time.h
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/sys/sys/time.h
==============================================================================
--- stable/12/sys/sys/time.h Tue Jul 21 07:41:36 2020 (r363383)
+++ stable/12/sys/sys/time.h Tue Jul 21 07:58:39 2020 (r363384)
@@ -161,19 +161,58 @@ sbttobt(sbintime_t _sbt)
* Decimal<->sbt conversions. Multiplying or dividing by SBT_1NS results in
* large roundoff errors which sbttons() and nstosbt() avoid. Millisecond and
* microsecond functions are also provided for completeness.
+ *
+ * These functions return the smallest sbt larger or equal to the
+ * number of seconds requested so that sbttoX(Xtosbt(y)) == y. Unlike
+ * top of second computations below, which require that we tick at the
+ * top of second, these need to be rounded up so we do whatever for at
+ * least as long as requested.
+ *
+ * The naive computation we'd do is this
+ * ((unit * 2^64 / SIFACTOR) + 2^32-1) >> 32
+ * However, that overflows. Instead, we compute
+ * ((unit * 2^63 / SIFACTOR) + 2^31-1) >> 32
+ * and use pre-computed constants that are the ceil of the 2^63 / SIFACTOR
+ * term to ensure we are using exactly the right constant. We use the lesser
+ * evil of ull rather than a uint64_t cast to ensure we have well defined
+ * right shift semantics. With these changes, we get all the ns, us and ms
+ * conversions back and forth right.
+ * Note: This file is used for both kernel and userland includes, so we can't
+ * rely on KASSERT being defined, nor can we pollute the namespace by including
+ * assert.h.
*/
static __inline int64_t
sbttons(sbintime_t _sbt)
{
+ uint64_t ns;
- return ((1000000000 * _sbt) >> 32);
+#ifdef KASSERT
+ KASSERT(_sbt >= 0, ("Negative values illegal for sbttons: %jx", _sbt));
+#endif
+ ns = _sbt;
+ if (ns >= SBT_1S)
+ ns = (ns >> 32) * 1000000000;
+ else
+ ns = 0;
+
+ return (ns + (1000000000 * (_sbt & 0xffffffffu) >> 32));
}
static __inline sbintime_t
nstosbt(int64_t _ns)
{
+ sbintime_t sb = 0;
- return ((_ns * (((uint64_t)1 << 63) / 500000000)) >> 32);
+#ifdef KASSERT
+ KASSERT(_ns >= 0, ("Negative values illegal for nstosbt: %jd", _ns));
+#endif
+ if (_ns >= SBT_1S) {
+ sb = (_ns / 1000000000) * SBT_1S;
+ _ns = _ns % 1000000000;
+ }
+ /* 9223372037 = ceil(2^63 / 1000000000) */
+ sb += ((_ns * 9223372037ull) + 0x7fffffff) >> 31;
+ return (sb);
}
static __inline int64_t
@@ -186,8 +225,18 @@ sbttous(sbintime_t _sbt)
static __inline sbintime_t
ustosbt(int64_t _us)
{
+ sbintime_t sb = 0;
- return ((_us * (((uint64_t)1 << 63) / 500000)) >> 32);
+#ifdef KASSERT
+ KASSERT(_us >= 0, ("Negative values illegal for ustosbt: %jd", _us));
+#endif
+ if (_us >= SBT_1S) {
+ sb = (_us / 1000000) * SBT_1S;
+ _us = _us % 1000000;
+ }
+ /* 9223372036855 = ceil(2^63 / 1000000) */
+ sb += ((_us * 9223372036855ull) + 0x7fffffff) >> 31;
+ return (sb);
}
static __inline int64_t
@@ -200,8 +249,18 @@ sbttoms(sbintime_t _sbt)
static __inline sbintime_t
mstosbt(int64_t _ms)
{
+ sbintime_t sb = 0;
- return ((_ms * (((uint64_t)1 << 63) / 500)) >> 32);
+#ifdef KASSERT
+ KASSERT(_ms >= 0, ("Negative values illegal for mstosbt: %jd", _ms));
+#endif
+ if (_ms >= SBT_1S) {
+ sb = (_ms / 1000) * SBT_1S;
+ _ms = _ms % 1000;
+ }
+ /* 9223372036854776 = ceil(2^63 / 1000) */
+ sb += ((_ms * 9223372036854776ull) + 0x7fffffff) >> 31;
+ return (sb);
}
/*-
More information about the svn-src-stable
mailing list