The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_tc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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, &timestepwarnings, 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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.