2000-02-18 03:39:52 +08:00
|
|
|
/* time.h -- An implementation of the standard Unix <sys/time.h> file.
|
|
|
|
Written by Geoffrey Noer <noer@cygnus.com>
|
|
|
|
Public domain; no rights reserved. */
|
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
/*-
|
2017-11-21 03:43:44 +08:00
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
*
|
2015-03-13 20:17:34 +08:00
|
|
|
* Copyright (c) 1982, 1986, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2017-03-01 07:42:47 +08:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
2015-03-13 20:17:34 +08:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* @(#)time.h 8.5 (Berkeley) 5/4/95
|
2019-04-13 12:46:35 +08:00
|
|
|
* $FreeBSD: head/sys/sys/time.h 346176 2019-04-13 04:46:35Z imp $
|
2015-03-13 20:17:34 +08:00
|
|
|
*/
|
|
|
|
|
2000-02-18 03:39:52 +08:00
|
|
|
#ifndef _SYS_TIME_H_
|
2015-03-13 20:17:34 +08:00
|
|
|
#define _SYS_TIME_H_
|
2000-02-18 03:39:52 +08:00
|
|
|
|
|
|
|
#include <_ansi.h>
|
2015-07-06 20:08:30 +08:00
|
|
|
#include <sys/cdefs.h>
|
2015-03-13 20:17:34 +08:00
|
|
|
#include <sys/_timeval.h>
|
2000-02-18 03:39:52 +08:00
|
|
|
#include <sys/types.h>
|
2015-03-13 20:17:34 +08:00
|
|
|
#include <sys/timespec.h>
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2016-03-15 10:14:39 +08:00
|
|
|
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
|
2015-05-02 21:07:44 +08:00
|
|
|
#include <sys/select.h>
|
2015-12-14 17:06:18 +08:00
|
|
|
#endif
|
2015-05-02 21:07:44 +08:00
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
struct timezone {
|
|
|
|
int tz_minuteswest; /* minutes west of Greenwich */
|
|
|
|
int tz_dsttime; /* type of dst correction */
|
|
|
|
};
|
|
|
|
#define DST_NONE 0 /* not on dst */
|
|
|
|
#define DST_USA 1 /* USA style dst */
|
|
|
|
#define DST_AUST 2 /* Australian style dst */
|
|
|
|
#define DST_WET 3 /* Western European dst */
|
|
|
|
#define DST_MET 4 /* Middle European dst */
|
|
|
|
#define DST_EET 5 /* Eastern European dst */
|
|
|
|
#define DST_CAN 6 /* Canada */
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
#if __BSD_VISIBLE
|
|
|
|
struct bintime {
|
|
|
|
time_t sec;
|
2015-04-02 02:34:08 +08:00
|
|
|
uint64_t frac;
|
2000-02-18 03:39:52 +08:00
|
|
|
};
|
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
static __inline void
|
2015-04-02 02:34:08 +08:00
|
|
|
bintime_addx(struct bintime *_bt, uint64_t _x)
|
2015-03-13 20:17:34 +08:00
|
|
|
{
|
2015-04-02 02:34:08 +08:00
|
|
|
uint64_t _u;
|
2012-11-12 23:57:35 +08:00
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
_u = _bt->frac;
|
|
|
|
_bt->frac += _x;
|
|
|
|
if (_u > _bt->frac)
|
|
|
|
_bt->sec++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime_add(struct bintime *_bt, const struct bintime *_bt2)
|
|
|
|
{
|
2015-04-02 02:34:08 +08:00
|
|
|
uint64_t _u;
|
2015-03-13 20:17:34 +08:00
|
|
|
|
|
|
|
_u = _bt->frac;
|
|
|
|
_bt->frac += _bt2->frac;
|
|
|
|
if (_u > _bt->frac)
|
|
|
|
_bt->sec++;
|
|
|
|
_bt->sec += _bt2->sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime_sub(struct bintime *_bt, const struct bintime *_bt2)
|
|
|
|
{
|
2015-04-02 02:34:08 +08:00
|
|
|
uint64_t _u;
|
2015-03-13 20:17:34 +08:00
|
|
|
|
|
|
|
_u = _bt->frac;
|
|
|
|
_bt->frac -= _bt2->frac;
|
|
|
|
if (_u < _bt->frac)
|
|
|
|
_bt->sec--;
|
|
|
|
_bt->sec -= _bt2->sec;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime_mul(struct bintime *_bt, u_int _x)
|
|
|
|
{
|
2015-04-02 02:34:08 +08:00
|
|
|
uint64_t _p1, _p2;
|
2015-03-13 20:17:34 +08:00
|
|
|
|
|
|
|
_p1 = (_bt->frac & 0xffffffffull) * _x;
|
|
|
|
_p2 = (_bt->frac >> 32) * _x + (_p1 >> 32);
|
|
|
|
_bt->sec *= _x;
|
|
|
|
_bt->sec += (_p2 >> 32);
|
|
|
|
_bt->frac = (_p2 << 32) | (_p1 & 0xffffffffull);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime_shift(struct bintime *_bt, int _exp)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (_exp > 0) {
|
|
|
|
_bt->sec <<= _exp;
|
|
|
|
_bt->sec |= _bt->frac >> (64 - _exp);
|
|
|
|
_bt->frac <<= _exp;
|
|
|
|
} else if (_exp < 0) {
|
|
|
|
_bt->frac >>= -_exp;
|
2015-04-02 02:34:08 +08:00
|
|
|
_bt->frac |= (uint64_t)_bt->sec << (64 + _exp);
|
2015-03-13 20:17:34 +08:00
|
|
|
_bt->sec >>= -_exp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define bintime_clear(a) ((a)->sec = (a)->frac = 0)
|
|
|
|
#define bintime_isset(a) ((a)->sec || (a)->frac)
|
|
|
|
#define bintime_cmp(a, b, cmp) \
|
|
|
|
(((a)->sec == (b)->sec) ? \
|
|
|
|
((a)->frac cmp (b)->frac) : \
|
|
|
|
((a)->sec cmp (b)->sec))
|
|
|
|
|
|
|
|
#define SBT_1S ((sbintime_t)1 << 32)
|
|
|
|
#define SBT_1M (SBT_1S * 60)
|
|
|
|
#define SBT_1MS (SBT_1S / 1000)
|
|
|
|
#define SBT_1US (SBT_1S / 1000000)
|
2017-07-30 01:00:23 +08:00
|
|
|
#define SBT_1NS (SBT_1S / 1000000000) /* beware rounding, see nstosbt() */
|
2015-03-13 20:17:34 +08:00
|
|
|
#define SBT_MAX 0x7fffffffffffffffLL
|
|
|
|
|
|
|
|
static __inline int
|
|
|
|
sbintime_getsec(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (_sbt >> 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
bttosbt(const struct bintime _bt)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (((sbintime_t)_bt.sec << 32) + (_bt.frac >> 32));
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline struct bintime
|
|
|
|
sbttobt(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
struct bintime _bt;
|
|
|
|
|
|
|
|
_bt.sec = _sbt >> 32;
|
|
|
|
_bt.frac = _sbt << 32;
|
|
|
|
return (_bt);
|
|
|
|
}
|
|
|
|
|
2017-07-30 01:00:23 +08:00
|
|
|
/*
|
|
|
|
* 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.
|
2018-11-16 00:02:13 +08:00
|
|
|
*
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
* 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.
|
2017-07-30 01:00:23 +08:00
|
|
|
*/
|
|
|
|
static __inline int64_t
|
|
|
|
sbttons(sbintime_t _sbt)
|
|
|
|
{
|
2019-04-13 12:46:35 +08:00
|
|
|
uint64_t ns;
|
2017-07-30 01:00:23 +08:00
|
|
|
|
2019-04-13 12:46:35 +08:00
|
|
|
ns = _sbt;
|
|
|
|
if (ns >= SBT_1S)
|
|
|
|
ns = (ns >> 32) * 1000000000;
|
|
|
|
else
|
|
|
|
ns = 0;
|
|
|
|
|
|
|
|
return (ns + (1000000000 * (_sbt & 0xffffffffu) >> 32));
|
2017-07-30 01:00:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
nstosbt(int64_t _ns)
|
|
|
|
{
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
sbintime_t sb = 0;
|
2017-07-30 01:00:23 +08:00
|
|
|
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
if (_ns >= SBT_1S) {
|
|
|
|
sb = (_ns / 1000000000) * SBT_1S;
|
|
|
|
_ns = _ns % 1000000000;
|
|
|
|
}
|
|
|
|
/* 9223372037 = ceil(2^63 / 1000000000) */
|
|
|
|
sb += ((_ns * 9223372037ull) + 0x7fffffff) >> 31;
|
|
|
|
return (sb);
|
2017-07-30 01:00:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int64_t
|
|
|
|
sbttous(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
|
|
|
|
return ((1000000 * _sbt) >> 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
ustosbt(int64_t _us)
|
|
|
|
{
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
sbintime_t sb = 0;
|
2017-07-30 01:00:23 +08:00
|
|
|
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
if (_us >= SBT_1S) {
|
|
|
|
sb = (_us / 1000000) * SBT_1S;
|
|
|
|
_us = _us % 1000000;
|
|
|
|
}
|
|
|
|
/* 9223372036855 = ceil(2^63 / 1000000) */
|
|
|
|
sb += ((_us * 9223372036855ull) + 0x7fffffff) >> 31;
|
|
|
|
return (sb);
|
2017-07-30 01:00:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int64_t
|
|
|
|
sbttoms(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
|
|
|
|
return ((1000 * _sbt) >> 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
mstosbt(int64_t _ms)
|
|
|
|
{
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
sbintime_t sb = 0;
|
2017-07-30 01:00:23 +08:00
|
|
|
|
Ensure that all values of ns, us and ms work
for {n,u,m}stosbt
Integer overflows and wrong constants limited the accuracy of these
functions and created situatiosn where sbttoXs(Xstosbt(Y)) != Y. This
was especailly true in the ns case where we had millions of values
that were wrong.
Instead, used fixed constants because there's no way to say ceil(X)
for integer math. Document what these crazy constants are.
Also, use a shift one fewer left to avoid integer overflow causing
incorrect results, and adjust the equasion accordingly. Document this.
Allow times >= 1s to be well defined for these conversion functions
(at least the Xstosbt). There's too many users in the tree that they
work for >= 1s.
This fixes a failure on boot to program firmware on the mlx4
NIC. There was a msleep(1000) in the code. Prior to my recent rounding
changes, msleep(1000) worked, but msleep(1001) did not because the old
code rounded to just below 2^64 and the new code rounds to just above
it (overflowing, causing the msleep(1000) to really sleep 1ms).
A test program to test all cases will be committed shortly. The test
exaustively tries every value (thanks to bde for the test).
Sponsored by: Netflix, Inc
Differential Revision: https://reviews.freebsd.org/D18051
2018-11-20 15:11:23 +08:00
|
|
|
if (_ms >= SBT_1S) {
|
|
|
|
sb = (_ms / 1000) * SBT_1S;
|
|
|
|
_ms = _ms % 1000;
|
|
|
|
}
|
|
|
|
/* 9223372036854776 = ceil(2^63 / 1000) */
|
|
|
|
sb += ((_ms * 9223372036854776ull) + 0x7fffffff) >> 31;
|
|
|
|
return (sb);
|
2017-07-30 01:00:23 +08:00
|
|
|
}
|
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
/*-
|
|
|
|
* Background information:
|
|
|
|
*
|
|
|
|
* When converting between timestamps on parallel timescales of differing
|
|
|
|
* resolutions it is historical and scientific practice to round down rather
|
|
|
|
* than doing 4/5 rounding.
|
|
|
|
*
|
|
|
|
* The date changes at midnight, not at noon.
|
|
|
|
*
|
|
|
|
* Even at 15:59:59.999999999 it's not four'o'clock.
|
|
|
|
*
|
|
|
|
* time_second ticks after N.999999999 not after N.4999999999
|
|
|
|
*/
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime2timespec(const struct bintime *_bt, struct timespec *_ts)
|
|
|
|
{
|
|
|
|
|
|
|
|
_ts->tv_sec = _bt->sec;
|
2015-04-02 02:34:08 +08:00
|
|
|
_ts->tv_nsec = ((uint64_t)1000000000 *
|
|
|
|
(uint32_t)(_bt->frac >> 32)) >> 32;
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
timespec2bintime(const struct timespec *_ts, struct bintime *_bt)
|
|
|
|
{
|
|
|
|
|
|
|
|
_bt->sec = _ts->tv_sec;
|
|
|
|
/* 18446744073 = int(2^64 / 1000000000) */
|
2015-04-02 02:34:08 +08:00
|
|
|
_bt->frac = _ts->tv_nsec * (uint64_t)18446744073LL;
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
bintime2timeval(const struct bintime *_bt, struct timeval *_tv)
|
|
|
|
{
|
|
|
|
|
|
|
|
_tv->tv_sec = _bt->sec;
|
2015-04-02 02:34:08 +08:00
|
|
|
_tv->tv_usec = ((uint64_t)1000000 * (uint32_t)(_bt->frac >> 32)) >> 32;
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
timeval2bintime(const struct timeval *_tv, struct bintime *_bt)
|
|
|
|
{
|
|
|
|
|
|
|
|
_bt->sec = _tv->tv_sec;
|
|
|
|
/* 18446744073709 = int(2^64 / 1000000) */
|
2015-04-02 02:34:08 +08:00
|
|
|
_bt->frac = _tv->tv_usec * (uint64_t)18446744073709LL;
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline struct timespec
|
|
|
|
sbttots(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
struct timespec _ts;
|
|
|
|
|
|
|
|
_ts.tv_sec = _sbt >> 32;
|
2017-07-30 01:00:23 +08:00
|
|
|
_ts.tv_nsec = sbttons((uint32_t)_sbt);
|
2015-03-13 20:17:34 +08:00
|
|
|
return (_ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
tstosbt(struct timespec _ts)
|
|
|
|
{
|
|
|
|
|
2017-07-30 01:00:23 +08:00
|
|
|
return (((sbintime_t)_ts.tv_sec << 32) + nstosbt(_ts.tv_nsec));
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline struct timeval
|
|
|
|
sbttotv(sbintime_t _sbt)
|
|
|
|
{
|
|
|
|
struct timeval _tv;
|
|
|
|
|
|
|
|
_tv.tv_sec = _sbt >> 32;
|
2017-07-30 01:00:23 +08:00
|
|
|
_tv.tv_usec = sbttous((uint32_t)_sbt);
|
2015-03-13 20:17:34 +08:00
|
|
|
return (_tv);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline sbintime_t
|
|
|
|
tvtosbt(struct timeval _tv)
|
|
|
|
{
|
|
|
|
|
2017-07-30 01:00:23 +08:00
|
|
|
return (((sbintime_t)_tv.tv_sec << 32) + ustosbt(_tv.tv_usec));
|
2015-03-13 20:17:34 +08:00
|
|
|
}
|
Synchronize <sys/time.h> with FreeBSD
This change is based on the FreeBSD commit:
Author: asomers <asomers@FreeBSD.org>
Date: Mon Jul 30 15:46:40 2018 +0000
Make timespecadd(3) and friends public
The timespecadd(3) family of macros were imported from NetBSD back in
r35029. However, they were initially guarded by #ifdef _KERNEL. In the
meantime, we have grown at least 28 syscalls that use timespecs in some
way, leading many programs both inside and outside of the base system to
redefine those macros. It's better just to make the definitions public.
Our kernel currently defines two-argument versions of timespecadd and
timespecsub. NetBSD, OpenBSD, and FreeDesktop.org's libbsd, however, define
three-argument versions. Solaris also defines a three-argument version, but
only in its kernel. This revision changes our definition to match the
common three-argument version.
Bump _FreeBSD_version due to the breaking KPI change.
Discussed with: cem, jilles, ian, bde
Differential Revision: https://reviews.freebsd.org/D14725
2019-09-23 18:02:11 +08:00
|
|
|
|
|
|
|
/* Operations on timespecs */
|
|
|
|
#define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
|
|
|
|
#define timespecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec)
|
|
|
|
#define timespeccmp(tvp, uvp, cmp) \
|
|
|
|
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
|
|
|
((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
|
|
|
|
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
|
|
|
|
|
|
|
#define timespecadd(tsp, usp, vsp) \
|
|
|
|
do { \
|
|
|
|
(vsp)->tv_sec = (tsp)->tv_sec + (usp)->tv_sec; \
|
|
|
|
(vsp)->tv_nsec = (tsp)->tv_nsec + (usp)->tv_nsec; \
|
|
|
|
if ((vsp)->tv_nsec >= 1000000000L) { \
|
|
|
|
(vsp)->tv_sec++; \
|
|
|
|
(vsp)->tv_nsec -= 1000000000L; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define timespecsub(tsp, usp, vsp) \
|
|
|
|
do { \
|
|
|
|
(vsp)->tv_sec = (tsp)->tv_sec - (usp)->tv_sec; \
|
|
|
|
(vsp)->tv_nsec = (tsp)->tv_nsec - (usp)->tv_nsec; \
|
|
|
|
if ((vsp)->tv_nsec < 0) { \
|
|
|
|
(vsp)->tv_sec--; \
|
|
|
|
(vsp)->tv_nsec += 1000000000L; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2019-09-24 14:34:35 +08:00
|
|
|
|
|
|
|
#ifndef _KERNEL /* NetBSD/OpenBSD compatible interfaces */
|
|
|
|
|
|
|
|
#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
|
|
|
|
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
|
|
|
|
#define timercmp(tvp, uvp, cmp) \
|
|
|
|
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
|
|
|
|
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
|
|
|
|
((tvp)->tv_sec cmp (uvp)->tv_sec))
|
|
|
|
#define timeradd(tvp, uvp, vvp) \
|
|
|
|
do { \
|
|
|
|
(vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
|
|
|
|
(vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
|
|
|
|
if ((vvp)->tv_usec >= 1000000) { \
|
|
|
|
(vvp)->tv_sec++; \
|
|
|
|
(vvp)->tv_usec -= 1000000; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#define timersub(tvp, uvp, vvp) \
|
|
|
|
do { \
|
|
|
|
(vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
|
|
|
|
(vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
|
|
|
|
if ((vvp)->tv_usec < 0) { \
|
|
|
|
(vvp)->tv_sec--; \
|
|
|
|
(vvp)->tv_usec += 1000000; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
#endif
|
2015-03-13 20:17:34 +08:00
|
|
|
#endif /* __BSD_VISIBLE */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Names of the interval timers, and structure
|
|
|
|
* defining a timer setting.
|
|
|
|
*/
|
|
|
|
#define ITIMER_REAL 0
|
|
|
|
#define ITIMER_VIRTUAL 1
|
|
|
|
#define ITIMER_PROF 2
|
2012-11-12 23:57:35 +08:00
|
|
|
|
2015-03-13 20:17:34 +08:00
|
|
|
struct itimerval {
|
|
|
|
struct timeval it_interval; /* timer interval */
|
|
|
|
struct timeval it_value; /* current value */
|
2012-11-12 23:57:35 +08:00
|
|
|
};
|
2000-12-05 02:40:53 +08:00
|
|
|
|
2016-04-07 18:58:43 +08:00
|
|
|
#ifndef _KERNEL
|
2015-03-13 20:17:34 +08:00
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
__BEGIN_DECLS
|
2021-01-26 22:16:31 +08:00
|
|
|
int utimes (const char *, const struct timeval [2]);
|
2012-08-08 19:04:18 +08:00
|
|
|
|
2014-07-23 03:30:00 +08:00
|
|
|
#if __BSD_VISIBLE
|
2017-12-04 13:54:48 +08:00
|
|
|
int adjtime (const struct timeval *, struct timeval *);
|
2021-01-26 22:16:31 +08:00
|
|
|
int futimes (int, const struct timeval [2]);
|
|
|
|
int lutimes (const char *, const struct timeval [2]);
|
2017-12-04 13:54:48 +08:00
|
|
|
int settimeofday (const struct timeval *, const struct timezone *);
|
2014-07-23 03:30:00 +08:00
|
|
|
#endif
|
2015-03-13 20:17:34 +08:00
|
|
|
|
2016-03-15 10:14:39 +08:00
|
|
|
#if __MISC_VISIBLE || __XSI_VISIBLE
|
2017-12-04 13:54:48 +08:00
|
|
|
int getitimer (int __which, struct itimerval *__value);
|
|
|
|
int setitimer (int __which, const struct itimerval *__restrict __value,
|
|
|
|
struct itimerval *__restrict __ovalue);
|
2016-06-20 16:11:24 +08:00
|
|
|
#endif
|
|
|
|
|
2017-12-04 13:54:48 +08:00
|
|
|
int gettimeofday (struct timeval *__restrict __p,
|
|
|
|
void *__restrict __tz);
|
2000-02-18 03:39:52 +08:00
|
|
|
|
2016-03-15 10:14:39 +08:00
|
|
|
#if __GNU_VISIBLE
|
2017-12-04 13:54:48 +08:00
|
|
|
int futimesat (int, const char *, const struct timeval [2]);
|
2016-03-15 10:14:39 +08:00
|
|
|
#endif
|
|
|
|
|
2021-11-09 11:22:27 +08:00
|
|
|
#ifdef _LIBC
|
2017-12-04 13:54:48 +08:00
|
|
|
int _gettimeofday (struct timeval *__p, void *__tz);
|
2000-02-18 03:39:52 +08:00
|
|
|
#endif
|
2015-03-13 20:17:34 +08:00
|
|
|
|
|
|
|
__END_DECLS
|
|
|
|
|
|
|
|
#endif /* !_KERNEL */
|
2016-04-07 18:58:43 +08:00
|
|
|
#include <machine/_time.h>
|
2015-03-13 20:17:34 +08:00
|
|
|
|
|
|
|
#endif /* !_SYS_TIME_H_ */
|