FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_tc.c
1 /* $OpenBSD: kern_tc.c,v 1.81 2022/12/13 17:30:36 cheloha Exp $ */
2
3 /*
4 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /*
20 * If we meet some day, and you think this stuff is worth it, you
21 * can buy me a beer in return. Poul-Henning Kamp
22 */
23
24 #include <sys/param.h>
25 #include <sys/atomic.h>
26 #include <sys/kernel.h>
27 #include <sys/mutex.h>
28 #include <sys/rwlock.h>
29 #include <sys/stdint.h>
30 #include <sys/timeout.h>
31 #include <sys/sysctl.h>
32 #include <sys/syslog.h>
33 #include <sys/systm.h>
34 #include <sys/timetc.h>
35 #include <sys/queue.h>
36 #include <sys/malloc.h>
37
38 u_int dummy_get_timecount(struct timecounter *);
39
40 int sysctl_tc_hardware(void *, size_t *, void *, size_t);
41 int sysctl_tc_choice(void *, size_t *, void *, size_t);
42
43 /*
44 * Implement a dummy timecounter which we can use until we get a real one
45 * in the air. This allows the console and other early stuff to use
46 * time services.
47 */
48
49 u_int
50 dummy_get_timecount(struct timecounter *tc)
51 {
52 static u_int now;
53
54 return atomic_inc_int_nv(&now);
55 }
56
57 static struct timecounter dummy_timecounter = {
58 .tc_get_timecount = dummy_get_timecount,
59 .tc_poll_pps = NULL,
60 .tc_counter_mask = ~0u,
61 .tc_frequency = 1000000,
62 .tc_name = "dummy",
63 .tc_quality = -1000000,
64 .tc_priv = NULL,
65 .tc_user = 0,
66 };
67
68 /*
69 * Locks used to protect struct members, global variables in this file:
70 * I immutable after initialization
71 * T tc_lock
72 * W windup_mtx
73 */
74
75 struct timehands {
76 /* These fields must be initialized by the driver. */
77 struct timecounter *th_counter; /* [W] */
78 int64_t th_adjtimedelta; /* [T,W] */
79 struct bintime th_next_ntp_update; /* [T,W] */
80 int64_t th_adjustment; /* [W] */
81 u_int64_t th_scale; /* [W] */
82 u_int th_offset_count; /* [W] */
83 struct bintime th_boottime; /* [T,W] */
84 struct bintime th_offset; /* [W] */
85 struct bintime th_naptime; /* [W] */
86 struct timeval th_microtime; /* [W] */
87 struct timespec th_nanotime; /* [W] */
88 /* Fields not to be copied in tc_windup start with th_generation. */
89 volatile u_int th_generation; /* [W] */
90 struct timehands *th_next; /* [I] */
91 };
92
93 static struct timehands th0;
94 static struct timehands th1 = {
95 .th_next = &th0
96 };
97 static struct timehands th0 = {
98 .th_counter = &dummy_timecounter,
99 .th_scale = UINT64_MAX / 1000000,
100 .th_offset = { .sec = 1, .frac = 0 },
101 .th_generation = 1,
102 .th_next = &th1
103 };
104
105 struct rwlock tc_lock = RWLOCK_INITIALIZER("tc_lock");
106
107 /*
108 * tc_windup() must be called before leaving this mutex.
109 */
110 struct mutex windup_mtx = MUTEX_INITIALIZER(IPL_CLOCK);
111
112 static struct timehands *volatile timehands = &th0; /* [W] */
113 struct timecounter *timecounter = &dummy_timecounter; /* [T] */
114 static SLIST_HEAD(, timecounter) tc_list = SLIST_HEAD_INITIALIZER(tc_list);
115
116 /*
117 * These are updated from tc_windup(). They are useful when
118 * examining kernel core dumps.
119 */
120 volatile time_t naptime = 0;
121 volatile time_t time_second = 1;
122 volatile time_t time_uptime = 0;
123
124 static int timestepwarnings;
125
126 void ntp_update_second(struct timehands *);
127 void tc_windup(struct bintime *, struct bintime *, int64_t *);
128
129 /*
130 * Return the difference between the timehands' counter value now and what
131 * was when we copied it to the timehands' offset_count.
132 */
133 static __inline u_int
134 tc_delta(struct timehands *th)
135 {
136 struct timecounter *tc;
137
138 tc = th->th_counter;
139 return ((tc->tc_get_timecount(tc) - th->th_offset_count) &
140 tc->tc_counter_mask);
141 }
142
143 /*
144 * Functions for reading the time. We have to loop until we are sure that
145 * the timehands that we operated on was not updated under our feet. See
146 * the comment in <sys/time.h> for a description of these functions.
147 */
148
149 void
150 binboottime(struct bintime *bt)
151 {
152 struct timehands *th;
153 u_int gen;
154
155 do {
156 th = timehands;
157 gen = th->th_generation;
158 membar_consumer();
159 *bt = th->th_boottime;
160 membar_consumer();
161 } while (gen == 0 || gen != th->th_generation);
162 }
163
164 void
165 microboottime(struct timeval *tvp)
166 {
167 struct bintime bt;
168
169 binboottime(&bt);
170 BINTIME_TO_TIMEVAL(&bt, tvp);
171 }
172
173 void
174 nanoboottime(struct timespec *tsp)
175 {
176 struct bintime bt;
177
178 binboottime(&bt);
179 BINTIME_TO_TIMESPEC(&bt, tsp);
180 }
181
182 void
183 binuptime(struct bintime *bt)
184 {
185 struct timehands *th;
186 u_int gen;
187
188 do {
189 th = timehands;
190 gen = th->th_generation;
191 membar_consumer();
192 TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt);
193 bintimeadd(bt, &th->th_offset, bt);
194 membar_consumer();
195 } while (gen == 0 || gen != th->th_generation);
196 }
197
198 void
199 getbinuptime(struct bintime *bt)
200 {
201 struct timehands *th;
202 u_int gen;
203
204 do {
205 th = timehands;
206 gen = th->th_generation;
207 membar_consumer();
208 *bt = th->th_offset;
209 membar_consumer();
210 } while (gen == 0 || gen != th->th_generation);
211 }
212
213 void
214 nanouptime(struct timespec *tsp)
215 {
216 struct bintime bt;
217
218 binuptime(&bt);
219 BINTIME_TO_TIMESPEC(&bt, tsp);
220 }
221
222 void
223 microuptime(struct timeval *tvp)
224 {
225 struct bintime bt;
226
227 binuptime(&bt);
228 BINTIME_TO_TIMEVAL(&bt, tvp);
229 }
230
231 time_t
232 getuptime(void)
233 {
234 #if defined(__LP64__)
235 return time_uptime; /* atomic */
236 #else
237 time_t now;
238 struct timehands *th;
239 u_int gen;
240
241 do {
242 th = timehands;
243 gen = th->th_generation;
244 membar_consumer();
245 now = th->th_offset.sec;
246 membar_consumer();
247 } while (gen == 0 || gen != th->th_generation);
248
249 return now;
250 #endif
251 }
252
253 uint64_t
254 nsecuptime(void)
255 {
256 struct bintime bt;
257
258 binuptime(&bt);
259 return BINTIME_TO_NSEC(&bt);
260 }
261
262 uint64_t
263 getnsecuptime(void)
264 {
265 struct bintime bt;
266
267 getbinuptime(&bt);
268 return BINTIME_TO_NSEC(&bt);
269 }
270
271 void
272 binruntime(struct bintime *bt)
273 {
274 struct timehands *th;
275 u_int gen;
276
277 do {
278 th = timehands;
279 gen = th->th_generation;
280 membar_consumer();
281 TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt);
282 bintimeadd(bt, &th->th_offset, bt);
283 bintimesub(bt, &th->th_naptime, bt);
284 membar_consumer();
285 } while (gen == 0 || gen != th->th_generation);
286 }
287
288 void
289 nanoruntime(struct timespec *ts)
290 {
291 struct bintime bt;
292
293 binruntime(&bt);
294 BINTIME_TO_TIMESPEC(&bt, ts);
295 }
296
297 void
298 getbinruntime(struct bintime *bt)
299 {
300 struct timehands *th;
301 u_int gen;
302
303 do {
304 th = timehands;
305 gen = th->th_generation;
306 membar_consumer();
307 bintimesub(&th->th_offset, &th->th_naptime, bt);
308 membar_consumer();
309 } while (gen == 0 || gen != th->th_generation);
310 }
311
312 uint64_t
313 getnsecruntime(void)
314 {
315 struct bintime bt;
316
317 getbinruntime(&bt);
318 return BINTIME_TO_NSEC(&bt);
319 }
320
321 void
322 bintime(struct bintime *bt)
323 {
324 struct timehands *th;
325 u_int gen;
326
327 do {
328 th = timehands;
329 gen = th->th_generation;
330 membar_consumer();
331 TIMECOUNT_TO_BINTIME(tc_delta(th), th->th_scale, bt);
332 bintimeadd(bt, &th->th_offset, bt);
333 bintimeadd(bt, &th->th_boottime, bt);
334 membar_consumer();
335 } while (gen == 0 || gen != th->th_generation);
336 }
337
338 void
339 nanotime(struct timespec *tsp)
340 {
341 struct bintime bt;
342
343 bintime(&bt);
344 BINTIME_TO_TIMESPEC(&bt, tsp);
345 }
346
347 void
348 microtime(struct timeval *tvp)
349 {
350 struct bintime bt;
351
352 bintime(&bt);
353 BINTIME_TO_TIMEVAL(&bt, tvp);
354 }
355
356 time_t
357 gettime(void)
358 {
359 #if defined(__LP64__)
360 return time_second; /* atomic */
361 #else
362 time_t now;
363 struct timehands *th;
364 u_int gen;
365
366 do {
367 th = timehands;
368 gen = th->th_generation;
369 membar_consumer();
370 now = th->th_microtime.tv_sec;
371 membar_consumer();
372 } while (gen == 0 || gen != th->th_generation);
373
374 return now;
375 #endif
376 }
377
378 void
379 getnanouptime(struct timespec *tsp)
380 {
381 struct timehands *th;
382 u_int gen;
383
384 do {
385 th = timehands;
386 gen = th->th_generation;
387 membar_consumer();
388 BINTIME_TO_TIMESPEC(&th->th_offset, tsp);
389 membar_consumer();
390 } while (gen == 0 || gen != th->th_generation);
391 }
392
393 void
394 getmicrouptime(struct timeval *tvp)
395 {
396 struct timehands *th;
397 u_int gen;
398
399 do {
400 th = timehands;
401 gen = th->th_generation;
402 membar_consumer();
403 BINTIME_TO_TIMEVAL(&th->th_offset, tvp);
404 membar_consumer();
405 } while (gen == 0 || gen != th->th_generation);
406 }
407
408 void
409 getnanotime(struct timespec *tsp)
410 {
411 struct timehands *th;
412 u_int gen;
413
414 do {
415 th = timehands;
416 gen = th->th_generation;
417 membar_consumer();
418 *tsp = th->th_nanotime;
419 membar_consumer();
420 } while (gen == 0 || gen != th->th_generation);
421 }
422
423 void
424 getmicrotime(struct timeval *tvp)
425 {
426 struct timehands *th;
427 u_int gen;
428
429 do {
430 th = timehands;
431 gen = th->th_generation;
432 membar_consumer();
433 *tvp = th->th_microtime;
434 membar_consumer();
435 } while (gen == 0 || gen != th->th_generation);
436 }
437
438 /*
439 * Initialize a new timecounter and possibly use it.
440 */
441 void
442 tc_init(struct timecounter *tc)
443 {
444 u_int64_t tmp;
445 u_int u;
446
447 u = tc->tc_frequency / tc->tc_counter_mask;
448 /* XXX: We need some margin here, 10% is a guess */
449 u *= 11;
450 u /= 10;
451 if (tc->tc_quality >= 0) {
452 if (u > hz) {
453 tc->tc_quality = -2000;
454 printf("Timecounter \"%s\" frequency %lu Hz",
455 tc->tc_name, (unsigned long)tc->tc_frequency);
456 printf(" -- Insufficient hz, needs at least %u\n", u);
457 }
458 }
459
460 /* Determine the counter's precision. */
461 for (tmp = 1; (tmp & tc->tc_counter_mask) == 0; tmp <<= 1)
462 continue;
463 tc->tc_precision = tmp;
464
465 SLIST_INSERT_HEAD(&tc_list, tc, tc_next);
466
467 /*
468 * Never automatically use a timecounter with negative quality.
469 * Even though we run on the dummy counter, switching here may be
470 * worse since this timecounter may not be monotonic.
471 */
472 if (tc->tc_quality < 0)
473 return;
474 if (tc->tc_quality < timecounter->tc_quality)
475 return;
476 if (tc->tc_quality == timecounter->tc_quality &&
477 tc->tc_frequency < timecounter->tc_frequency)
478 return;
479 (void)tc->tc_get_timecount(tc);
480 enqueue_randomness(tc->tc_get_timecount(tc));
481
482 timecounter = tc;
483 }
484
485 /*
486 * Change the given timecounter's quality. If it is the active
487 * counter and it is no longer the best counter, activate the
488 * best counter.
489 */
490 void
491 tc_reset_quality(struct timecounter *tc, int quality)
492 {
493 struct timecounter *best = &dummy_timecounter, *tmp;
494
495 if (tc == &dummy_timecounter)
496 panic("%s: cannot change dummy counter quality", __func__);
497
498 tc->tc_quality = quality;
499 if (timecounter == tc) {
500 SLIST_FOREACH(tmp, &tc_list, tc_next) {
501 if (tmp->tc_quality < 0)
502 continue;
503 if (tmp->tc_quality < best->tc_quality)
504 continue;
505 if (tmp->tc_quality == best->tc_quality &&
506 tmp->tc_frequency < best->tc_frequency)
507 continue;
508 best = tmp;
509 }
510 if (best != tc) {
511 enqueue_randomness(best->tc_get_timecount(best));
512 timecounter = best;
513 printf("timecounter: active counter changed: %s -> %s\n",
514 tc->tc_name, best->tc_name);
515 }
516 }
517 }
518
519 /* Report the frequency of the current timecounter. */
520 u_int64_t
521 tc_getfrequency(void)
522 {
523 return (timehands->th_counter->tc_frequency);
524 }
525
526 /* Report the precision of the current timecounter. */
527 u_int64_t
528 tc_getprecision(void)
529 {
530 return (timehands->th_counter->tc_precision);
531 }
532
533 /*
534 * Step our concept of UTC, aka the realtime clock.
535 * This is done by modifying our estimate of when we booted.
536 *
537 * Any ongoing adjustment is meaningless after a clock jump,
538 * so we zero adjtimedelta here as well.
539 */
540 void
541 tc_setrealtimeclock(const struct timespec *ts)
542 {
543 struct bintime boottime, old_utc, uptime, utc;
544 struct timespec tmp;
545 int64_t zero = 0;
546
547 TIMESPEC_TO_BINTIME(ts, &utc);
548
549 rw_enter_write(&tc_lock);
550 mtx_enter(&windup_mtx);
551
552 binuptime(&uptime);
553 bintimesub(&utc, &uptime, &boottime);
554 bintimeadd(&timehands->th_boottime, &uptime, &old_utc);
555 /* XXX fiddle all the little crinkly bits around the fiords... */
556 tc_windup(&boottime, NULL, &zero);
557
558 mtx_leave(&windup_mtx);
559 rw_exit_write(&tc_lock);
560
561 enqueue_randomness(ts->tv_sec);
562
563 if (timestepwarnings) {
564 BINTIME_TO_TIMESPEC(&old_utc, &tmp);
565 log(LOG_INFO, "Time stepped from %lld.%09ld to %lld.%09ld\n",
566 (long long)tmp.tv_sec, tmp.tv_nsec,
567 (long long)ts->tv_sec, ts->tv_nsec);
568 }
569 }
570
571 /*
572 * Step the monotonic and realtime clocks, triggering any timeouts that
573 * should have occurred across the interval.
574 */
575 void
576 tc_setclock(const struct timespec *ts)
577 {
578 struct bintime new_naptime, old_naptime, uptime, utc;
579 static int first = 1;
580 #ifndef SMALL_KERNEL
581 struct bintime elapsed;
582 long long adj_ticks;
583 #endif
584
585 /*
586 * When we're called for the first time, during boot when
587 * the root partition is mounted, we need to set boottime.
588 */
589 if (first) {
590 tc_setrealtimeclock(ts);
591 first = 0;
592 return;
593 }
594
595 enqueue_randomness(ts->tv_sec);
596
597 TIMESPEC_TO_BINTIME(ts, &utc);
598
599 mtx_enter(&windup_mtx);
600
601 bintimesub(&utc, &timehands->th_boottime, &uptime);
602 old_naptime = timehands->th_naptime;
603 /* XXX fiddle all the little crinkly bits around the fiords... */
604 tc_windup(NULL, &uptime, NULL);
605 new_naptime = timehands->th_naptime;
606
607 mtx_leave(&windup_mtx);
608
609 #ifndef SMALL_KERNEL
610 /* convert the bintime to ticks */
611 bintimesub(&new_naptime, &old_naptime, &elapsed);
612 adj_ticks = BINTIME_TO_NSEC(&elapsed) / tick_nsec;
613 if (adj_ticks > 0) {
614 if (adj_ticks > INT_MAX)
615 adj_ticks = INT_MAX;
616 timeout_adjust_ticks(adj_ticks);
617 }
618 #endif
619 }
620
621 void
622 tc_update_timekeep(void)
623 {
624 static struct timecounter *last_tc = NULL;
625 struct timehands *th;
626
627 MUTEX_ASSERT_LOCKED(&windup_mtx);
628
629 if (timekeep == NULL)
630 return;
631
632 th = timehands;
633 timekeep->tk_generation = 0;
634 membar_producer();
635 timekeep->tk_scale = th->th_scale;
636 timekeep->tk_offset_count = th->th_offset_count;
637 timekeep->tk_offset = th->th_offset;
638 timekeep->tk_naptime = th->th_naptime;
639 timekeep->tk_boottime = th->th_boottime;
640 if (last_tc != th->th_counter) {
641 timekeep->tk_counter_mask = th->th_counter->tc_counter_mask;
642 timekeep->tk_user = th->th_counter->tc_user;
643 last_tc = th->th_counter;
644 }
645 membar_producer();
646 timekeep->tk_generation = th->th_generation;
647
648 return;
649 }
650
651 /*
652 * Initialize the next struct timehands in the ring and make
653 * it the active timehands. Along the way we might switch to a different
654 * timecounter and/or do seconds processing in NTP. Slightly magic.
655 */
656 void
657 tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
658 int64_t *new_adjtimedelta)
659 {
660 struct bintime bt;
661 struct timecounter *active_tc;
662 struct timehands *th, *tho;
663 u_int64_t scale;
664 u_int delta, ncount, ogen;
665
666 if (new_boottime != NULL || new_adjtimedelta != NULL)
667 rw_assert_wrlock(&tc_lock);
668 MUTEX_ASSERT_LOCKED(&windup_mtx);
669
670 active_tc = timecounter;
671
672 /*
673 * Make the next timehands a copy of the current one, but do not
674 * overwrite the generation or next pointer. While we update
675 * the contents, the generation must be zero.
676 */
677 tho = timehands;
678 ogen = tho->th_generation;
679 th = tho->th_next;
680 th->th_generation = 0;
681 membar_producer();
682 memcpy(th, tho, offsetof(struct timehands, th_generation));
683
684 /*
685 * Capture a timecounter delta on the current timecounter and if
686 * changing timecounters, a counter value from the new timecounter.
687 * Update the offset fields accordingly.
688 */
689 delta = tc_delta(th);
690 if (th->th_counter != active_tc)
691 ncount = active_tc->tc_get_timecount(active_tc);
692 else
693 ncount = 0;
694 th->th_offset_count += delta;
695 th->th_offset_count &= th->th_counter->tc_counter_mask;
696 TIMECOUNT_TO_BINTIME(delta, th->th_scale, &bt);
697 bintimeadd(&th->th_offset, &bt, &th->th_offset);
698
699 /*
700 * Ignore new offsets that predate the current offset.
701 * If changing the offset, first increase the naptime
702 * accordingly.
703 */
704 if (new_offset != NULL && bintimecmp(&th->th_offset, new_offset, <)) {
705 bintimesub(new_offset, &th->th_offset, &bt);
706 bintimeadd(&th->th_naptime, &bt, &th->th_naptime);
707 naptime = th->th_naptime.sec;
708 th->th_offset = *new_offset;
709 }
710
711 #ifdef notyet
712 /*
713 * Hardware latching timecounters may not generate interrupts on
714 * PPS events, so instead we poll them. There is a finite risk that
715 * the hardware might capture a count which is later than the one we
716 * got above, and therefore possibly in the next NTP second which might
717 * have a different rate than the current NTP second. It doesn't
718 * matter in practice.
719 */
720 if (tho->th_counter->tc_poll_pps)
721 tho->th_counter->tc_poll_pps(tho->th_counter);
722 #endif
723
724 /*
725 * If changing the boot time or clock adjustment, do so before
726 * NTP processing.
727 */
728 if (new_boottime != NULL)
729 th->th_boottime = *new_boottime;
730 if (new_adjtimedelta != NULL) {
731 th->th_adjtimedelta = *new_adjtimedelta;
732 /* Reset the NTP update period. */
733 bintimesub(&th->th_offset, &th->th_naptime,
734 &th->th_next_ntp_update);
735 }
736
737 /*
738 * Deal with NTP second processing. The while-loop normally
739 * iterates at most once, but in extreme situations it might
740 * keep NTP sane if tc_windup() is not run for several seconds.
741 */
742 bintimesub(&th->th_offset, &th->th_naptime, &bt);
743 while (bintimecmp(&th->th_next_ntp_update, &bt, <=)) {
744 ntp_update_second(th);
745 th->th_next_ntp_update.sec++;
746 }
747
748 /* Update the UTC timestamps used by the get*() functions. */
749 bintimeadd(&th->th_boottime, &th->th_offset, &bt);
750 BINTIME_TO_TIMEVAL(&bt, &th->th_microtime);
751 BINTIME_TO_TIMESPEC(&bt, &th->th_nanotime);
752
753 /* Now is a good time to change timecounters. */
754 if (th->th_counter != active_tc) {
755 th->th_counter = active_tc;
756 th->th_offset_count = ncount;
757 }
758
759 /*-
760 * Recalculate the scaling factor. We want the number of 1/2^64
761 * fractions of a second per period of the hardware counter, taking
762 * into account the th_adjustment factor which the NTP PLL/adjtime(2)
763 * processing provides us with.
764 *
765 * The th_adjustment is nanoseconds per second with 32 bit binary
766 * fraction and we want 64 bit binary fraction of second:
767 *
768 * x = a * 2^32 / 10^9 = a * 4.294967296
769 *
770 * The range of th_adjustment is +/- 5000PPM so inside a 64bit int
771 * we can only multiply by about 850 without overflowing, but that
772 * leaves suitably precise fractions for multiply before divide.
773 *
774 * Divide before multiply with a fraction of 2199/512 results in a
775 * systematic undercompensation of 10PPM of th_adjustment. On a
776 * 5000PPM adjustment this is a 0.05PPM error. This is acceptable.
777 *
778 * We happily sacrifice the lowest of the 64 bits of our result
779 * to the goddess of code clarity.
780 *
781 */
782 scale = (u_int64_t)1 << 63;
783 scale += \
784 ((th->th_adjustment + th->th_counter->tc_freq_adj) / 1024) * 2199;
785 scale /= th->th_counter->tc_frequency;
786 th->th_scale = scale * 2;
787
788 /*
789 * Now that the struct timehands is again consistent, set the new
790 * generation number, making sure to not make it zero.
791 */
792 if (++ogen == 0)
793 ogen = 1;
794 membar_producer();
795 th->th_generation = ogen;
796
797 /* Go live with the new struct timehands. */
798 time_second = th->th_microtime.tv_sec;
799 time_uptime = th->th_offset.sec;
800 membar_producer();
801 timehands = th;
802
803 tc_update_timekeep();
804 }
805
806 /* Report or change the active timecounter hardware. */
807 int
808 sysctl_tc_hardware(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
809 {
810 char newname[32];
811 struct timecounter *newtc, *tc;
812 int error;
813
814 tc = timecounter;
815 strlcpy(newname, tc->tc_name, sizeof(newname));
816
817 error = sysctl_string(oldp, oldlenp, newp, newlen, newname, sizeof(newname));
818 if (error != 0 || strcmp(newname, tc->tc_name) == 0)
819 return (error);
820 SLIST_FOREACH(newtc, &tc_list, tc_next) {
821 if (strcmp(newname, newtc->tc_name) != 0)
822 continue;
823
824 /* Warm up new timecounter. */
825 (void)newtc->tc_get_timecount(newtc);
826 (void)newtc->tc_get_timecount(newtc);
827
828 rw_enter_write(&tc_lock);
829 timecounter = newtc;
830 rw_exit_write(&tc_lock);
831
832 return (0);
833 }
834 return (EINVAL);
835 }
836
837 /* Report or change the active timecounter hardware. */
838 int
839 sysctl_tc_choice(void *oldp, size_t *oldlenp, void *newp, size_t newlen)
840 {
841 char buf[32], *spc, *choices;
842 struct timecounter *tc;
843 int error, maxlen;
844
845 if (SLIST_EMPTY(&tc_list))
846 return (sysctl_rdstring(oldp, oldlenp, newp, ""));
847
848 spc = "";
849 maxlen = 0;
850 SLIST_FOREACH(tc, &tc_list, tc_next)
851 maxlen += sizeof(buf);
852 choices = malloc(maxlen, M_TEMP, M_WAITOK);
853 *choices = '\0';
854 SLIST_FOREACH(tc, &tc_list, tc_next) {
855 snprintf(buf, sizeof(buf), "%s%s(%d)",
856 spc, tc->tc_name, tc->tc_quality);
857 spc = " ";
858 strlcat(choices, buf, maxlen);
859 }
860 error = sysctl_rdstring(oldp, oldlenp, newp, choices);
861 free(choices, M_TEMP, maxlen);
862 return (error);
863 }
864
865 /*
866 * Timecounters need to be updated every so often to prevent the hardware
867 * counter from overflowing. Updating also recalculates the cached values
868 * used by the get*() family of functions, so their precision depends on
869 * the update frequency.
870 */
871 static int tc_tick;
872
873 void
874 tc_ticktock(void)
875 {
876 static int count;
877
878 if (++count < tc_tick)
879 return;
880 if (!mtx_enter_try(&windup_mtx))
881 return;
882 count = 0;
883 tc_windup(NULL, NULL, NULL);
884 mtx_leave(&windup_mtx);
885 }
886
887 void
888 inittimecounter(void)
889 {
890 #ifdef DEBUG
891 u_int p;
892 #endif
893
894 /*
895 * Set the initial timeout to
896 * max(1, <approx. number of hardclock ticks in a millisecond>).
897 * People should probably not use the sysctl to set the timeout
898 * to smaller than its initial value, since that value is the
899 * smallest reasonable one. If they want better timestamps they
900 * should use the non-"get"* functions.
901 */
902 if (hz > 1000)
903 tc_tick = (hz + 500) / 1000;
904 else
905 tc_tick = 1;
906 #ifdef DEBUG
907 p = (tc_tick * 1000000) / hz;
908 printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
909 #endif
910
911 /* warm up new timecounter (again) and get rolling. */
912 (void)timecounter->tc_get_timecount(timecounter);
913 (void)timecounter->tc_get_timecount(timecounter);
914 }
915
916 const struct sysctl_bounded_args tc_vars[] = {
917 { KERN_TIMECOUNTER_TICK, &tc_tick, SYSCTL_INT_READONLY },
918 { KERN_TIMECOUNTER_TIMESTEPWARNINGS, ×tepwarnings, 0, 1 },
919 };
920
921 /*
922 * Return timecounter-related information.
923 */
924 int
925 sysctl_tc(int *name, u_int namelen, void *oldp, size_t *oldlenp,
926 void *newp, size_t newlen)
927 {
928 if (namelen != 1)
929 return (ENOTDIR);
930
931 switch (name[0]) {
932 case KERN_TIMECOUNTER_HARDWARE:
933 return (sysctl_tc_hardware(oldp, oldlenp, newp, newlen));
934 case KERN_TIMECOUNTER_CHOICE:
935 return (sysctl_tc_choice(oldp, oldlenp, newp, newlen));
936 default:
937 return (sysctl_bounded_arr(tc_vars, nitems(tc_vars), name,
938 namelen, oldp, oldlenp, newp, newlen));
939 }
940 /* NOTREACHED */
941 }
942
943 /*
944 * Skew the timehands according to any adjtime(2) adjustment.
945 */
946 void
947 ntp_update_second(struct timehands *th)
948 {
949 int64_t adj;
950
951 MUTEX_ASSERT_LOCKED(&windup_mtx);
952
953 if (th->th_adjtimedelta > 0)
954 adj = MIN(5000, th->th_adjtimedelta);
955 else
956 adj = MAX(-5000, th->th_adjtimedelta);
957 th->th_adjtimedelta -= adj;
958 th->th_adjustment = (adj * 1000) << 32;
959 }
960
961 void
962 tc_adjfreq(int64_t *old, int64_t *new)
963 {
964 if (old != NULL) {
965 rw_assert_anylock(&tc_lock);
966 *old = timecounter->tc_freq_adj;
967 }
968 if (new != NULL) {
969 rw_assert_wrlock(&tc_lock);
970 mtx_enter(&windup_mtx);
971 timecounter->tc_freq_adj = *new;
972 tc_windup(NULL, NULL, NULL);
973 mtx_leave(&windup_mtx);
974 }
975 }
976
977 void
978 tc_adjtime(int64_t *old, int64_t *new)
979 {
980 struct timehands *th;
981 u_int gen;
982
983 if (old != NULL) {
984 do {
985 th = timehands;
986 gen = th->th_generation;
987 membar_consumer();
988 *old = th->th_adjtimedelta;
989 membar_consumer();
990 } while (gen == 0 || gen != th->th_generation);
991 }
992 if (new != NULL) {
993 rw_assert_wrlock(&tc_lock);
994 mtx_enter(&windup_mtx);
995 tc_windup(NULL, NULL, new);
996 mtx_leave(&windup_mtx);
997 }
998 }
Cache object: d679a0d666c66a90ccb44b60e9cc909e
|