summaryrefslogtreecommitdiffstats
path: root/usr.sbin/xntpd/xntpd/ntp_timer.c
blob: 99551f74a9f3f364b9dc6136246757502ffaa60b (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
 * ntp_event.c - event timer support routines
 */
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/signal.h>

#include "ntpd.h"
#include "ntp_stdlib.h"

/*
 * These routines provide support for the event timer.  The timer is
 * implemented by an interrupt routine which sets a flag once every
 * 2**EVENT_TIMEOUT seconds (currently 4), and a timer routine which
 * is called when the mainline code gets around to seeing the flag.
 * The timer routine dispatches the clock adjustment code if its time
 * has come, then searches the timer queue for expiries which are
 * dispatched to the transmit procedure.  Finally, we call the hourly
 * procedure to do cleanup and print a message.
 */

/*
 * Alarm flag.  The mainline code imports this.
 */
int alarm_flag;

/*
 * adjust and hourly counters
 */
static	u_long adjust_timer;
static	u_long hourly_timer;

/*
 * Imported from the leap module.  The leap timer.
 */
extern u_long leap_timer;

/*
 * Statistics counter for the interested.
 */
u_long alarm_overflow;

#define	HOUR	(60*60)

/*
 * Current_time holds the number of seconds since we started, in
 * increments of 2**EVENT_TIMEOUT seconds.  The timer queue is the
 * hash into which we sort timer entries.
 */
u_long current_time;
struct event timerqueue[TIMER_NSLOTS];

/*
 * Stats.  Number of overflows and number of calls to transmit().
 */
u_long timer_timereset;
u_long timer_overflows;
u_long timer_xmtcalls;

static	RETSIGTYPE alarming	P((int));

/*
 * init_timer - initialize the timer data structures
 */
void
init_timer()
{
	register int i;
	struct itimerval itimer;

	/*
	 * Initialize...
	 */
	alarm_flag = 0;
	alarm_overflow = 0;
	adjust_timer = (1<<CLOCK_ADJ);
	hourly_timer = HOUR;
	current_time = 0;
	timer_overflows = 0;
	timer_xmtcalls = 0;
	timer_timereset = 0;

	for (i = 0; i < TIMER_NSLOTS; i++) {
		/*
		 * Queue pointers should point at themselves.  Event
		 * times must be set to 0 since this is used to
		 * detect the queue end.
		 */
		timerqueue[i].next = &timerqueue[i];
		timerqueue[i].prev = &timerqueue[i];
		timerqueue[i].event_time = 0;
	}

	/*
	 * Set up the alarm interrupt.  The first comes 2**EVENT_TIMEOUT
	 * seconds from now and they continue on every 2**EVENT_TIMEOUT
	 * seconds.
	 */
	(void) signal_no_reset(SIGALRM, alarming);
	itimer.it_interval.tv_sec = itimer.it_value.tv_sec = (1<<EVENT_TIMEOUT);
	itimer.it_interval.tv_usec = itimer.it_value.tv_usec = 0;
	setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
}



/*
 * timer - dispatch anyone who needs to be
 */
void
timer()
{
	register struct event *ev;
	register struct event *tq;

	current_time += (1<<EVENT_TIMEOUT);

	/*
	 * Adjustment timeout first
	 */
	if (adjust_timer <= current_time) {
		adjust_timer += (1<<CLOCK_ADJ);
		adj_host_clock();
	}

	/*
	 * Leap timer next.
	 */
	if (leap_timer != 0 && leap_timer <= current_time)
		leap_process();

	/*
	 * Now dispatch any peers whose event timer has expired.
	 */
	tq = &timerqueue[TIMER_SLOT(current_time)];
	ev = tq->next;
	while (ev->event_time != 0
	    && ev->event_time < (current_time + (1<<EVENT_TIMEOUT))) {
		tq->next = ev->next;
		tq->next->prev = tq;
		ev->prev = ev->next = 0;
		timer_xmtcalls++;
		ev->event_handler(ev->peer);
		ev = tq->next;
	}

	/*
	 * Finally, call the hourly routine
	 */
	if (hourly_timer <= current_time) {
		hourly_timer += HOUR;
		hourly_stats();
	}
}


/*
 * alarming - tell the world we've been alarmed
 */
static RETSIGTYPE
alarming(sig)
int sig;
{
	extern int initializing;	/* from main line code */

	if (initializing)
		return;
	if (alarm_flag)
		alarm_overflow++;
	else
		alarm_flag++;
}


/*
 * timer_clr_stats - clear timer module stat counters
 */
void
timer_clr_stats()
{
	timer_overflows = 0;
	timer_xmtcalls = 0;
	timer_timereset = current_time;
}
OpenPOWER on IntegriCloud