1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-26 11:47:31 +00:00
freebsd/sys/sys/timetc.h
1999-08-28 01:08:13 +00:00

305 lines
10 KiB
C

/*
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 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
* $FreeBSD$
*/
#ifndef _SYS_TIME_H_
#define _SYS_TIME_H_
#include <sys/types.h>
/*
* Structure returned by gettimeofday(2) system call,
* and used in other calls.
*/
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
#ifndef _TIMESPEC_DECLARED
#define _TIMESPEC_DECLARED
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
};
#endif
#define TIMEVAL_TO_TIMESPEC(tv, ts) \
do { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
} while (0)
#define TIMESPEC_TO_TIMEVAL(tv, ts) \
do { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
} while (0)
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 */
/*
* Structure used to interface to the machine dependent hardware support
* for timekeeping.
*
* A timecounter is a (hard or soft) binary counter which has two properties:
* * it runs at a fixed, known frequency.
* * it must not roll over in less than (1 + delta)/HZ seconds. "delta"
* is expected to be less than 20 msec, but no hard data has been
* collected on this. 16 bit at 5 MHz (31 msec) is known to work.
*
* get_timecount() reads the counter.
*
* counter_mask removes unimplemented bits from the count value.
*
* frequency is the counter frequency in hz.
*
* name is a short mnemonic name for this counter.
*
* cost is a measure of how long time it takes to read the counter.
*
* adjustment [PPM << 16] which means that the smallest unit of correction
* you can apply amounts to 481.5 usec/year.
*
* scale_micro [2^32 * usec/tick].
* scale_nano_i [ns/tick].
* scale_nano_f [(ns/2^32)/tick].
*
* offset_count is the contents of the counter which corresponds to the
* rest of the offset_* values.
*
* offset_sec [s].
* offset_micro [usec].
* offset_nano [ns/2^32] is misnamed, the real unit is .23283064365...
* attoseconds (10E-18) and before you ask: yes, they are in fact
* called attoseconds, it comes from "atten" for 18 in Danish/Swedish.
*
* Each timecounter must supply an array of three timecounters, this is needed
* to guarantee atomicity in the code. Index zero is used to transport
* modifications, for instance done with sysctl, into the timecounter being
* used in a safe way. Such changes may be adopted with a delay of up to 1/HZ,
* index one & two are used alternately for the actual timekeeping.
*
* 'tc_avail' points to the next available (external) timecounter in a
* circular queue. This is only valid for index 0.
*
* `tc_other' points to the next "work" timecounter in a circular queue,
* i.e., for index i > 0 it points to index 1 + (i - 1) % NTIMECOUNTER.
* We also use it to point from index 0 to index 1.
*
* `tc_tweak' points to index 0.
*/
struct timecounter;
typedef unsigned timecounter_get_t __P((struct timecounter *));
typedef void timecounter_pps_t __P((struct timecounter *));
struct timecounter {
/* These fields must be initialized by the driver. */
timecounter_get_t *tc_get_timecount;
timecounter_pps_t *tc_poll_pps;
unsigned tc_counter_mask;
u_int32_t tc_frequency;
char *tc_name;
void *tc_priv;
/* These fields will be managed by the generic code. */
int64_t tc_adjustment;
u_int32_t tc_scale_micro;
u_int32_t tc_scale_nano_i;
u_int32_t tc_scale_nano_f;
unsigned tc_offset_count;
u_int32_t tc_offset_sec;
u_int32_t tc_offset_micro;
u_int64_t tc_offset_nano;
struct timeval tc_microtime;
struct timespec tc_nanotime;
struct timecounter *tc_avail;
struct timecounter *tc_other;
struct timecounter *tc_tweak;
};
#ifdef KERNEL
/* 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(vvp, uvp) \
do { \
(vvp)->tv_sec += (uvp)->tv_sec; \
(vvp)->tv_nsec += (uvp)->tv_nsec; \
if ((vvp)->tv_nsec >= 1000000000) { \
(vvp)->tv_sec++; \
(vvp)->tv_nsec -= 1000000000; \
} \
} while (0)
#define timespecsub(vvp, uvp) \
do { \
(vvp)->tv_sec -= (uvp)->tv_sec; \
(vvp)->tv_nsec -= (uvp)->tv_nsec; \
if ((vvp)->tv_nsec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_nsec += 1000000000; \
} \
} while (0)
/* Operations on timevals. */
#define timevalclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
#define timevalisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#define timevalcmp(tvp, uvp, cmp) \
(((tvp)->tv_sec == (uvp)->tv_sec) ? \
((tvp)->tv_usec cmp (uvp)->tv_usec) : \
((tvp)->tv_sec cmp (uvp)->tv_sec))
/* timevaladd and timevalsub are not inlined */
#endif /* KERNEL */
#ifndef KERNEL /* NetBSD/OpenBSD compatable 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
/*
* Names of the interval timers, and structure
* defining a timer setting.
*/
#define ITIMER_REAL 0
#define ITIMER_VIRTUAL 1
#define ITIMER_PROF 2
struct itimerval {
struct timeval it_interval; /* timer interval */
struct timeval it_value; /* current value */
};
/*
* Getkerninfo clock information structure
*/
struct clockinfo {
int hz; /* clock frequency */
int tick; /* micro-seconds per hz tick */
int tickadj; /* clock skew rate for adjtime() */
int stathz; /* statistics clock frequency */
int profhz; /* profiling clock frequency */
};
/* CLOCK_REALTIME and TIMER_ABSTIME are supposed to be in time.h */
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif
#define CLOCK_VIRTUAL 1
#define CLOCK_PROF 2
#define TIMER_RELTIME 0x0 /* relative timer */
#ifndef TIMER_ABSTIME
#define TIMER_ABSTIME 0x1 /* absolute timer */
#endif
#ifdef KERNEL
extern struct timecounter *timecounter;
extern time_t time_second;
void getmicrouptime __P((struct timeval *tv));
void getmicrotime __P((struct timeval *tv));
void getnanouptime __P((struct timespec *tv));
void getnanotime __P((struct timespec *tv));
void init_timecounter __P((struct timecounter *tc));
int itimerdecr __P((struct itimerval *itp, int usec));
int itimerfix __P((struct timeval *tv));
void microuptime __P((struct timeval *tv));
void microtime __P((struct timeval *tv));
void nanouptime __P((struct timespec *ts));
void nanotime __P((struct timespec *ts));
void set_timecounter __P((struct timespec *ts));
void timevaladd __P((struct timeval *, struct timeval *));
void timevalsub __P((struct timeval *, struct timeval *));
int tvtohz __P((struct timeval *));
void update_timecounter __P((struct timecounter *tc));
#else /* !KERNEL */
#include <time.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
int adjtime __P((const struct timeval *, struct timeval *));
int getitimer __P((int, struct itimerval *));
int gettimeofday __P((struct timeval *, struct timezone *));
int setitimer __P((int, const struct itimerval *, struct itimerval *));
int settimeofday __P((const struct timeval *, const struct timezone *));
int utimes __P((const char *, const struct timeval *));
__END_DECLS
#endif /* !KERNEL */
#endif /* !_SYS_TIME_H_ */