1 /* $OpenBSD: kern_tc.c,v 1.40 2019/03/17 01:06:15 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/timeout.h> 29 #include <sys/sysctl.h> 30 #include <sys/syslog.h> 31 #include <sys/systm.h> 32 #include <sys/timetc.h> 33 #include <sys/malloc.h> 34 #include <dev/rndvar.h> 35 36 /* 37 * A large step happens on boot. This constant detects such steps. 38 * It is relatively small so that ntp_update_second gets called enough 39 * in the typical 'missed a couple of seconds' case, but doesn't loop 40 * forever when the time step is large. 41 */ 42 #define LARGE_STEP 200 43 44 u_int dummy_get_timecount(struct timecounter *); 45 46 void ntp_update_second(int64_t *); 47 int sysctl_tc_hardware(void *, size_t *, void *, size_t); 48 int sysctl_tc_choice(void *, size_t *, void *, size_t); 49 50 /* 51 * Implement a dummy timecounter which we can use until we get a real one 52 * in the air. This allows the console and other early stuff to use 53 * time services. 54 */ 55 56 u_int 57 dummy_get_timecount(struct timecounter *tc) 58 { 59 static u_int now; 60 61 return (++now); 62 } 63 64 static struct timecounter dummy_timecounter = { 65 dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000 66 }; 67 68 struct timehands { 69 /* These fields must be initialized by the driver. */ 70 struct timecounter *th_counter; 71 int64_t th_adjustment; 72 u_int64_t th_scale; 73 u_int th_offset_count; 74 struct bintime th_boottime; 75 struct bintime th_offset; 76 struct timeval th_microtime; 77 struct timespec th_nanotime; 78 /* Fields not to be copied in tc_windup start with th_generation. */ 79 volatile u_int th_generation; 80 struct timehands *th_next; 81 }; 82 83 static struct timehands th0; 84 static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th0}; 85 static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th9}; 86 static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th8}; 87 static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th7}; 88 static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th6}; 89 static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th5}; 90 static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th4}; 91 static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th3}; 92 static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, &th2}; 93 static struct timehands th0 = { 94 &dummy_timecounter, 95 0, 96 (uint64_t)-1 / 1000000, 97 0, 98 {0, 0}, 99 {1, 0}, 100 {0, 0}, 101 {0, 0}, 102 1, 103 &th1 104 }; 105 106 /* 107 * Protects writes to anything accessed during tc_windup(). 108 * tc_windup() must be called before leaving this mutex. 109 */ 110 struct mutex timecounter_mtx = MUTEX_INITIALIZER(IPL_CLOCK); 111 112 static struct timehands *volatile timehands = &th0; 113 struct timecounter *timecounter = &dummy_timecounter; 114 static struct timecounter *timecounters = &dummy_timecounter; 115 116 volatile time_t time_second = 1; 117 volatile time_t time_uptime = 0; 118 119 int64_t adjtimedelta; /* unapplied time correction (microseconds) */ 120 121 struct bintime naptime; 122 static int timestepwarnings; 123 124 void tc_windup(struct bintime *, struct bintime *); 125 126 /* 127 * Return the difference between the timehands' counter value now and what 128 * was when we copied it to the timehands' offset_count. 129 */ 130 static __inline u_int 131 tc_delta(struct timehands *th) 132 { 133 struct timecounter *tc; 134 135 tc = th->th_counter; 136 return ((tc->tc_get_timecount(tc) - th->th_offset_count) & 137 tc->tc_counter_mask); 138 } 139 140 /* 141 * Functions for reading the time. We have to loop until we are sure that 142 * the timehands that we operated on was not updated under our feet. See 143 * the comment in <sys/time.h> for a description of these functions. 144 */ 145 146 void 147 binboottime(struct bintime *bt) 148 { 149 struct timehands *th; 150 u_int gen; 151 152 do { 153 th = timehands; 154 gen = th->th_generation; 155 membar_consumer(); 156 *bt = th->th_boottime; 157 membar_consumer(); 158 } while (gen == 0 || gen != th->th_generation); 159 } 160 161 void 162 microboottime(struct timeval *tvp) 163 { 164 struct bintime bt; 165 166 binboottime(&bt); 167 bintime2timeval(&bt, tvp); 168 } 169 170 void 171 binuptime(struct bintime *bt) 172 { 173 struct timehands *th; 174 u_int gen; 175 176 do { 177 th = timehands; 178 gen = th->th_generation; 179 membar_consumer(); 180 *bt = th->th_offset; 181 bintime_addx(bt, th->th_scale * tc_delta(th)); 182 membar_consumer(); 183 } while (gen == 0 || gen != th->th_generation); 184 } 185 186 void 187 nanouptime(struct timespec *tsp) 188 { 189 struct bintime bt; 190 191 binuptime(&bt); 192 bintime2timespec(&bt, tsp); 193 } 194 195 void 196 microuptime(struct timeval *tvp) 197 { 198 struct bintime bt; 199 200 binuptime(&bt); 201 bintime2timeval(&bt, tvp); 202 } 203 204 void 205 bintime(struct bintime *bt) 206 { 207 struct timehands *th; 208 u_int gen; 209 210 do { 211 th = timehands; 212 gen = th->th_generation; 213 membar_consumer(); 214 *bt = th->th_offset; 215 bintime_addx(bt, th->th_scale * tc_delta(th)); 216 bintime_add(bt, &th->th_boottime); 217 membar_consumer(); 218 } while (gen == 0 || gen != th->th_generation); 219 } 220 221 void 222 nanotime(struct timespec *tsp) 223 { 224 struct bintime bt; 225 226 bintime(&bt); 227 bintime2timespec(&bt, tsp); 228 } 229 230 void 231 microtime(struct timeval *tvp) 232 { 233 struct bintime bt; 234 235 bintime(&bt); 236 bintime2timeval(&bt, tvp); 237 } 238 239 void 240 getnanouptime(struct timespec *tsp) 241 { 242 struct timehands *th; 243 u_int gen; 244 245 do { 246 th = timehands; 247 gen = th->th_generation; 248 membar_consumer(); 249 bintime2timespec(&th->th_offset, tsp); 250 membar_consumer(); 251 } while (gen == 0 || gen != th->th_generation); 252 } 253 254 void 255 getmicrouptime(struct timeval *tvp) 256 { 257 struct timehands *th; 258 u_int gen; 259 260 do { 261 th = timehands; 262 gen = th->th_generation; 263 membar_consumer(); 264 bintime2timeval(&th->th_offset, tvp); 265 membar_consumer(); 266 } while (gen == 0 || gen != th->th_generation); 267 } 268 269 void 270 getnanotime(struct timespec *tsp) 271 { 272 struct timehands *th; 273 u_int gen; 274 275 do { 276 th = timehands; 277 gen = th->th_generation; 278 membar_consumer(); 279 *tsp = th->th_nanotime; 280 membar_consumer(); 281 } while (gen == 0 || gen != th->th_generation); 282 } 283 284 void 285 getmicrotime(struct timeval *tvp) 286 { 287 struct timehands *th; 288 u_int gen; 289 290 do { 291 th = timehands; 292 gen = th->th_generation; 293 membar_consumer(); 294 *tvp = th->th_microtime; 295 membar_consumer(); 296 } while (gen == 0 || gen != th->th_generation); 297 } 298 299 /* 300 * Initialize a new timecounter and possibly use it. 301 */ 302 void 303 tc_init(struct timecounter *tc) 304 { 305 u_int u; 306 307 u = tc->tc_frequency / tc->tc_counter_mask; 308 /* XXX: We need some margin here, 10% is a guess */ 309 u *= 11; 310 u /= 10; 311 if (tc->tc_quality >= 0) { 312 if (u > hz) { 313 tc->tc_quality = -2000; 314 printf("Timecounter \"%s\" frequency %lu Hz", 315 tc->tc_name, (unsigned long)tc->tc_frequency); 316 printf(" -- Insufficient hz, needs at least %u\n", u); 317 } 318 } 319 320 tc->tc_next = timecounters; 321 timecounters = tc; 322 /* 323 * Never automatically use a timecounter with negative quality. 324 * Even though we run on the dummy counter, switching here may be 325 * worse since this timecounter may not be monotonic. 326 */ 327 if (tc->tc_quality < 0) 328 return; 329 if (tc->tc_quality < timecounter->tc_quality) 330 return; 331 if (tc->tc_quality == timecounter->tc_quality && 332 tc->tc_frequency < timecounter->tc_frequency) 333 return; 334 (void)tc->tc_get_timecount(tc); 335 enqueue_randomness(tc->tc_get_timecount(tc)); 336 337 timecounter = tc; 338 } 339 340 /* Report the frequency of the current timecounter. */ 341 u_int64_t 342 tc_getfrequency(void) 343 { 344 345 return (timehands->th_counter->tc_frequency); 346 } 347 348 /* 349 * Step our concept of UTC, aka the realtime clock. 350 * This is done by modifying our estimate of when we booted. 351 */ 352 void 353 tc_setrealtimeclock(const struct timespec *ts) 354 { 355 struct timespec ts2; 356 struct bintime bt, bt2; 357 358 mtx_enter(&timecounter_mtx); 359 binuptime(&bt2); 360 timespec2bintime(ts, &bt); 361 bintime_sub(&bt, &bt2); 362 bintime_add(&bt2, &timehands->th_boottime); 363 364 /* XXX fiddle all the little crinkly bits around the fiords... */ 365 tc_windup(&bt, NULL); 366 mtx_leave(&timecounter_mtx); 367 368 enqueue_randomness(ts->tv_sec); 369 370 if (timestepwarnings) { 371 bintime2timespec(&bt2, &ts2); 372 log(LOG_INFO, "Time stepped from %lld.%09ld to %lld.%09ld\n", 373 (long long)ts2.tv_sec, ts2.tv_nsec, 374 (long long)ts->tv_sec, ts->tv_nsec); 375 } 376 } 377 378 /* 379 * Step the monotonic and realtime clocks, triggering any timeouts that 380 * should have occurred across the interval. 381 */ 382 void 383 tc_setclock(const struct timespec *ts) 384 { 385 struct bintime bt, bt2; 386 struct timespec earlier; 387 static int first = 1; 388 #ifndef SMALL_KERNEL 389 long long adj_ticks; 390 #endif 391 392 /* 393 * When we're called for the first time, during boot when 394 * the root partition is mounted, we need to set boottime. 395 */ 396 if (first) { 397 tc_setrealtimeclock(ts); 398 first = 0; 399 return; 400 } 401 402 enqueue_randomness(ts->tv_sec); 403 404 mtx_enter(&timecounter_mtx); 405 timespec2bintime(ts, &bt); 406 bintime_sub(&bt, &timehands->th_boottime); 407 408 /* 409 * Don't rewind the offset. 410 */ 411 if (bt.sec < timehands->th_offset.sec || 412 (bt.sec == timehands->th_offset.sec && 413 bt.frac < timehands->th_offset.frac)) { 414 mtx_leave(&timecounter_mtx); 415 bintime2timespec(&bt, &earlier); 416 printf("%s: cannot rewind uptime to %lld.%09ld\n", 417 __func__, (long long)earlier.tv_sec, earlier.tv_nsec); 418 return; 419 } 420 421 bt2 = timehands->th_offset; 422 423 /* XXX fiddle all the little crinkly bits around the fiords... */ 424 tc_windup(NULL, &bt); 425 mtx_leave(&timecounter_mtx); 426 427 #ifndef SMALL_KERNEL 428 /* convert the bintime to ticks */ 429 bintime_sub(&bt, &bt2); 430 bintime_add(&naptime, &bt); 431 adj_ticks = (uint64_t)hz * bt.sec + 432 (((uint64_t)1000000 * (uint32_t)(bt.frac >> 32)) >> 32) / tick; 433 if (adj_ticks > 0) { 434 if (adj_ticks > INT_MAX) 435 adj_ticks = INT_MAX; 436 timeout_adjust_ticks(adj_ticks); 437 } 438 #endif 439 } 440 441 /* 442 * Initialize the next struct timehands in the ring and make 443 * it the active timehands. Along the way we might switch to a different 444 * timecounter and/or do seconds processing in NTP. Slightly magic. 445 */ 446 void 447 tc_windup(struct bintime *new_boottime, struct bintime *new_offset) 448 { 449 struct bintime bt; 450 struct timecounter *active_tc; 451 struct timehands *th, *tho; 452 u_int64_t scale; 453 u_int delta, ncount, ogen; 454 int i; 455 456 MUTEX_ASSERT_LOCKED(&timecounter_mtx); 457 458 active_tc = timecounter; 459 460 /* 461 * Make the next timehands a copy of the current one, but do not 462 * overwrite the generation or next pointer. While we update 463 * the contents, the generation must be zero. 464 */ 465 tho = timehands; 466 th = tho->th_next; 467 ogen = th->th_generation; 468 th->th_generation = 0; 469 membar_producer(); 470 memcpy(th, tho, offsetof(struct timehands, th_generation)); 471 472 /* 473 * If changing the boot offset, do so before updating the 474 * offset fields. 475 */ 476 if (new_offset != NULL) 477 th->th_offset = *new_offset; 478 479 /* 480 * Capture a timecounter delta on the current timecounter and if 481 * changing timecounters, a counter value from the new timecounter. 482 * Update the offset fields accordingly. 483 */ 484 delta = tc_delta(th); 485 if (th->th_counter != active_tc) 486 ncount = active_tc->tc_get_timecount(active_tc); 487 else 488 ncount = 0; 489 th->th_offset_count += delta; 490 th->th_offset_count &= th->th_counter->tc_counter_mask; 491 bintime_addx(&th->th_offset, th->th_scale * delta); 492 493 #ifdef notyet 494 /* 495 * Hardware latching timecounters may not generate interrupts on 496 * PPS events, so instead we poll them. There is a finite risk that 497 * the hardware might capture a count which is later than the one we 498 * got above, and therefore possibly in the next NTP second which might 499 * have a different rate than the current NTP second. It doesn't 500 * matter in practice. 501 */ 502 if (tho->th_counter->tc_poll_pps) 503 tho->th_counter->tc_poll_pps(tho->th_counter); 504 #endif 505 506 /* 507 * If changing the boot time, do so before NTP processing. 508 */ 509 if (new_boottime != NULL) { 510 /* 511 * Adjtime in progress is meaningless or harmful after 512 * setting the clock. Cancel adjtime and then set new time. 513 */ 514 adjtimedelta = 0; 515 th->th_boottime = *new_boottime; 516 } 517 518 /* 519 * Deal with NTP second processing. The for loop normally 520 * iterates at most once, but in extreme situations it might 521 * keep NTP sane if timeouts are not run for several seconds. 522 * At boot, the time step can be large when the TOD hardware 523 * has been read, so on really large steps, we call 524 * ntp_update_second only twice. We need to call it twice in 525 * case we missed a leap second. 526 */ 527 bt = th->th_offset; 528 bintime_add(&bt, &th->th_boottime); 529 i = bt.sec - tho->th_microtime.tv_sec; 530 if (i > LARGE_STEP) 531 i = 2; 532 for (; i > 0; i--) 533 ntp_update_second(&th->th_adjustment); 534 535 /* Update the UTC timestamps used by the get*() functions. */ 536 /* XXX shouldn't do this here. Should force non-`get' versions. */ 537 bintime2timeval(&bt, &th->th_microtime); 538 bintime2timespec(&bt, &th->th_nanotime); 539 540 /* Now is a good time to change timecounters. */ 541 if (th->th_counter != active_tc) { 542 th->th_counter = active_tc; 543 th->th_offset_count = ncount; 544 } 545 546 /*- 547 * Recalculate the scaling factor. We want the number of 1/2^64 548 * fractions of a second per period of the hardware counter, taking 549 * into account the th_adjustment factor which the NTP PLL/adjtime(2) 550 * processing provides us with. 551 * 552 * The th_adjustment is nanoseconds per second with 32 bit binary 553 * fraction and we want 64 bit binary fraction of second: 554 * 555 * x = a * 2^32 / 10^9 = a * 4.294967296 556 * 557 * The range of th_adjustment is +/- 5000PPM so inside a 64bit int 558 * we can only multiply by about 850 without overflowing, but that 559 * leaves suitably precise fractions for multiply before divide. 560 * 561 * Divide before multiply with a fraction of 2199/512 results in a 562 * systematic undercompensation of 10PPM of th_adjustment. On a 563 * 5000PPM adjustment this is a 0.05PPM error. This is acceptable. 564 * 565 * We happily sacrifice the lowest of the 64 bits of our result 566 * to the goddess of code clarity. 567 * 568 */ 569 scale = (u_int64_t)1 << 63; 570 scale += (th->th_adjustment / 1024) * 2199; 571 scale /= th->th_counter->tc_frequency; 572 th->th_scale = scale * 2; 573 574 /* 575 * Now that the struct timehands is again consistent, set the new 576 * generation number, making sure to not make it zero. 577 */ 578 if (++ogen == 0) 579 ogen = 1; 580 membar_producer(); 581 th->th_generation = ogen; 582 583 /* Go live with the new struct timehands. */ 584 time_second = th->th_microtime.tv_sec; 585 time_uptime = th->th_offset.sec; 586 membar_producer(); 587 timehands = th; 588 } 589 590 /* Report or change the active timecounter hardware. */ 591 int 592 sysctl_tc_hardware(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 593 { 594 char newname[32]; 595 struct timecounter *newtc, *tc; 596 int error; 597 598 tc = timecounter; 599 strlcpy(newname, tc->tc_name, sizeof(newname)); 600 601 error = sysctl_string(oldp, oldlenp, newp, newlen, newname, sizeof(newname)); 602 if (error != 0 || strcmp(newname, tc->tc_name) == 0) 603 return (error); 604 for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) { 605 if (strcmp(newname, newtc->tc_name) != 0) 606 continue; 607 608 /* Warm up new timecounter. */ 609 (void)newtc->tc_get_timecount(newtc); 610 (void)newtc->tc_get_timecount(newtc); 611 612 timecounter = newtc; 613 return (0); 614 } 615 return (EINVAL); 616 } 617 618 /* Report or change the active timecounter hardware. */ 619 int 620 sysctl_tc_choice(void *oldp, size_t *oldlenp, void *newp, size_t newlen) 621 { 622 char buf[32], *spc, *choices; 623 struct timecounter *tc; 624 int error, maxlen; 625 626 spc = ""; 627 maxlen = 0; 628 for (tc = timecounters; tc != NULL; tc = tc->tc_next) 629 maxlen += sizeof(buf); 630 choices = malloc(maxlen, M_TEMP, M_WAITOK); 631 *choices = '\0'; 632 for (tc = timecounters; tc != NULL; tc = tc->tc_next) { 633 snprintf(buf, sizeof(buf), "%s%s(%d)", 634 spc, tc->tc_name, tc->tc_quality); 635 spc = " "; 636 strlcat(choices, buf, maxlen); 637 } 638 error = sysctl_rdstring(oldp, oldlenp, newp, choices); 639 free(choices, M_TEMP, maxlen); 640 return (error); 641 } 642 643 /* 644 * Timecounters need to be updated every so often to prevent the hardware 645 * counter from overflowing. Updating also recalculates the cached values 646 * used by the get*() family of functions, so their precision depends on 647 * the update frequency. 648 */ 649 static int tc_tick; 650 651 void 652 tc_ticktock(void) 653 { 654 static int count; 655 656 if (++count < tc_tick) 657 return; 658 if (!mtx_enter_try(&timecounter_mtx)) 659 return; 660 count = 0; 661 tc_windup(NULL, NULL); 662 mtx_leave(&timecounter_mtx); 663 } 664 665 void 666 inittimecounter(void) 667 { 668 #ifdef DEBUG 669 u_int p; 670 #endif 671 672 /* 673 * Set the initial timeout to 674 * max(1, <approx. number of hardclock ticks in a millisecond>). 675 * People should probably not use the sysctl to set the timeout 676 * to smaller than its initial value, since that value is the 677 * smallest reasonable one. If they want better timestamps they 678 * should use the non-"get"* functions. 679 */ 680 if (hz > 1000) 681 tc_tick = (hz + 500) / 1000; 682 else 683 tc_tick = 1; 684 #ifdef DEBUG 685 p = (tc_tick * 1000000) / hz; 686 printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); 687 #endif 688 689 /* warm up new timecounter (again) and get rolling. */ 690 (void)timecounter->tc_get_timecount(timecounter); 691 (void)timecounter->tc_get_timecount(timecounter); 692 } 693 694 /* 695 * Return timecounter-related information. 696 */ 697 int 698 sysctl_tc(int *name, u_int namelen, void *oldp, size_t *oldlenp, 699 void *newp, size_t newlen) 700 { 701 if (namelen != 1) 702 return (ENOTDIR); 703 704 switch (name[0]) { 705 case KERN_TIMECOUNTER_TICK: 706 return (sysctl_rdint(oldp, oldlenp, newp, tc_tick)); 707 case KERN_TIMECOUNTER_TIMESTEPWARNINGS: 708 return (sysctl_int(oldp, oldlenp, newp, newlen, 709 ×tepwarnings)); 710 case KERN_TIMECOUNTER_HARDWARE: 711 return (sysctl_tc_hardware(oldp, oldlenp, newp, newlen)); 712 case KERN_TIMECOUNTER_CHOICE: 713 return (sysctl_tc_choice(oldp, oldlenp, newp, newlen)); 714 default: 715 return (EOPNOTSUPP); 716 } 717 /* NOTREACHED */ 718 } 719 720 void 721 ntp_update_second(int64_t *adjust) 722 { 723 int64_t adj; 724 725 /* Skew time according to any adjtime(2) adjustments. */ 726 if (adjtimedelta > 0) 727 adj = MIN(5000, adjtimedelta); 728 else 729 adj = MAX(-5000, adjtimedelta); 730 adjtimedelta -= adj; 731 *adjust = (adj * 1000) << 32; 732 *adjust += timecounter->tc_freq_adj; 733 } 734 735 int 736 tc_adjfreq(int64_t *old, int64_t *new) 737 { 738 if (old != NULL) { 739 *old = timecounter->tc_freq_adj; 740 } 741 if (new != NULL) { 742 timecounter->tc_freq_adj = *new; 743 } 744 return 0; 745 } 746 747 void 748 tc_adjtime(int64_t *old, int64_t *new) 749 { 750 if (old != NULL) 751 *old = adjtimedelta; 752 if (new != NULL) 753 adjtimedelta = *new; 754 } 755