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_clock.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 /*-
    2  * Copyright (c) 1997, 1998 Poul-Henning Kamp <phk@FreeBSD.org>
    3  * Copyright (c) 1982, 1986, 1991, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  * (c) UNIX System Laboratories, Inc.
    6  * All or some portions of this file are derived from material licensed
    7  * to the University of California by American Telephone and Telegraph
    8  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
    9  * the permission of UNIX System Laboratories, Inc.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the University of
   22  *      California, Berkeley and its contributors.
   23  * 4. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      @(#)kern_clock.c        8.5 (Berkeley) 1/21/94
   40  * $FreeBSD$
   41  */
   42 
   43 #include "opt_ntp.h"
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/dkstat.h>
   48 #include <sys/callout.h>
   49 #include <sys/kernel.h>
   50 #include <sys/proc.h>
   51 #include <sys/malloc.h>
   52 #include <sys/resourcevar.h>
   53 #include <sys/signalvar.h>
   54 #include <sys/timex.h>
   55 #include <sys/timepps.h>
   56 #include <vm/vm.h>
   57 #include <sys/lock.h>
   58 #include <vm/pmap.h>
   59 #include <vm/vm_map.h>
   60 #include <sys/sysctl.h>
   61 
   62 #include <machine/cpu.h>
   63 #include <machine/limits.h>
   64 
   65 #ifdef GPROF
   66 #include <sys/gmon.h>
   67 #endif
   68 
   69 #if defined(SMP) && defined(BETTER_CLOCK)
   70 #include <machine/smp.h>
   71 #endif
   72 
   73 /*
   74  * Number of timecounters used to implement stable storage
   75  */
   76 #ifndef NTIMECOUNTER
   77 #define NTIMECOUNTER    5
   78 #endif
   79 
   80 static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter", 
   81         "Timecounter stable storage");
   82 
   83 static void initclocks __P((void *dummy));
   84 SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
   85 
   86 static void tco_forward __P((int force));
   87 static void tco_setscales __P((struct timecounter *tc));
   88 static __inline unsigned tco_delta __P((struct timecounter *tc));
   89 
   90 /* Some of these don't belong here, but it's easiest to concentrate them. */
   91 #if defined(SMP) && defined(BETTER_CLOCK)
   92 long cp_time[CPUSTATES];
   93 #else
   94 static long cp_time[CPUSTATES];
   95 #endif
   96 
   97 long tk_cancc;
   98 long tk_nin;
   99 long tk_nout;
  100 long tk_rawcc;
  101 
  102 time_t time_second;
  103 
  104 /*
  105  * Which update policy to use.
  106  *   0 - every tick, bad hardware may fail with "calcru negative..."
  107  *   1 - more resistent to the above hardware, but less efficient.
  108  */
  109 static int tco_method;
  110 
  111 /*
  112  * Implement a dummy timecounter which we can use until we get a real one
  113  * in the air.  This allows the console and other early stuff to use
  114  * timeservices.
  115  */
  116 
  117 static unsigned 
  118 dummy_get_timecount(struct timecounter *tc)
  119 {
  120         static unsigned now;
  121         return (++now);
  122 }
  123 
  124 static struct timecounter dummy_timecounter = {
  125         dummy_get_timecount,
  126         0,
  127         ~0u,
  128         1000000,
  129         "dummy"
  130 };
  131 
  132 struct timecounter *timecounter = &dummy_timecounter;
  133 
  134 /*
  135  * Clock handling routines.
  136  *
  137  * This code is written to operate with two timers that run independently of
  138  * each other.
  139  *
  140  * The main timer, running hz times per second, is used to trigger interval
  141  * timers, timeouts and rescheduling as needed.
  142  *
  143  * The second timer handles kernel and user profiling,
  144  * and does resource use estimation.  If the second timer is programmable,
  145  * it is randomized to avoid aliasing between the two clocks.  For example,
  146  * the randomization prevents an adversary from always giving up the cpu
  147  * just before its quantum expires.  Otherwise, it would never accumulate
  148  * cpu ticks.  The mean frequency of the second timer is stathz.
  149  *
  150  * If no second timer exists, stathz will be zero; in this case we drive
  151  * profiling and statistics off the main clock.  This WILL NOT be accurate;
  152  * do not do it unless absolutely necessary.
  153  *
  154  * The statistics clock may (or may not) be run at a higher rate while
  155  * profiling.  This profile clock runs at profhz.  We require that profhz
  156  * be an integral multiple of stathz.
  157  *
  158  * If the statistics clock is running fast, it must be divided by the ratio
  159  * profhz/stathz for statistics.  (For profiling, every tick counts.)
  160  *
  161  * Time-of-day is maintained using a "timecounter", which may or may
  162  * not be related to the hardware generating the above mentioned
  163  * interrupts.
  164  */
  165 
  166 int     stathz;
  167 int     profhz;
  168 static int profprocs;
  169 int     ticks;
  170 static int psdiv, pscnt;                /* prof => stat divider */
  171 int     psratio;                        /* ratio: prof / stat */
  172 
  173 /*
  174  * Initialize clock frequencies and start both clocks running.
  175  */
  176 /* ARGSUSED*/
  177 static void
  178 initclocks(dummy)
  179         void *dummy;
  180 {
  181         register int i;
  182 
  183         /*
  184          * Set divisors to 1 (normal case) and let the machine-specific
  185          * code do its bit.
  186          */
  187         psdiv = pscnt = 1;
  188         cpu_initclocks();
  189 
  190         /*
  191          * Compute profhz/stathz, and fix profhz if needed.
  192          */
  193         i = stathz ? stathz : hz;
  194         if (profhz == 0)
  195                 profhz = i;
  196         psratio = profhz / i;
  197 }
  198 
  199 /*
  200  * The real-time timer, interrupting hz times per second.
  201  */
  202 void
  203 hardclock(frame)
  204         register struct clockframe *frame;
  205 {
  206         register struct proc *p;
  207 
  208         p = curproc;
  209         if (p) {
  210                 register struct pstats *pstats;
  211 
  212                 /*
  213                  * Run current process's virtual and profile time, as needed.
  214                  */
  215                 pstats = p->p_stats;
  216                 if (CLKF_USERMODE(frame) &&
  217                     timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
  218                     itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0)
  219                         psignal(p, SIGVTALRM);
  220                 if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) &&
  221                     itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0)
  222                         psignal(p, SIGPROF);
  223         }
  224 
  225 #if defined(SMP) && defined(BETTER_CLOCK)
  226         forward_hardclock(pscnt);
  227 #endif
  228 
  229         /*
  230          * If no separate statistics clock is available, run it from here.
  231          */
  232         if (stathz == 0)
  233                 statclock(frame);
  234 
  235         tco_forward(0);
  236         ticks++;
  237 
  238         /*
  239          * Process callouts at a very low cpu priority, so we don't keep the
  240          * relatively high clock interrupt priority any longer than necessary.
  241          */
  242         if (TAILQ_FIRST(&callwheel[ticks & callwheelmask]) != NULL) {
  243                 if (CLKF_BASEPRI(frame)) {
  244                         /*
  245                          * Save the overhead of a software interrupt;
  246                          * it will happen as soon as we return, so do it now.
  247                          */
  248                         (void)splsoftclock();
  249                         softclock();
  250                 } else
  251                         setsoftclock();
  252         } else if (softticks + 1 == ticks)
  253                 ++softticks;
  254 }
  255 
  256 /*
  257  * Compute number of ticks in the specified amount of time.
  258  */
  259 int
  260 tvtohz(tv)
  261         struct timeval *tv;
  262 {
  263         register unsigned long ticks;
  264         register long sec, usec;
  265 
  266         /*
  267          * If the number of usecs in the whole seconds part of the time
  268          * difference fits in a long, then the total number of usecs will
  269          * fit in an unsigned long.  Compute the total and convert it to
  270          * ticks, rounding up and adding 1 to allow for the current tick
  271          * to expire.  Rounding also depends on unsigned long arithmetic
  272          * to avoid overflow.
  273          *
  274          * Otherwise, if the number of ticks in the whole seconds part of
  275          * the time difference fits in a long, then convert the parts to
  276          * ticks separately and add, using similar rounding methods and
  277          * overflow avoidance.  This method would work in the previous
  278          * case but it is slightly slower and assumes that hz is integral.
  279          *
  280          * Otherwise, round the time difference down to the maximum
  281          * representable value.
  282          *
  283          * If ints have 32 bits, then the maximum value for any timeout in
  284          * 10ms ticks is 248 days.
  285          */
  286         sec = tv->tv_sec;
  287         usec = tv->tv_usec;
  288         if (usec < 0) {
  289                 sec--;
  290                 usec += 1000000;
  291         }
  292         if (sec < 0) {
  293 #ifdef DIAGNOSTIC
  294                 if (usec > 0) {
  295                         sec++;
  296                         usec -= 1000000;
  297                 }
  298                 printf("tvotohz: negative time difference %ld sec %ld usec\n",
  299                        sec, usec);
  300 #endif
  301                 ticks = 1;
  302         } else if (sec <= LONG_MAX / 1000000)
  303                 ticks = (sec * 1000000 + (unsigned long)usec + (tick - 1))
  304                         / tick + 1;
  305         else if (sec <= LONG_MAX / hz)
  306                 ticks = sec * hz
  307                         + ((unsigned long)usec + (tick - 1)) / tick + 1;
  308         else
  309                 ticks = LONG_MAX;
  310         if (ticks > INT_MAX)
  311                 ticks = INT_MAX;
  312         return ((int)ticks);
  313 }
  314 
  315 /*
  316  * Start profiling on a process.
  317  *
  318  * Kernel profiling passes proc0 which never exits and hence
  319  * keeps the profile clock running constantly.
  320  */
  321 void
  322 startprofclock(p)
  323         register struct proc *p;
  324 {
  325         int s;
  326 
  327         if ((p->p_flag & P_PROFIL) == 0) {
  328                 p->p_flag |= P_PROFIL;
  329                 if (++profprocs == 1 && stathz != 0) {
  330                         s = splstatclock();
  331                         psdiv = pscnt = psratio;
  332                         setstatclockrate(profhz);
  333                         splx(s);
  334                 }
  335         }
  336 }
  337 
  338 /*
  339  * Stop profiling on a process.
  340  */
  341 void
  342 stopprofclock(p)
  343         register struct proc *p;
  344 {
  345         int s;
  346 
  347         if (p->p_flag & P_PROFIL) {
  348                 p->p_flag &= ~P_PROFIL;
  349                 if (--profprocs == 0 && stathz != 0) {
  350                         s = splstatclock();
  351                         psdiv = pscnt = 1;
  352                         setstatclockrate(stathz);
  353                         splx(s);
  354                 }
  355         }
  356 }
  357 
  358 /*
  359  * Statistics clock.  Grab profile sample, and if divider reaches 0,
  360  * do process and kernel statistics.
  361  */
  362 void
  363 statclock(frame)
  364         register struct clockframe *frame;
  365 {
  366 #ifdef GPROF
  367         register struct gmonparam *g;
  368         int i;
  369 #endif
  370         register struct proc *p;
  371         struct pstats *pstats;
  372         long rss;
  373         struct rusage *ru;
  374         struct vmspace *vm;
  375 
  376         if (curproc != NULL && CLKF_USERMODE(frame)) {
  377                 p = curproc;
  378                 if (p->p_flag & P_PROFIL)
  379                         addupc_intr(p, CLKF_PC(frame), 1);
  380 #if defined(SMP) && defined(BETTER_CLOCK)
  381                 if (stathz != 0)
  382                         forward_statclock(pscnt);
  383 #endif
  384                 if (--pscnt > 0)
  385                         return;
  386                 /*
  387                  * Came from user mode; CPU was in user state.
  388                  * If this process is being profiled record the tick.
  389                  */
  390                 p->p_uticks++;
  391                 if (p->p_nice > NZERO)
  392                         cp_time[CP_NICE]++;
  393                 else
  394                         cp_time[CP_USER]++;
  395         } else {
  396 #ifdef GPROF
  397                 /*
  398                  * Kernel statistics are just like addupc_intr, only easier.
  399                  */
  400                 g = &_gmonparam;
  401                 if (g->state == GMON_PROF_ON) {
  402                         i = CLKF_PC(frame) - g->lowpc;
  403                         if (i < g->textsize) {
  404                                 i /= HISTFRACTION * sizeof(*g->kcount);
  405                                 g->kcount[i]++;
  406                         }
  407                 }
  408 #endif
  409 #if defined(SMP) && defined(BETTER_CLOCK)
  410                 if (stathz != 0)
  411                         forward_statclock(pscnt);
  412 #endif
  413                 if (--pscnt > 0)
  414                         return;
  415                 /*
  416                  * Came from kernel mode, so we were:
  417                  * - handling an interrupt,
  418                  * - doing syscall or trap work on behalf of the current
  419                  *   user process, or
  420                  * - spinning in the idle loop.
  421                  * Whichever it is, charge the time as appropriate.
  422                  * Note that we charge interrupts to the current process,
  423                  * regardless of whether they are ``for'' that process,
  424                  * so that we know how much of its real time was spent
  425                  * in ``non-process'' (i.e., interrupt) work.
  426                  */
  427                 p = curproc;
  428                 if (CLKF_INTR(frame)) {
  429                         if (p != NULL)
  430                                 p->p_iticks++;
  431                         cp_time[CP_INTR]++;
  432                 } else if (p != NULL) {
  433                         p->p_sticks++;
  434                         cp_time[CP_SYS]++;
  435                 } else
  436                         cp_time[CP_IDLE]++;
  437         }
  438         pscnt = psdiv;
  439 
  440         /*
  441          * We maintain statistics shown by user-level statistics
  442          * programs:  the amount of time in each cpu state.
  443          */
  444 
  445         /*
  446          * We adjust the priority of the current process.  The priority of
  447          * a process gets worse as it accumulates CPU time.  The cpu usage
  448          * estimator (p_estcpu) is increased here.  The formula for computing
  449          * priorities (in kern_synch.c) will compute a different value each
  450          * time p_estcpu increases by 4.  The cpu usage estimator ramps up
  451          * quite quickly when the process is running (linearly), and decays
  452          * away exponentially, at a rate which is proportionally slower when
  453          * the system is busy.  The basic principal is that the system will
  454          * 90% forget that the process used a lot of CPU time in 5 * loadav
  455          * seconds.  This causes the system to favor processes which haven't
  456          * run much recently, and to round-robin among other processes.
  457          */
  458         if (p != NULL) {
  459                 p->p_cpticks++;
  460                 if (++p->p_estcpu == 0)
  461                         p->p_estcpu--;
  462                 if ((p->p_estcpu & 3) == 0) {
  463                         resetpriority(p);
  464                         if (p->p_priority >= PUSER)
  465                                 p->p_priority = p->p_usrpri;
  466                 }
  467 
  468                 /* Update resource usage integrals and maximums. */
  469                 if ((pstats = p->p_stats) != NULL &&
  470                     (ru = &pstats->p_ru) != NULL &&
  471                     (vm = p->p_vmspace) != NULL) {
  472                         ru->ru_ixrss += vm->vm_tsize * PAGE_SIZE / 1024;
  473                         ru->ru_idrss += vm->vm_dsize * PAGE_SIZE / 1024;
  474                         ru->ru_isrss += vm->vm_ssize * PAGE_SIZE / 1024;
  475                         rss = vm->vm_pmap.pm_stats.resident_count *
  476                               PAGE_SIZE / 1024;
  477                         if (ru->ru_maxrss < rss)
  478                                 ru->ru_maxrss = rss;
  479                 }
  480         }
  481 }
  482 
  483 /*
  484  * Return information about system clocks.
  485  */
  486 static int
  487 sysctl_kern_clockrate SYSCTL_HANDLER_ARGS
  488 {
  489         struct clockinfo clkinfo;
  490         /*
  491          * Construct clockinfo structure.
  492          */
  493         clkinfo.hz = hz;
  494         clkinfo.tick = tick;
  495         clkinfo.tickadj = tickadj;
  496         clkinfo.profhz = profhz;
  497         clkinfo.stathz = stathz ? stathz : hz;
  498         return (sysctl_handle_opaque(oidp, &clkinfo, sizeof clkinfo, req));
  499 }
  500 
  501 SYSCTL_PROC(_kern, KERN_CLOCKRATE, clockrate, CTLTYPE_STRUCT|CTLFLAG_RD,
  502         0, 0, sysctl_kern_clockrate, "S,clockinfo","");
  503 
  504 static __inline unsigned
  505 tco_delta(struct timecounter *tc)
  506 {
  507 
  508         return ((tc->tc_get_timecount(tc) - tc->tc_offset_count) & 
  509             tc->tc_counter_mask);
  510 }
  511 
  512 /*
  513  * We have eight functions for looking at the clock, four for
  514  * microseconds and four for nanoseconds.  For each there is fast
  515  * but less precise version "get{nano|micro}[up]time" which will
  516  * return a time which is up to 1/HZ previous to the call, whereas
  517  * the raw version "{nano|micro}[up]time" will return a timestamp
  518  * which is as precise as possible.  The "up" variants return the
  519  * time relative to system boot, these are well suited for time
  520  * interval measurements.
  521  */
  522 
  523 void
  524 getmicrotime(struct timeval *tvp)
  525 {
  526         struct timecounter *tc;
  527 
  528         if (!tco_method) {
  529                 tc = timecounter;
  530                 *tvp = tc->tc_microtime;
  531         } else {
  532                 microtime(tvp);
  533         }
  534 }
  535 
  536 void
  537 getnanotime(struct timespec *tsp)
  538 {
  539         struct timecounter *tc;
  540 
  541         if (!tco_method) {
  542                 tc = timecounter;
  543                 *tsp = tc->tc_nanotime;
  544         } else {
  545                 nanotime(tsp);
  546         }
  547 }
  548 
  549 void
  550 microtime(struct timeval *tv)
  551 {
  552         struct timecounter *tc;
  553 
  554         tc = (struct timecounter *)timecounter;
  555         tv->tv_sec = tc->tc_offset_sec;
  556         tv->tv_usec = tc->tc_offset_micro;
  557         tv->tv_usec += ((u_int64_t)tco_delta(tc) * tc->tc_scale_micro) >> 32;
  558         tv->tv_usec += boottime.tv_usec;
  559         tv->tv_sec += boottime.tv_sec;
  560         while (tv->tv_usec >= 1000000) {
  561                 tv->tv_usec -= 1000000;
  562                 tv->tv_sec++;
  563         }
  564 }
  565 
  566 void
  567 nanotime(struct timespec *ts)
  568 {
  569         unsigned count;
  570         u_int64_t delta;
  571         struct timecounter *tc;
  572 
  573         tc = (struct timecounter *)timecounter;
  574         ts->tv_sec = tc->tc_offset_sec;
  575         count = tco_delta(tc);
  576         delta = tc->tc_offset_nano;
  577         delta += ((u_int64_t)count * tc->tc_scale_nano_f);
  578         delta >>= 32;
  579         delta += ((u_int64_t)count * tc->tc_scale_nano_i);
  580         delta += boottime.tv_usec * 1000;
  581         ts->tv_sec += boottime.tv_sec;
  582         while (delta >= 1000000000) {
  583                 delta -= 1000000000;
  584                 ts->tv_sec++;
  585         }
  586         ts->tv_nsec = delta;
  587 }
  588 
  589 void
  590 getmicrouptime(struct timeval *tvp)
  591 {
  592         struct timecounter *tc;
  593 
  594         if (!tco_method) {
  595                 tc = timecounter;
  596                 tvp->tv_sec = tc->tc_offset_sec;
  597                 tvp->tv_usec = tc->tc_offset_micro;
  598         } else {
  599                 microuptime(tvp);
  600         }
  601 }
  602 
  603 void
  604 getnanouptime(struct timespec *tsp)
  605 {
  606         struct timecounter *tc;
  607 
  608         if (!tco_method) {
  609                 tc = timecounter;
  610                 tsp->tv_sec = tc->tc_offset_sec;
  611                 tsp->tv_nsec = tc->tc_offset_nano >> 32;
  612         } else {
  613                 nanouptime(tsp);
  614         }
  615 }
  616 
  617 void
  618 microuptime(struct timeval *tv)
  619 {
  620         struct timecounter *tc;
  621 
  622         tc = (struct timecounter *)timecounter;
  623         tv->tv_sec = tc->tc_offset_sec;
  624         tv->tv_usec = tc->tc_offset_micro;
  625         tv->tv_usec += ((u_int64_t)tco_delta(tc) * tc->tc_scale_micro) >> 32;
  626         if (tv->tv_usec >= 1000000) {
  627                 tv->tv_usec -= 1000000;
  628                 tv->tv_sec++;
  629         }
  630 }
  631 
  632 void
  633 nanouptime(struct timespec *ts)
  634 {
  635         unsigned count;
  636         u_int64_t delta;
  637         struct timecounter *tc;
  638 
  639         tc = (struct timecounter *)timecounter;
  640         ts->tv_sec = tc->tc_offset_sec;
  641         count = tco_delta(tc);
  642         delta = tc->tc_offset_nano;
  643         delta += ((u_int64_t)count * tc->tc_scale_nano_f);
  644         delta >>= 32;
  645         delta += ((u_int64_t)count * tc->tc_scale_nano_i);
  646         if (delta >= 1000000000) {
  647                 delta -= 1000000000;
  648                 ts->tv_sec++;
  649         }
  650         ts->tv_nsec = delta;
  651 }
  652 
  653 static void
  654 tco_setscales(struct timecounter *tc)
  655 {
  656         u_int64_t scale;
  657 
  658         scale = 1000000000LL << 32;
  659         scale += tc->tc_adjustment;
  660         scale /= tc->tc_tweak->tc_frequency;
  661         tc->tc_scale_micro = scale / 1000;
  662         tc->tc_scale_nano_f = scale & 0xffffffff;
  663         tc->tc_scale_nano_i = scale >> 32;
  664 }
  665 
  666 void
  667 update_timecounter(struct timecounter *tc)
  668 {
  669         tco_setscales(tc);
  670 }
  671 
  672 void
  673 init_timecounter(struct timecounter *tc)
  674 {
  675         struct timespec ts1;
  676         struct timecounter *t1, *t2, *t3;
  677         int i;
  678 
  679         tc->tc_adjustment = 0;
  680         tc->tc_tweak = tc;
  681         tco_setscales(tc);
  682         tc->tc_offset_count = tc->tc_get_timecount(tc);
  683         MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK);
  684         *t1 = *tc;
  685         t2 = t1;
  686         for (i = 1; i < NTIMECOUNTER; i++) {
  687                 MALLOC(t3, struct timecounter *, sizeof *t3,
  688                     M_TIMECOUNTER, M_WAITOK);
  689                 *t3 = *tc;
  690                 t3->tc_other = t2;
  691                 t2 = t3;
  692         }
  693         t1->tc_other = t3;
  694         tc = t1;
  695 
  696         printf("Timecounter \"%s\"  frequency %lu Hz\n", 
  697             tc->tc_name, (u_long)tc->tc_frequency);
  698 
  699         /* XXX: For now always start using the counter. */
  700         tc->tc_offset_count = tc->tc_get_timecount(tc);
  701         nanouptime(&ts1);
  702         tc->tc_offset_nano = (u_int64_t)ts1.tv_nsec << 32;
  703         tc->tc_offset_micro = ts1.tv_nsec / 1000;
  704         tc->tc_offset_sec = ts1.tv_sec;
  705         timecounter = tc;
  706 }
  707 
  708 void
  709 set_timecounter(struct timespec *ts)
  710 {
  711         struct timespec ts2;
  712 
  713         nanouptime(&ts2);
  714         boottime.tv_sec = ts->tv_sec - ts2.tv_sec;
  715         boottime.tv_usec = (ts->tv_nsec - ts2.tv_nsec) / 1000;
  716         if (boottime.tv_usec < 0) {
  717                 boottime.tv_usec += 1000000;
  718                 boottime.tv_sec--;
  719         }
  720         /* fiddle all the little crinkly bits around the fiords... */
  721         tco_forward(1);
  722 }
  723 
  724 
  725 #if 0 /* Currently unused */
  726 void
  727 switch_timecounter(struct timecounter *newtc)
  728 {
  729         int s;
  730         struct timecounter *tc;
  731         struct timespec ts;
  732 
  733         s = splclock();
  734         tc = timecounter;
  735         if (newtc == tc || newtc == tc->tc_other) {
  736                 splx(s);
  737                 return;
  738         }
  739         nanouptime(&ts);
  740         newtc->tc_offset_sec = ts.tv_sec;
  741         newtc->tc_offset_nano = (u_int64_t)ts.tv_nsec << 32;
  742         newtc->tc_offset_micro = ts.tv_nsec / 1000;
  743         newtc->tc_offset_count = newtc->tc_get_timecount(newtc);
  744         timecounter = newtc;
  745         splx(s);
  746 }
  747 #endif
  748 
  749 static struct timecounter *
  750 sync_other_counter(void)
  751 {
  752         struct timecounter *tc, *tcn, *tco;
  753         unsigned delta;
  754 
  755         tco = timecounter;
  756         tc = tco->tc_other;
  757         tcn = tc->tc_other;
  758         *tc = *tco;
  759         tc->tc_other = tcn;
  760         delta = tco_delta(tc);
  761         tc->tc_offset_count += delta;
  762         tc->tc_offset_count &= tc->tc_counter_mask;
  763         tc->tc_offset_nano += (u_int64_t)delta * tc->tc_scale_nano_f;
  764         tc->tc_offset_nano += (u_int64_t)delta * tc->tc_scale_nano_i << 32;
  765         return (tc);
  766 }
  767 
  768 static void
  769 tco_forward(int force)
  770 {
  771         struct timecounter *tc, *tco;
  772 
  773         tco = timecounter;
  774         tc = sync_other_counter();
  775         /*
  776          * We may be inducing a tiny error here, the tc_poll_pps() may
  777          * process a latched count which happens after the tco_delta()
  778          * in sync_other_counter(), which would extend the previous
  779          * counters parameters into the domain of this new one.
  780          * Since the timewindow is very small for this, the error is
  781          * going to be only a few weenieseconds (as Dave Mills would
  782          * say), so lets just not talk more about it, OK ?
  783          */
  784         if (tco->tc_poll_pps) 
  785                 tco->tc_poll_pps(tco);
  786         if (timedelta != 0) {
  787                 tc->tc_offset_nano += (u_int64_t)(tickdelta * 1000) << 32;
  788                 timedelta -= tickdelta;
  789                 force++;
  790         }
  791 
  792         while (tc->tc_offset_nano >= 1000000000ULL << 32) {
  793                 tc->tc_offset_nano -= 1000000000ULL << 32;
  794                 tc->tc_offset_sec++;
  795                 ntp_update_second(tc);  /* XXX only needed if xntpd runs */
  796                 tco_setscales(tc);
  797                 force++;
  798         }
  799 
  800         if (tco_method && !force)
  801                 return;
  802 
  803         tc->tc_offset_micro = (tc->tc_offset_nano / 1000) >> 32;
  804 
  805         /* Figure out the wall-clock time */
  806         tc->tc_nanotime.tv_sec = tc->tc_offset_sec + boottime.tv_sec;
  807         tc->tc_nanotime.tv_nsec = 
  808             (tc->tc_offset_nano >> 32) + boottime.tv_usec * 1000;
  809         tc->tc_microtime.tv_usec = tc->tc_offset_micro + boottime.tv_usec;
  810         if (tc->tc_nanotime.tv_nsec >= 1000000000) {
  811                 tc->tc_nanotime.tv_nsec -= 1000000000;
  812                 tc->tc_microtime.tv_usec -= 1000000;
  813                 tc->tc_nanotime.tv_sec++;
  814         }
  815         time_second = tc->tc_microtime.tv_sec = tc->tc_nanotime.tv_sec;
  816 
  817         timecounter = tc;
  818 }
  819 
  820 SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
  821 
  822 SYSCTL_INT(_kern_timecounter, OID_AUTO, method, CTLFLAG_RW, &tco_method, 0,
  823     "This variable determines the method used for updating timecounters. "
  824     "If the default algorithm (0) fails with \"calcru negative...\" messages "
  825     "try the alternate algorithm (1) which handles bad hardware better."
  826 
  827 );
  828 
  829 
  830 int
  831 pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
  832 {
  833         pps_params_t *app;
  834         struct pps_fetch_args *fapi;
  835 #ifdef PPS_SYNC
  836         struct pps_kcbind_args *kapi;
  837 #endif
  838 
  839         switch (cmd) {
  840         case PPS_IOC_CREATE:
  841                 return (0);
  842         case PPS_IOC_DESTROY:
  843                 return (0);
  844         case PPS_IOC_SETPARAMS:
  845                 app = (pps_params_t *)data;
  846                 if (app->mode & ~pps->ppscap)
  847                         return (EINVAL);
  848                 pps->ppsparam = *app;         
  849                 return (0);
  850         case PPS_IOC_GETPARAMS:
  851                 app = (pps_params_t *)data;
  852                 *app = pps->ppsparam;
  853                 app->api_version = PPS_API_VERS_1;
  854                 return (0);
  855         case PPS_IOC_GETCAP:
  856                 *(int*)data = pps->ppscap;
  857                 return (0);
  858         case PPS_IOC_FETCH:
  859                 fapi = (struct pps_fetch_args *)data;
  860                 if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
  861                         return (EINVAL);
  862                 if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
  863                         return (EOPNOTSUPP);
  864                 pps->ppsinfo.current_mode = pps->ppsparam.mode;         
  865                 fapi->pps_info_buf = pps->ppsinfo;
  866                 return (0);
  867         case PPS_IOC_KCBIND:
  868 #ifdef PPS_SYNC
  869                 kapi = (struct pps_kcbind_args *)data;
  870                 /* XXX Only root should be able to do this */
  871                 if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
  872                         return (EINVAL);
  873                 if (kapi->kernel_consumer != PPS_KC_HARDPPS)
  874                         return (EINVAL);
  875                 if (kapi->edge & ~pps->ppscap)
  876                         return (EINVAL);
  877                 pps->kcmode = kapi->edge;
  878                 return (0);
  879 #else
  880                 return (EOPNOTSUPP);
  881 #endif
  882         default:
  883                 return (ENOTTY);
  884         }
  885 }
  886 
  887 void
  888 pps_init(struct pps_state *pps)
  889 {
  890         pps->ppscap |= PPS_TSFMT_TSPEC;
  891         if (pps->ppscap & PPS_CAPTUREASSERT)
  892                 pps->ppscap |= PPS_OFFSETASSERT;
  893         if (pps->ppscap & PPS_CAPTURECLEAR)
  894                 pps->ppscap |= PPS_OFFSETCLEAR;
  895 }
  896 
  897 void
  898 pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event)
  899 {
  900         struct timespec ts, *tsp, *osp;
  901         u_int64_t delta;
  902         unsigned tcount, *pcount;
  903         int foff, fhard;
  904         pps_seq_t       *pseq;
  905 
  906         /* Things would be easier with arrays... */
  907         if (event == PPS_CAPTUREASSERT) {
  908                 tsp = &pps->ppsinfo.assert_timestamp;
  909                 osp = &pps->ppsparam.assert_offset;
  910                 foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
  911                 fhard = pps->kcmode & PPS_CAPTUREASSERT;
  912                 pcount = &pps->ppscount[0];
  913                 pseq = &pps->ppsinfo.assert_sequence;
  914         } else {
  915                 tsp = &pps->ppsinfo.clear_timestamp;
  916                 osp = &pps->ppsparam.clear_offset;
  917                 foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
  918                 fhard = pps->kcmode & PPS_CAPTURECLEAR;
  919                 pcount = &pps->ppscount[1];
  920                 pseq = &pps->ppsinfo.clear_sequence;
  921         }
  922 
  923         /* The timecounter changed: bail */
  924         if (!pps->ppstc || 
  925             pps->ppstc->tc_name != tc->tc_name || 
  926             tc->tc_name != timecounter->tc_name) {
  927                 pps->ppstc = tc;
  928                 *pcount = count;
  929                 return;
  930         }
  931 
  932         /* Nothing really happened */
  933         if (*pcount == count)
  934                 return;
  935 
  936         *pcount = count;
  937 
  938         /* Convert the count to timespec */
  939         ts.tv_sec = tc->tc_offset_sec;
  940         tcount = count - tc->tc_offset_count;
  941         tcount &= tc->tc_counter_mask;
  942         delta = tc->tc_offset_nano;
  943         delta += ((u_int64_t)tcount * tc->tc_scale_nano_f);
  944         delta >>= 32;
  945         delta += ((u_int64_t)tcount * tc->tc_scale_nano_i);
  946         delta += boottime.tv_usec * 1000;
  947         ts.tv_sec += boottime.tv_sec;
  948         while (delta >= 1000000000) {
  949                 delta -= 1000000000;
  950                 ts.tv_sec++;
  951         }
  952         ts.tv_nsec = delta;
  953 
  954         (*pseq)++;
  955         *tsp = ts;
  956 
  957         if (foff) {
  958                 timespecadd(tsp, osp);
  959                 if (tsp->tv_nsec < 0) {
  960                         tsp->tv_nsec += 1000000000;
  961                         tsp->tv_sec -= 1;
  962                 }
  963         }
  964 #ifdef PPS_SYNC
  965         if (fhard) {
  966                 /* magic, at its best... */
  967                 tcount = count - pps->ppscount[2];
  968                 pps->ppscount[2] = count;
  969                 tcount &= tc->tc_counter_mask;
  970                 delta = ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_f);
  971                 delta >>= 32;
  972                 delta += ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_i);
  973                 hardpps(tsp, delta);
  974         }
  975 #endif
  976 }

Cache object: 972247d99a4b10dfdf14d77bca827d05


[ 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.