2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997-2003
6 * Copyright (C) Miroslav Lichvar 2011, 2013-2016
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 **********************************************************************
23 =======================================================================
25 This file contains the scheduling loop and the timeout queue.
40 /* ================================================== */
42 /* Flag indicating that we are initialised */
43 static int initialised
= 0;
45 /* ================================================== */
47 /* One more than the highest file descriptor that is registered */
48 static unsigned int one_highest_fd
;
51 /* If FD_SETSIZE is not defined, assume that fd_set is implemented
52 as a fixed size array of bits, possibly embedded inside a record */
53 #define FD_SETSIZE (sizeof(fd_set) * 8)
57 SCH_FileHandler handler
;
58 SCH_ArbitraryArgument arg
;
62 static ARR_Instance file_handlers
;
64 /* Timestamp when last select() returned */
65 static struct timespec last_select_ts
, last_select_ts_raw
;
66 static double last_select_ts_err
;
68 #define TS_MONO_PRECISION_NS 10000000U
70 /* Monotonic low-precision timestamp measuring interval since the start */
71 static double last_select_ts_mono
;
72 static uint32_t last_select_ts_mono_ns
;
74 /* ================================================== */
76 /* Variables to handler the timer queue */
78 typedef struct _TimerQueueEntry
80 struct _TimerQueueEntry
*next
; /* Forward and back links in the list */
81 struct _TimerQueueEntry
*prev
;
82 struct timespec ts
; /* Local system time at which the
83 timeout is to expire. Clearly this
84 must be in terms of what the
85 operating system thinks of as
86 system time, because it will be an
87 argument to select(). Therefore,
88 any fudges etc that our local time
89 driver module would apply to time
90 that we pass to clients etc doesn't
92 SCH_TimeoutID id
; /* ID to allow client to delete
94 SCH_TimeoutClass
class; /* The class that the epoch is in */
95 SCH_TimeoutHandler handler
; /* The handler routine to use */
96 SCH_ArbitraryArgument arg
; /* The argument to pass to the handler */
100 /* The timer queue. We only use the next and prev entries of this
101 record, these chain to the real entries. */
102 static TimerQueueEntry timer_queue
;
103 static unsigned long n_timer_queue_entries
;
104 static SCH_TimeoutID next_tqe_id
;
106 /* Pointer to head of free list */
107 static TimerQueueEntry
*tqe_free_list
= NULL
;
109 /* Timestamp when was last timeout dispatched for each class */
110 static struct timespec last_class_dispatch
[SCH_NumberOfClasses
];
112 /* ================================================== */
114 /* Flag terminating the main loop, which can be set from a signal handler */
115 static volatile int need_to_exit
;
117 /* ================================================== */
120 handle_slew(struct timespec
*raw
,
121 struct timespec
*cooked
,
124 LCL_ChangeType change_type
,
127 /* ================================================== */
132 file_handlers
= ARR_CreateInstance(sizeof (FileHandlerEntry
));
134 n_timer_queue_entries
= 0;
137 timer_queue
.next
= &timer_queue
;
138 timer_queue
.prev
= &timer_queue
;
142 LCL_AddParameterChangeHandler(handle_slew
, NULL
);
144 LCL_ReadRawTime(&last_select_ts_raw
);
145 last_select_ts
= last_select_ts_raw
;
146 last_select_ts_mono
= 0.0;
147 last_select_ts_mono_ns
= 0;
153 /* ================================================== */
157 ARR_DestroyInstance(file_handlers
);
159 LCL_RemoveParameterChangeHandler(handle_slew
, NULL
);
164 /* ================================================== */
168 (int fd
, int events
, SCH_FileHandler handler
, SCH_ArbitraryArgument arg
)
170 FileHandlerEntry
*ptr
;
176 if (fd
>= FD_SETSIZE
)
177 LOG_FATAL("Too many file descriptors");
179 /* Resize the array if the descriptor is highest so far */
180 while (ARR_GetSize(file_handlers
) <= fd
) {
181 ptr
= ARR_GetNewElement(file_handlers
);
187 ptr
= ARR_GetElement(file_handlers
, fd
);
189 /* Don't want to allow the same fd to register a handler more than
190 once without deleting a previous association - this suggests
191 a bug somewhere else in the program. */
192 assert(!ptr
->handler
);
194 ptr
->handler
= handler
;
196 ptr
->events
= events
;
198 if (one_highest_fd
< fd
+ 1)
199 one_highest_fd
= fd
+ 1;
203 /* ================================================== */
206 SCH_RemoveFileHandler(int fd
)
208 FileHandlerEntry
*ptr
;
212 ptr
= ARR_GetElement(file_handlers
, fd
);
214 /* Check that a handler was registered for the fd in question */
215 assert(ptr
->handler
);
221 /* Find new highest file descriptor */
222 while (one_highest_fd
> 0) {
223 ptr
= ARR_GetElement(file_handlers
, one_highest_fd
- 1);
230 /* ================================================== */
233 SCH_SetFileHandlerEvent(int fd
, int event
, int enable
)
235 FileHandlerEntry
*ptr
;
237 ptr
= ARR_GetElement(file_handlers
, fd
);
240 ptr
->events
|= event
;
242 ptr
->events
&= ~event
;
245 /* ================================================== */
248 SCH_GetLastEventTime(struct timespec
*cooked
, double *err
, struct timespec
*raw
)
251 *cooked
= last_select_ts
;
253 *err
= last_select_ts_err
;
256 *raw
= last_select_ts_raw
;
259 /* ================================================== */
262 SCH_GetLastEventMonoTime(void)
264 return last_select_ts_mono
;
267 /* ================================================== */
269 #define TQE_ALLOC_QUANTUM 32
271 static TimerQueueEntry
*
274 TimerQueueEntry
*new_block
;
275 TimerQueueEntry
*result
;
277 if (tqe_free_list
== NULL
) {
278 new_block
= MallocArray(TimerQueueEntry
, TQE_ALLOC_QUANTUM
);
279 for (i
=1; i
<TQE_ALLOC_QUANTUM
; i
++) {
280 new_block
[i
].next
= &(new_block
[i
-1]);
282 new_block
[0].next
= NULL
;
283 tqe_free_list
= &(new_block
[TQE_ALLOC_QUANTUM
- 1]);
286 result
= tqe_free_list
;
287 tqe_free_list
= tqe_free_list
->next
;
291 /* ================================================== */
294 release_tqe(TimerQueueEntry
*node
)
296 node
->next
= tqe_free_list
;
297 tqe_free_list
= node
;
300 /* ================================================== */
305 TimerQueueEntry
*ptr
;
312 /* Make sure the ID isn't already used */
313 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
)
314 if (ptr
->id
== next_tqe_id
)
320 /* ================================================== */
323 SCH_AddTimeout(struct timespec
*ts
, SCH_TimeoutHandler handler
, SCH_ArbitraryArgument arg
)
325 TimerQueueEntry
*new_tqe
;
326 TimerQueueEntry
*ptr
;
330 new_tqe
= allocate_tqe();
332 new_tqe
->id
= get_new_tqe_id();
333 new_tqe
->handler
= handler
;
336 new_tqe
->class = SCH_ReservedTimeoutValue
;
338 /* Now work out where to insert the new entry in the list */
339 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
) {
340 if (UTI_CompareTimespecs(&new_tqe
->ts
, &ptr
->ts
) == -1) {
341 /* If the new entry comes before the current pointer location in
342 the list, we want to insert the new entry just before ptr. */
347 /* At this stage, we want to insert the new entry immediately before
348 the entry identified by 'ptr' */
351 new_tqe
->prev
= ptr
->prev
;
352 ptr
->prev
->next
= new_tqe
;
355 n_timer_queue_entries
++;
360 /* ================================================== */
361 /* This queues a timeout to elapse at a given delta time relative to
362 the current (raw) time */
365 SCH_AddTimeoutByDelay(double delay
, SCH_TimeoutHandler handler
, SCH_ArbitraryArgument arg
)
367 struct timespec now
, then
;
370 assert(delay
>= 0.0);
372 LCL_ReadRawTime(&now
);
373 UTI_AddDoubleToTimespec(&now
, delay
, &then
);
374 if (UTI_CompareTimespecs(&now
, &then
) > 0) {
375 LOG_FATAL("Timeout overflow");
378 return SCH_AddTimeout(&then
, handler
, arg
);
382 /* ================================================== */
385 SCH_AddTimeoutInClass(double min_delay
, double separation
, double randomness
,
386 SCH_TimeoutClass
class,
387 SCH_TimeoutHandler handler
, SCH_ArbitraryArgument arg
)
389 TimerQueueEntry
*new_tqe
;
390 TimerQueueEntry
*ptr
;
393 double new_min_delay
;
396 assert(min_delay
>= 0.0);
397 assert(class < SCH_NumberOfClasses
);
399 if (randomness
> 0.0) {
402 UTI_GetRandomBytes(&rnd
, sizeof (rnd
));
403 r
= rnd
* (randomness
/ (uint32_t)-1) + 1.0;
408 LCL_ReadRawTime(&now
);
409 new_min_delay
= min_delay
;
411 /* Check the separation from the last dispatched timeout */
412 diff
= UTI_DiffTimespecsToDouble(&now
, &last_class_dispatch
[class]);
413 if (diff
< separation
&& diff
>= 0.0 && diff
+ new_min_delay
< separation
) {
414 new_min_delay
= separation
- diff
;
417 /* Scan through list for entries in the same class and increase min_delay
418 if necessary to keep at least the separation away */
419 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
) {
420 if (ptr
->class == class) {
421 diff
= UTI_DiffTimespecsToDouble(&ptr
->ts
, &now
);
422 if (new_min_delay
> diff
) {
423 if (new_min_delay
- diff
< separation
) {
424 new_min_delay
= diff
+ separation
;
427 if (diff
- new_min_delay
< separation
) {
428 new_min_delay
= diff
+ separation
;
434 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
) {
435 diff
= UTI_DiffTimespecsToDouble(&ptr
->ts
, &now
);
436 if (diff
> new_min_delay
) {
441 /* We have located the insertion point */
442 new_tqe
= allocate_tqe();
444 new_tqe
->id
= get_new_tqe_id();
445 new_tqe
->handler
= handler
;
447 UTI_AddDoubleToTimespec(&now
, new_min_delay
, &new_tqe
->ts
);
448 new_tqe
->class = class;
451 new_tqe
->prev
= ptr
->prev
;
452 ptr
->prev
->next
= new_tqe
;
454 n_timer_queue_entries
++;
459 /* ================================================== */
462 SCH_RemoveTimeout(SCH_TimeoutID id
)
464 TimerQueueEntry
*ptr
;
471 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
) {
474 /* Found the required entry */
476 /* Unlink from the queue */
477 ptr
->next
->prev
= ptr
->prev
;
478 ptr
->prev
->next
= ptr
->next
;
480 /* Decrement entry count */
481 --n_timer_queue_entries
;
483 /* Release memory back to the operating system */
490 /* Catch calls with invalid non-zero ID */
494 /* ================================================== */
495 /* Try to dispatch any timeouts that have already gone by, and
496 keep going until all are done. (The earlier ones may take so
497 long to do that the later ones come around by the time they are
501 dispatch_timeouts(struct timespec
*now
) {
502 unsigned long n_done
, n_entries_on_start
;
503 TimerQueueEntry
*ptr
;
504 SCH_TimeoutHandler handler
;
505 SCH_ArbitraryArgument arg
;
507 n_entries_on_start
= n_timer_queue_entries
;
511 LCL_ReadRawTime(now
);
513 if (!(n_timer_queue_entries
> 0 &&
514 UTI_CompareTimespecs(now
, &timer_queue
.next
->ts
) >= 0)) {
518 ptr
= timer_queue
.next
;
520 last_class_dispatch
[ptr
->class] = *now
;
522 handler
= ptr
->handler
;
525 SCH_RemoveTimeout(ptr
->id
);
527 /* Dispatch the handler */
530 /* Increment count of timeouts handled */
533 /* If the number of dispatched timeouts is significantly larger than the
534 length of the queue on start and now, assume there is a bug causing
535 an infinite loop by constantly adding a timeout with a zero or negative
536 delay. Check the actual rate of timeouts to avoid false positives in
537 case the execution slowed down so much (e.g. due to memory thrashing)
538 that it repeatedly takes more time to handle the timeout than is its
539 delay. This is a safety mechanism intended to stop a full-speed flood
540 of NTP requests due to a bug in the NTP polling. */
543 n_done
> 4 * MAX(n_timer_queue_entries
, n_entries_on_start
) &&
544 fabs(UTI_DiffTimespecsToDouble(now
, &last_select_ts_raw
)) / n_done
< 0.01)
545 LOG_FATAL("Possible infinite loop in scheduling");
547 } while (!need_to_exit
);
550 /* ================================================== */
552 /* nfd is the number of bits set in all fd_sets */
555 dispatch_filehandlers(int nfd
, fd_set
*read_fds
, fd_set
*write_fds
, fd_set
*except_fds
)
557 FileHandlerEntry
*ptr
;
560 for (fd
= 0; nfd
&& fd
< one_highest_fd
; fd
++) {
561 if (except_fds
&& FD_ISSET(fd
, except_fds
)) {
562 /* This descriptor has an exception, dispatch its handler */
563 ptr
= (FileHandlerEntry
*)ARR_GetElement(file_handlers
, fd
);
565 (ptr
->handler
)(fd
, SCH_FILE_EXCEPTION
, ptr
->arg
);
568 /* Don't try to read from it now */
569 if (read_fds
&& FD_ISSET(fd
, read_fds
)) {
570 FD_CLR(fd
, read_fds
);
575 if (read_fds
&& FD_ISSET(fd
, read_fds
)) {
576 /* This descriptor can be read from, dispatch its handler */
577 ptr
= (FileHandlerEntry
*)ARR_GetElement(file_handlers
, fd
);
579 (ptr
->handler
)(fd
, SCH_FILE_INPUT
, ptr
->arg
);
583 if (write_fds
&& FD_ISSET(fd
, write_fds
)) {
584 /* This descriptor can be written to, dispatch its handler */
585 ptr
= (FileHandlerEntry
*)ARR_GetElement(file_handlers
, fd
);
587 (ptr
->handler
)(fd
, SCH_FILE_OUTPUT
, ptr
->arg
);
593 /* ================================================== */
596 handle_slew(struct timespec
*raw
,
597 struct timespec
*cooked
,
600 LCL_ChangeType change_type
,
603 TimerQueueEntry
*ptr
;
607 if (change_type
!= LCL_ChangeAdjust
) {
608 /* Make sure this handler is invoked first in order to not shift new timers
609 added from other handlers */
610 assert(LCL_IsFirstParameterChangeHandler(handle_slew
));
612 /* If a step change occurs, just shift all raw time stamps by the offset */
614 for (ptr
= timer_queue
.next
; ptr
!= &timer_queue
; ptr
= ptr
->next
) {
615 UTI_AddDoubleToTimespec(&ptr
->ts
, -doffset
, &ptr
->ts
);
618 for (i
= 0; i
< SCH_NumberOfClasses
; i
++) {
619 UTI_AddDoubleToTimespec(&last_class_dispatch
[i
], -doffset
, &last_class_dispatch
[i
]);
622 UTI_AddDoubleToTimespec(&last_select_ts_raw
, -doffset
, &last_select_ts_raw
);
625 UTI_AdjustTimespec(&last_select_ts
, cooked
, &last_select_ts
, &delta
, dfreq
, doffset
);
628 /* ================================================== */
631 fill_fd_sets(fd_set
**read_fds
, fd_set
**write_fds
, fd_set
**except_fds
)
633 FileHandlerEntry
*handlers
;
634 fd_set
*rd
, *wr
, *ex
;
637 n
= ARR_GetSize(file_handlers
);
638 handlers
= ARR_GetElements(file_handlers
);
641 for (i
= 0; i
< n
; i
++) {
642 events
= handlers
[i
].events
;
647 if (events
& SCH_FILE_INPUT
) {
655 if (events
& SCH_FILE_OUTPUT
) {
663 if (events
& SCH_FILE_EXCEPTION
) {
680 /* ================================================== */
682 #define JUMP_DETECT_THRESHOLD 10
685 check_current_time(struct timespec
*prev_raw
, struct timespec
*raw
, int timeout
,
686 struct timeval
*orig_select_tv
,
687 struct timeval
*rem_select_tv
)
689 struct timespec elapsed_min
, elapsed_max
, orig_select_ts
, rem_select_ts
;
690 double step
, elapsed
;
692 UTI_TimevalToTimespec(orig_select_tv
, &orig_select_ts
);
694 /* Get an estimate of the time spent waiting in the select() call. On some
695 systems (e.g. Linux) the timeout timeval is modified to return the
696 remaining time, use that information. */
698 elapsed_max
= elapsed_min
= orig_select_ts
;
699 } else if (rem_select_tv
&& rem_select_tv
->tv_sec
>= 0 &&
700 rem_select_tv
->tv_sec
<= orig_select_tv
->tv_sec
&&
701 (rem_select_tv
->tv_sec
!= orig_select_tv
->tv_sec
||
702 rem_select_tv
->tv_usec
!= orig_select_tv
->tv_usec
)) {
703 UTI_TimevalToTimespec(rem_select_tv
, &rem_select_ts
);
704 UTI_DiffTimespecs(&elapsed_min
, &orig_select_ts
, &rem_select_ts
);
705 elapsed_max
= elapsed_min
;
708 elapsed_max
= orig_select_ts
;
710 UTI_DiffTimespecs(&elapsed_max
, raw
, prev_raw
);
711 UTI_ZeroTimespec(&elapsed_min
);
714 if (last_select_ts_raw
.tv_sec
+ elapsed_min
.tv_sec
>
715 raw
->tv_sec
+ JUMP_DETECT_THRESHOLD
) {
716 LOG(LOGS_WARN
, "Backward time jump detected!");
717 } else if (prev_raw
->tv_sec
+ elapsed_max
.tv_sec
+ JUMP_DETECT_THRESHOLD
<
719 LOG(LOGS_WARN
, "Forward time jump detected!");
724 step
= UTI_DiffTimespecsToDouble(&last_select_ts_raw
, raw
);
725 elapsed
= UTI_TimespecToDouble(&elapsed_min
);
728 /* Cooked time may no longer be valid after dispatching the handlers */
729 LCL_NotifyExternalTimeStep(raw
, raw
, step
, fabs(step
));
734 /* ================================================== */
737 update_monotonic_time(struct timespec
*now
, struct timespec
*before
)
739 struct timespec diff
;
741 /* Avoid frequent floating-point operations and handle small
742 increments to a large value */
744 UTI_DiffTimespecs(&diff
, now
, before
);
745 if (diff
.tv_sec
== 0) {
746 last_select_ts_mono_ns
+= diff
.tv_nsec
;
748 last_select_ts_mono
+= fabs(UTI_TimespecToDouble(&diff
) +
749 last_select_ts_mono_ns
/ 1.0e9
);
750 last_select_ts_mono_ns
= 0;
753 if (last_select_ts_mono_ns
> TS_MONO_PRECISION_NS
) {
754 last_select_ts_mono
+= last_select_ts_mono_ns
/ 1.0e9
;
755 last_select_ts_mono_ns
= 0;
759 /* ================================================== */
764 fd_set read_fds
, write_fds
, except_fds
;
765 fd_set
*p_read_fds
, *p_write_fds
, *p_except_fds
;
767 struct timeval tv
, saved_tv
, *ptv
;
768 struct timespec ts
, now
, saved_now
, cooked
;
773 while (!need_to_exit
) {
774 /* Dispatch timeouts and fill now with current raw time */
775 dispatch_timeouts(&now
);
778 /* The timeout handlers may request quit */
782 /* Check whether there is a timeout and set it up */
783 if (n_timer_queue_entries
> 0) {
784 UTI_DiffTimespecs(&ts
, &timer_queue
.next
->ts
, &now
);
785 assert(ts
.tv_sec
> 0 || ts
.tv_nsec
> 0);
787 UTI_TimespecToTimeval(&ts
, &tv
);
792 saved_tv
.tv_sec
= saved_tv
.tv_usec
= 0;
795 p_read_fds
= &read_fds
;
796 p_write_fds
= &write_fds
;
797 p_except_fds
= &except_fds
;
798 fill_fd_sets(&p_read_fds
, &p_write_fds
, &p_except_fds
);
800 /* if there are no file descriptors being waited on and no
801 timeout set, this is clearly ridiculous, so stop the run */
802 if (!ptv
&& !p_read_fds
&& !p_write_fds
)
803 LOG_FATAL("Nothing to do");
805 status
= select(one_highest_fd
, p_read_fds
, p_write_fds
, p_except_fds
, ptv
);
808 LCL_ReadRawTime(&now
);
809 LCL_CookTime(&now
, &cooked
, &err
);
811 update_monotonic_time(&now
, &last_select_ts_raw
);
813 /* Check if the time didn't jump unexpectedly */
814 if (!check_current_time(&saved_now
, &now
, status
== 0, &saved_tv
, ptv
)) {
815 /* Cook the time again after handling the step */
816 LCL_CookTime(&now
, &cooked
, &err
);
819 last_select_ts_raw
= now
;
820 last_select_ts
= cooked
;
821 last_select_ts_err
= err
;
824 if (!need_to_exit
&& errsv
!= EINTR
) {
825 LOG_FATAL("select() failed : %s", strerror(errsv
));
827 } else if (status
> 0) {
828 /* A file descriptor is ready for input or output */
829 dispatch_filehandlers(status
, p_read_fds
, p_write_fds
, p_except_fds
);
831 /* No descriptors readable, timeout must have elapsed.
832 Therefore, tv must be non-null */
835 /* There's nothing to do here, since the timeouts
836 will be dispatched at the top of the next loop
843 /* ================================================== */
846 SCH_QuitProgram(void)
851 /* ================================================== */