aboutsummaryrefslogtreecommitdiff
path: root/sys/sys/timetc.h
blob: dccee1364bdf1556cb78b6911fbbcd146a757c14 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*	$OpenBSD: timetc.h,v 1.12 2020/07/06 13:33:09 pirofti Exp $ */

/*
 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * If we meet some day, and you think this stuff is worth it, you
 * can buy me a beer in return. Poul-Henning Kamp
 */

#ifndef _SYS_TIMETC_H_
#define	_SYS_TIMETC_H_

#if !defined(_KERNEL) && !defined(_LIBC)
#error "no user-serviceable parts inside"
#endif

#include <machine/timetc.h>
#include <sys/queue.h>

/*-
 * `struct timecounter' is the interface between the hardware which implements
 * a timecounter and the MI code which uses this to keep track of time.
 *
 * A timecounter is a binary counter which has two properties:
 *    * it runs at a fixed, known frequency.
 *    * it has sufficient bits to not roll over in less than approximately
 *      max(2 msec, 2/HZ seconds).  (The value 2 here is really 1 + delta,
 *      for some indeterminate value of delta.)
 */

struct timecounter;
typedef u_int timecounter_get_t(struct timecounter *);
typedef void timecounter_pps_t(struct timecounter *);

/*
 * Locks used to protect struct members in this file:
 *	I	immutable after initialization
 *	T	tc_lock
 *	W	windup_mtx
 */

struct timecounter {
	timecounter_get_t	*tc_get_timecount;	/* [I] */
		/*
		 * This function reads the counter.  It is not required to
		 * mask any unimplemented bits out, as long as they are
		 * constant.
		 */
	timecounter_pps_t	*tc_poll_pps;		/* [I] */
		/*
		 * This function is optional.  It will be called whenever the
		 * timecounter is rewound, and is intended to check for PPS
		 * events.  Normal hardware does not need it but timecounters
		 * which latch PPS in hardware (like sys/pci/xrpu.c) do.
		 */
	u_int 			tc_counter_mask;	/* [I] */
		/* This mask should mask off any unimplemented bits. */
	u_int64_t		tc_frequency;		/* [I] */
		/* Frequency of the counter in Hz. */
	char			*tc_name;		/* [I] */
		/* Name of the timecounter. */
	int			tc_quality;		/* [I] */
		/*
		 * Used to determine if this timecounter is better than
		 * another timecounter higher means better.  Negative
		 * means "only use at explicit request".
		 */
	void			*tc_priv;		/* [I] */
		/* Pointer to the timecounter's private parts. */
	int			tc_user;		/* [I] */
		/* Expose this timecounter to userland. */
	SLIST_ENTRY(timecounter) tc_next;		/* [I] */
		/* Pointer to the next timecounter. */
	int64_t			tc_freq_adj;		/* [T,W] */
		/* Current frequency adjustment. */
	u_int64_t		tc_precision;		/* [I] */
		/* Precision of the counter.  Computed in tc_init(). */
};

struct timekeep {
	/* set at initialization */
	uint32_t	tk_version;		/* version number */

	/* timehands members */
	uint64_t	tk_scale;
	u_int		tk_offset_count;
	struct bintime	tk_offset;
	struct bintime	tk_naptime;
	struct bintime	tk_boottime;
	volatile u_int	tk_generation;

	/* timecounter members */
	int		tk_user;
	u_int		tk_counter_mask;
};
#define TK_VERSION	0

struct rwlock;
extern struct rwlock tc_lock;

extern struct timecounter *timecounter;

extern struct uvm_object *timekeep_object;
extern struct timekeep *timekeep;

u_int64_t tc_getfrequency(void);
u_int64_t tc_getprecision(void);
void	tc_init(struct timecounter *tc);
void	tc_setclock(const struct timespec *ts);
void	tc_setrealtimeclock(const struct timespec *ts);
void	tc_ticktock(void);
void	inittimecounter(void);
int	sysctl_tc(int *, u_int, void *, size_t *, void *, size_t);
void	tc_adjfreq(int64_t *, int64_t *);
void	tc_adjtime(int64_t *, int64_t *);

#endif /* !_SYS_TIMETC_H_ */