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_ntptime.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  *                                                                            *
    3  * Copyright (c) David L. Mills 1993, 1994                                    *
    4  *                                                                            *
    5  * Permission to use, copy, modify, and distribute this software and its      *
    6  * documentation for any purpose and without fee is hereby granted, provided  *
    7  * that the above copyright notice appears in all copies and that both the    *
    8  * copyright notice and this permission notice appear in supporting           *
    9  * documentation, and that the name University of Delaware not be used in     *
   10  * advertising or publicity pertaining to distribution of the software        *
   11  * without specific, written prior permission.  The University of Delaware    *
   12  * makes no representations about the suitability this software for any       *
   13  * purpose.  It is provided "as is" without express or implied warranty.      *
   14  *                                                                            *
   15  ******************************************************************************/
   16 
   17 /*
   18  * Modification history kern_ntptime.c
   19  *
   20  * 24 Sep 94    David L. Mills
   21  *      Tightened code at exits.
   22  *
   23  * 24 Mar 94    David L. Mills
   24  *      Revised syscall interface to include new variables for PPS
   25  *      time discipline.
   26  *
   27  * 14 Feb 94    David L. Mills
   28  *      Added code for external clock
   29  *
   30  * 28 Nov 93    David L. Mills
   31  *      Revised frequency scaling to conform with adjusted parameters
   32  *
   33  * 17 Sep 93    David L. Mills
   34  *      Created file
   35  */
   36 /*
   37  * ntp_gettime(), ntp_adjtime() - precision time interface for SunOS
   38  * V4.1.1 and V4.1.3
   39  *
   40  * These routines consitute the Network Time Protocol (NTP) interfaces
   41  * for user and daemon application programs. The ntp_gettime() routine
   42  * provides the time, maximum error (synch distance) and estimated error
   43  * (dispersion) to client user application programs. The ntp_adjtime()
   44  * routine is used by the NTP daemon to adjust the system clock to an
   45  * externally derived time. The time offset and related variables set by
   46  * this routine are used by hardclock() to adjust the phase and
   47  * frequency of the phase-lock loop which controls the system clock.
   48  */
   49 #include <sys/param.h>
   50 #include <sys/systm.h>
   51 #include <sys/sysproto.h>
   52 #include <sys/kernel.h>
   53 #include <sys/proc.h>
   54 #include <sys/timex.h>
   55 #include <sys/sysctl.h>
   56 
   57 /*
   58  * The following variables are used by the hardclock() routine in the
   59  * kern_clock.c module and are described in that module.
   60  */
   61 extern int time_state;          /* clock state */
   62 extern int time_status;         /* clock status bits */
   63 extern long time_offset;        /* time adjustment (us) */
   64 extern long time_freq;          /* frequency offset (scaled ppm) */
   65 extern long time_maxerror;      /* maximum error (us) */
   66 extern long time_esterror;      /* estimated error (us) */
   67 extern long time_constant;      /* pll time constant */
   68 extern long time_precision;     /* clock precision (us) */
   69 extern long time_tolerance;     /* frequency tolerance (scaled ppm) */
   70 
   71 #ifdef PPS_SYNC
   72 /*
   73  * The following variables are used only if the PPS signal discipline
   74  * is configured in the kernel.
   75  */
   76 extern int pps_shift;           /* interval duration (s) (shift) */
   77 extern long pps_freq;           /* pps frequency offset (scaled ppm) */
   78 extern long pps_jitter;         /* pps jitter (us) */
   79 extern long pps_stabil;         /* pps stability (scaled ppm) */
   80 extern long pps_jitcnt;         /* jitter limit exceeded */
   81 extern long pps_calcnt;         /* calibration intervals */
   82 extern long pps_errcnt;         /* calibration errors */
   83 extern long pps_stbcnt;         /* stability limit exceeded */
   84 #endif /* PPS_SYNC */
   85 
   86 static int
   87 ntp_sysctl SYSCTL_HANDLER_ARGS
   88 {
   89         struct timeval atv;
   90         struct ntptimeval ntv;
   91         int s;
   92 
   93         s = splclock();
   94 #ifdef EXT_CLOCK
   95         /*
   96          * The microtime() external clock routine returns a
   97          * status code. If less than zero, we declare an error
   98          * in the clock status word and return the kernel
   99          * (software) time variable. While there are other
  100          * places that call microtime(), this is the only place
  101          * that matters from an application point of view.
  102          */
  103         if (microtime(&atv) < 0) {
  104                 time_status |= STA_CLOCKERR;
  105                 ntv.time = time;
  106         } else {
  107                 time_status &= ~STA_CLOCKERR;
  108         }
  109 #else /* EXT_CLOCK */
  110         microtime(&atv);
  111 #endif /* EXT_CLOCK */
  112         ntv.time = atv;
  113         ntv.maxerror = time_maxerror;
  114         ntv.esterror = time_esterror;
  115         splx(s);
  116 
  117         ntv.time_state = time_state;
  118 
  119         /*
  120          * Status word error decode. If any of these conditions
  121          * occur, an error is returned, instead of the status
  122          * word. Most applications will care only about the fact
  123          * the system clock may not be trusted, not about the
  124          * details.
  125          *
  126          * Hardware or software error
  127          */
  128         if (time_status & (STA_UNSYNC | STA_CLOCKERR)) {
  129                 ntv.time_state = TIME_ERROR;
  130         }
  131 
  132         /*
  133          * PPS signal lost when either time or frequency
  134          * synchronization requested
  135          */
  136         if (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
  137             !(time_status & STA_PPSSIGNAL)) {
  138                 ntv.time_state = TIME_ERROR;
  139         }
  140 
  141         /*
  142          * PPS jitter exceeded when time synchronization
  143          * requested
  144          */
  145         if (time_status & STA_PPSTIME &&
  146             time_status & STA_PPSJITTER) {
  147                 ntv.time_state = TIME_ERROR;
  148         }
  149 
  150         /*
  151          * PPS wander exceeded or calibration error when
  152          * frequency synchronization requested
  153          */
  154         if (time_status & STA_PPSFREQ &&
  155             time_status & (STA_PPSWANDER | STA_PPSERROR)) {
  156                 ntv.time_state = TIME_ERROR;
  157         }
  158         return (sysctl_handle_opaque(oidp, &ntv, sizeof ntv, req));
  159 }
  160 
  161 SYSCTL_NODE(_kern, KERN_NTP_PLL, ntp_pll, CTLFLAG_RW, 0,
  162         "NTP kernel PLL related stuff");
  163 SYSCTL_PROC(_kern_ntp_pll, NTP_PLL_GETTIME, gettime, CTLTYPE_OPAQUE|CTLFLAG_RD,
  164         0, sizeof(struct ntptimeval) , ntp_sysctl, "S,ntptimeval", "");
  165 
  166 /*
  167  * ntp_adjtime() - NTP daemon application interface
  168  */
  169 #ifndef _SYS_SYSPROTO_H_
  170 struct ntp_adjtime_args {
  171   struct timex *tp;
  172 };
  173 #endif
  174 
  175 int
  176 ntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap, int *retval)
  177 {
  178         struct timex ntv;
  179         int modes;
  180         int s;
  181         int error;
  182 
  183         error = copyin((caddr_t)uap->tp, (caddr_t)&ntv, sizeof(ntv));
  184         if (error)
  185                 return error;
  186 
  187         /*
  188          * Update selected clock variables - only the superuser can
  189          * change anything. Note that there is no error checking here on
  190          * the assumption the superuser should know what it is doing.
  191          */
  192         modes = ntv.modes;
  193         if ((modes != 0)
  194             && (error = suser(p->p_cred->pc_ucred, &p->p_acflag)))
  195                 return error;
  196 
  197         s = splclock();
  198         if (modes & MOD_FREQUENCY)
  199 #ifdef PPS_SYNC
  200                 time_freq = ntv.freq - pps_freq;
  201 #else /* PPS_SYNC */
  202                 time_freq = ntv.freq;
  203 #endif /* PPS_SYNC */
  204         if (modes & MOD_MAXERROR)
  205                 time_maxerror = ntv.maxerror;
  206         if (modes & MOD_ESTERROR)
  207                 time_esterror = ntv.esterror;
  208         if (modes & MOD_STATUS) {
  209                 time_status &= STA_RONLY;
  210                 time_status |= ntv.status & ~STA_RONLY;
  211         }
  212         if (modes & MOD_TIMECONST)
  213                 time_constant = ntv.constant;
  214         if (modes & MOD_OFFSET)
  215                 hardupdate(ntv.offset);
  216 
  217         /*
  218          * Retrieve all clock variables
  219          */
  220         if (time_offset < 0)
  221                 ntv.offset = -(-time_offset >> SHIFT_UPDATE);
  222         else
  223                 ntv.offset = time_offset >> SHIFT_UPDATE;
  224 #ifdef PPS_SYNC
  225         ntv.freq = time_freq + pps_freq;
  226 #else /* PPS_SYNC */
  227         ntv.freq = time_freq;
  228 #endif /* PPS_SYNC */
  229         ntv.maxerror = time_maxerror;
  230         ntv.esterror = time_esterror;
  231         ntv.status = time_status;
  232         ntv.constant = time_constant;
  233         ntv.precision = time_precision;
  234         ntv.tolerance = time_tolerance;
  235 #ifdef PPS_SYNC
  236         ntv.shift = pps_shift;
  237         ntv.ppsfreq = pps_freq;
  238         ntv.jitter = pps_jitter >> PPS_AVG;
  239         ntv.stabil = pps_stabil;
  240         ntv.calcnt = pps_calcnt;
  241         ntv.errcnt = pps_errcnt;
  242         ntv.jitcnt = pps_jitcnt;
  243         ntv.stbcnt = pps_stbcnt;
  244 #endif /* PPS_SYNC */
  245         (void)splx(s);
  246 
  247         error = copyout((caddr_t)&ntv, (caddr_t)uap->tp, sizeof(ntv));
  248         if (!error) {
  249                 /*
  250                  * Status word error decode. See comments in
  251                  * ntp_gettime() routine.
  252                  */
  253                 retval[0] = time_state;
  254                 if (time_status & (STA_UNSYNC | STA_CLOCKERR))
  255                         retval[0] = TIME_ERROR;
  256                 if (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
  257                     !(time_status & STA_PPSSIGNAL))
  258                         retval[0] = TIME_ERROR;
  259                 if (time_status & STA_PPSTIME &&
  260                     time_status & STA_PPSJITTER)
  261                         retval[0] = TIME_ERROR;
  262                 if (time_status & STA_PPSFREQ &&
  263                     time_status & (STA_PPSWANDER | STA_PPSERROR))
  264                         retval[0] = TIME_ERROR;
  265         }
  266         return error;
  267 }
  268 
  269 

Cache object: 6b19979e20f5d8c9f18ecce3379f3402


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