91266b96c4
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!)
105 lines
3.6 KiB
C
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_ */
|