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 /*      $NetBSD: kern_ntptime.c,v 1.26.2.1 2004/04/21 04:27:44 jmc Exp $        */
    2 
    3 /******************************************************************************
    4  *                                                                            *
    5  * Copyright (c) David L. Mills 1993, 1994                                    *
    6  *                                                                            *
    7  * Permission to use, copy, modify, and distribute this software and its      *
    8  * documentation for any purpose and without fee is hereby granted, provided  *
    9  * that the above copyright notice appears in all copies and that both the    *
   10  * copyright notice and this permission notice appear in supporting           *
   11  * documentation, and that the name University of Delaware not be used in     *
   12  * advertising or publicity pertaining to distribution of the software        *
   13  * without specific, written prior permission.  The University of Delaware    *
   14  * makes no representations about the suitability this software for any       *
   15  * purpose.  It is provided "as is" without express or implied warranty.      *
   16  *                                                                            *
   17  ******************************************************************************/
   18 
   19 /*
   20  * Modification history kern_ntptime.c
   21  *
   22  * 24 Sep 94    David L. Mills
   23  *      Tightened code at exits.
   24  *
   25  * 24 Mar 94    David L. Mills
   26  *      Revised syscall interface to include new variables for PPS
   27  *      time discipline.
   28  *
   29  * 14 Feb 94    David L. Mills
   30  *      Added code for external clock
   31  *
   32  * 28 Nov 93    David L. Mills
   33  *      Revised frequency scaling to conform with adjusted parameters
   34  *
   35  * 17 Sep 93    David L. Mills
   36  *      Created file
   37  */
   38 /*
   39  * ntp_gettime(), ntp_adjtime() - precision time interface for SunOS
   40  * V4.1.1 and V4.1.3
   41  *
   42  * These routines consitute the Network Time Protocol (NTP) interfaces
   43  * for user and daemon application programs. The ntp_gettime() routine
   44  * provides the time, maximum error (synch distance) and estimated error
   45  * (dispersion) to client user application programs. The ntp_adjtime()
   46  * routine is used by the NTP daemon to adjust the system clock to an
   47  * externally derived time. The time offset and related variables set by
   48  * this routine are used by hardclock() to adjust the phase and
   49  * frequency of the phase-lock loop which controls the system clock.
   50  */
   51 
   52 #include <sys/cdefs.h>
   53 __KERNEL_RCSID(0, "$NetBSD: kern_ntptime.c,v 1.26.2.1 2004/04/21 04:27:44 jmc Exp $");
   54 
   55 #include "opt_ntp.h"
   56 
   57 #include <sys/param.h>
   58 #include <sys/resourcevar.h>
   59 #include <sys/systm.h>
   60 #include <sys/kernel.h>
   61 #include <sys/proc.h>
   62 #include <sys/sysctl.h>
   63 #include <sys/timex.h>
   64 #include <sys/vnode.h>
   65 
   66 #include <sys/mount.h>
   67 #include <sys/sa.h>
   68 #include <sys/syscallargs.h>
   69 
   70 #include <machine/cpu.h>
   71 
   72 #ifdef NTP
   73 /*
   74  * The following variables are used by the hardclock() routine in the
   75  * kern_clock.c module and are described in that module. 
   76  */
   77 extern int time_state;          /* clock state */
   78 extern int time_status;         /* clock status bits */
   79 extern long time_offset;        /* time adjustment (us) */
   80 extern long time_freq;          /* frequency offset (scaled ppm) */
   81 extern long time_maxerror;      /* maximum error (us) */
   82 extern long time_esterror;      /* estimated error (us) */
   83 extern long time_constant;      /* pll time constant */
   84 extern long time_precision;     /* clock precision (us) */
   85 extern long time_tolerance;     /* frequency tolerance (scaled ppm) */
   86 extern int time_adjusted;       /* ntp might have changed the system time */
   87 
   88 #ifdef PPS_SYNC
   89 /*
   90  * The following variables are used only if the PPS signal discipline
   91  * is configured in the kernel.
   92  */
   93 extern int pps_shift;           /* interval duration (s) (shift) */
   94 extern long pps_freq;           /* pps frequency offset (scaled ppm) */
   95 extern long pps_jitter;         /* pps jitter (us) */
   96 extern long pps_stabil;         /* pps stability (scaled ppm) */
   97 extern long pps_jitcnt;         /* jitter limit exceeded */
   98 extern long pps_calcnt;         /* calibration intervals */
   99 extern long pps_errcnt;         /* calibration errors */
  100 extern long pps_stbcnt;         /* stability limit exceeded */
  101 #endif /* PPS_SYNC */
  102 
  103 /*ARGSUSED*/
  104 /*
  105  * ntp_gettime() - NTP user application interface
  106  */
  107 int
  108 sys_ntp_gettime(l, v, retval)
  109         struct lwp *l;
  110         void *v;
  111         register_t *retval;
  112 
  113 {
  114         struct sys_ntp_gettime_args /* {
  115                 syscallarg(struct ntptimeval *) ntvp;
  116         } */ *uap = v;
  117         struct timeval atv;
  118         struct ntptimeval ntv;
  119         int error = 0;
  120         int s;
  121 
  122         if (SCARG(uap, ntvp)) {
  123                 s = splclock();
  124 #ifdef EXT_CLOCK
  125                 /*
  126                  * The microtime() external clock routine returns a
  127                  * status code. If less than zero, we declare an error
  128                  * in the clock status word and return the kernel
  129                  * (software) time variable. While there are other
  130                  * places that call microtime(), this is the only place
  131                  * that matters from an application point of view.
  132                  */
  133                 if (microtime(&atv) < 0) {
  134                         time_status |= STA_CLOCKERR;
  135                         ntv.time = time;
  136                 } else
  137                         time_status &= ~STA_CLOCKERR;
  138 #else /* EXT_CLOCK */
  139                 microtime(&atv);
  140 #endif /* EXT_CLOCK */
  141                 ntv.time = atv;
  142                 ntv.maxerror = time_maxerror;
  143                 ntv.esterror = time_esterror;
  144                 (void) splx(s);
  145 
  146                 error = copyout((caddr_t)&ntv, (caddr_t)SCARG(uap, ntvp),
  147                     sizeof(ntv));
  148         }
  149         if (!error) {
  150 
  151                 /*
  152                  * Status word error decode. If any of these conditions
  153                  * occur, an error is returned, instead of the status
  154                  * word. Most applications will care only about the fact
  155                  * the system clock may not be trusted, not about the
  156                  * details.
  157                  *
  158                  * Hardware or software error
  159                  */
  160                 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
  161 
  162                 /*
  163                  * PPS signal lost when either time or frequency
  164                  * synchronization requested
  165                  */
  166                     (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
  167                     !(time_status & STA_PPSSIGNAL)) ||
  168 
  169                 /*
  170                  * PPS jitter exceeded when time synchronization
  171                  * requested
  172                  */
  173                     (time_status & STA_PPSTIME &&
  174                     time_status & STA_PPSJITTER) ||
  175 
  176                 /*
  177                  * PPS wander exceeded or calibration error when
  178                  * frequency synchronization requested
  179                  */
  180                     (time_status & STA_PPSFREQ &&
  181                     time_status & (STA_PPSWANDER | STA_PPSERROR)))
  182                         *retval = TIME_ERROR;
  183                 else
  184                         *retval = (register_t)time_state;
  185         }
  186         return(error);
  187 }
  188 
  189 /* ARGSUSED */
  190 /*
  191  * ntp_adjtime() - NTP daemon application interface
  192  */
  193 int
  194 sys_ntp_adjtime(l, v, retval)
  195         struct lwp *l;
  196         void *v;
  197         register_t *retval;
  198 {
  199         struct sys_ntp_adjtime_args /* {
  200                 syscallarg(struct timex *) tp;
  201         } */ *uap = v;
  202         struct proc *p = l->l_proc;
  203         struct timex ntv;
  204         int error = 0;
  205 
  206         if ((error = copyin((caddr_t)SCARG(uap, tp), (caddr_t)&ntv,
  207                         sizeof(ntv))) != 0)
  208                 return (error);
  209 
  210         if (ntv.modes != 0 && (error = suser(p->p_ucred, &p->p_acflag)) != 0)
  211                 return (error);
  212 
  213         return (ntp_adjtime1(&ntv, v, retval));
  214 }
  215 
  216 int
  217 ntp_adjtime1(ntv, v, retval)
  218         struct timex *ntv;
  219         void *v;
  220         register_t      *retval;
  221 {
  222         struct sys_ntp_adjtime_args /* {
  223                 syscallarg(struct timex *) tp;
  224         } */ *uap = v;
  225         int error = 0;
  226         int modes;
  227         int s;
  228 
  229         /*
  230          * Update selected clock variables. Note that there is no error 
  231          * checking here on the assumption the superuser should know 
  232          * what it is doing.
  233          */
  234         modes = ntv->modes;
  235         if (modes != 0)
  236                 /* We need to save the system time during shutdown */
  237                 time_adjusted |= 2;
  238         s = splclock();
  239         if (modes & MOD_FREQUENCY)
  240 #ifdef PPS_SYNC
  241                 time_freq = ntv->freq - pps_freq;
  242 #else /* PPS_SYNC */
  243                 time_freq = ntv->freq;
  244 #endif /* PPS_SYNC */
  245         if (modes & MOD_MAXERROR)
  246                 time_maxerror = ntv->maxerror;
  247         if (modes & MOD_ESTERROR)
  248                 time_esterror = ntv->esterror;
  249         if (modes & MOD_STATUS) {
  250                 time_status &= STA_RONLY;
  251                 time_status |= ntv->status & ~STA_RONLY;
  252         }
  253         if (modes & MOD_TIMECONST)
  254                 time_constant = ntv->constant;
  255         if (modes & MOD_OFFSET)
  256                 hardupdate(ntv->offset);
  257 
  258         /*
  259          * Retrieve all clock variables
  260          */
  261         if (time_offset < 0)
  262                 ntv->offset = -(-time_offset >> SHIFT_UPDATE);
  263         else
  264                 ntv->offset = time_offset >> SHIFT_UPDATE;
  265 #ifdef PPS_SYNC
  266         ntv->freq = time_freq + pps_freq;
  267 #else /* PPS_SYNC */
  268         ntv->freq = time_freq;
  269 #endif /* PPS_SYNC */
  270         ntv->maxerror = time_maxerror;
  271         ntv->esterror = time_esterror;
  272         ntv->status = time_status;
  273         ntv->constant = time_constant;
  274         ntv->precision = time_precision;
  275         ntv->tolerance = time_tolerance;
  276 #ifdef PPS_SYNC
  277         ntv->shift = pps_shift;
  278         ntv->ppsfreq = pps_freq;
  279         ntv->jitter = pps_jitter >> PPS_AVG;
  280         ntv->stabil = pps_stabil;
  281         ntv->calcnt = pps_calcnt;
  282         ntv->errcnt = pps_errcnt;
  283         ntv->jitcnt = pps_jitcnt;
  284         ntv->stbcnt = pps_stbcnt;
  285 #endif /* PPS_SYNC */
  286         (void)splx(s);
  287 
  288         error = copyout((caddr_t)ntv, (caddr_t)SCARG(uap, tp), sizeof(*ntv));
  289         if (!error) {
  290 
  291                 /*
  292                  * Status word error decode. See comments in
  293                  * ntp_gettime() routine.
  294                  */
  295                 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
  296                     (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
  297                     !(time_status & STA_PPSSIGNAL)) ||
  298                     (time_status & STA_PPSTIME &&
  299                     time_status & STA_PPSJITTER) ||
  300                     (time_status & STA_PPSFREQ &&
  301                     time_status & (STA_PPSWANDER | STA_PPSERROR)))
  302                         *retval = TIME_ERROR;
  303                 else
  304                         *retval = (register_t)time_state;
  305         }
  306         return error;
  307 }
  308 
  309 /*
  310  * return information about kernel precision timekeeping
  311  */
  312 static int
  313 sysctl_kern_ntptime(SYSCTLFN_ARGS)
  314 {
  315         struct sysctlnode node;
  316         struct timeval atv;
  317         struct ntptimeval ntv;
  318         int s;
  319 
  320         /*
  321          * Construct ntp_timeval.
  322          */
  323 
  324         s = splclock();
  325 #ifdef EXT_CLOCK
  326         /*
  327          * The microtime() external clock routine returns a
  328          * status code. If less than zero, we declare an error
  329          * in the clock status word and return the kernel
  330          * (software) time variable. While there are other
  331          * places that call microtime(), this is the only place
  332          * that matters from an application point of view.
  333          */
  334         if (microtime(&atv) < 0) {
  335                 time_status |= STA_CLOCKERR;
  336                 ntv.time = time;
  337         } else {
  338                 time_status &= ~STA_CLOCKERR;
  339         }
  340 #else /* EXT_CLOCK */
  341         microtime(&atv);
  342 #endif /* EXT_CLOCK */
  343         ntv.time = atv;
  344         ntv.maxerror = time_maxerror;
  345         ntv.esterror = time_esterror;
  346         splx(s);
  347 
  348 #ifdef notyet
  349         /*
  350          * Status word error decode. If any of these conditions
  351          * occur, an error is returned, instead of the status
  352          * word. Most applications will care only about the fact
  353          * the system clock may not be trusted, not about the
  354          * details.
  355          *
  356          * Hardware or software error
  357          */
  358         if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) ||
  359                 ntv.time_state = TIME_ERROR;
  360 
  361         /*
  362          * PPS signal lost when either time or frequency
  363          * synchronization requested
  364          */
  365            (time_status & (STA_PPSFREQ | STA_PPSTIME) &&
  366             !(time_status & STA_PPSSIGNAL)) ||
  367 
  368         /*
  369          * PPS jitter exceeded when time synchronization
  370          * requested
  371          */
  372            (time_status & STA_PPSTIME &&
  373             time_status & STA_PPSJITTER) ||
  374 
  375         /*
  376          * PPS wander exceeded or calibration error when
  377          * frequency synchronization requested
  378          */
  379            (time_status & STA_PPSFREQ &&
  380             time_status & (STA_PPSWANDER | STA_PPSERROR)))
  381                 ntv.time_state = TIME_ERROR;
  382         else
  383                 ntv.time_state = time_state;
  384 #endif /* notyet */
  385 
  386         node = *rnode;
  387         node.sysctl_data = &ntv;
  388         node.sysctl_size = sizeof(ntv);
  389         return (sysctl_lookup(SYSCTLFN_CALL(&node)));
  390 }
  391 
  392 SYSCTL_SETUP(sysctl_kern_ntptime_setup, "sysctl kern.ntptime node setup")
  393 {
  394 
  395         sysctl_createv(clog, 0, NULL, NULL,
  396                        CTLFLAG_PERMANENT,
  397                        CTLTYPE_NODE, "kern", NULL,
  398                        NULL, 0, NULL, 0,
  399                        CTL_KERN, CTL_EOL);
  400 
  401         sysctl_createv(clog, 0, NULL, NULL,
  402                        CTLFLAG_PERMANENT,
  403                        CTLTYPE_STRUCT, "ntptime",
  404                        SYSCTL_DESCR("Kernel clock values for NTP"),
  405                        sysctl_kern_ntptime, 0, NULL,
  406                        sizeof(struct ntptimeval),
  407                        CTL_KERN, KERN_NTPTIME, CTL_EOL);
  408 }
  409 #else /* !NTP */
  410 /* For some reason, raising SIGSYS (as sys_nosys would) is problematic. */
  411 
  412 int
  413 sys_ntp_gettime(l, v, retval)
  414         struct lwp *l;
  415         void *v;
  416         register_t *retval;
  417 {
  418 
  419         return(ENOSYS);
  420 }
  421 #endif /* !NTP */

Cache object: 9067d9788dd98fb53d59bc5e321d1dc5


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