freebsd-nq/sys/sys/timetc.h
Poul-Henning Kamp 91266b96c4 Isolate the Timecounter internals in their own two files.
Make the public interface more systematically named.

Remove the alternate method, it doesn't do any good, only ruins performance.

Add counters to profile the usage of the 8 access functions.

Apply the beer-ware to my code.

The weird +/- counts are caused by two repocopies behind the scenes:
	kern/kern_clock.c -> kern/kern_tc.c
	sys/time.h -> sys/timetc.h
(thanks peter!)
2000-03-20 14:09:06 +00:00

105 lines
3.6 KiB
C

/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
* $FreeBSD$
*/
#ifndef _SYS_TIMETC_H_
#define _SYS_TIMETC_H_
/*
* 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
extern struct timecounter *timecounter;
void tc_init __P((struct timecounter *tc));
void tc_setclock __P((struct timespec *ts));
void tc_windup __P((void));
void tc_update __P((struct timecounter *tc));
#endif /* !_KERNEL */
#endif /* !_SYS_TIMETC_H_ */