ntp_unixclock.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 1996 by Sun Microsystems, Inc.
* All Rights Reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* ntp_unixclock.c - routines for reading and adjusting a 4BSD-style
* system clock. Emacs has hide-ifdef-mode ...
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef NLIST_STRUCT
# include <nlist.h>
# ifdef NLIST_NAME_UNION
# else /* not NLIST_NAME_UNION */
# endif /* not NLIST_NAME_UNION */
#endif /* NLIST_STRUCT */
#ifdef HAVE_SYS_PARAM_H
#endif
#ifdef HAVE_UTMP_H
# include <utmp.h>
#endif
#ifdef HAVE_SYS_SYSCTL_H
#endif
#if defined(HAVE_GETBOOTFILE)
# include <paths.h>
#endif
#include "ntpd.h"
#include "ntp_io.h"
#include "ntp_unixtime.h"
#include "ntp_stdlib.h"
#if defined(HAVE_LIBKVM)
# ifdef HAVE_SYS_PROC_H
# endif
# include <kvm.h>
# include <limits.h>
# ifndef _POSIX2_LINE_MAX
# define _POSIX2_LINE_MAX 2048
# endif
#endif /* HAVE_LIBKVM */
#ifdef HAVE_SYS_TIMEX_H /* Linux - also HAVE___ADJTIMEX */
#endif
#ifdef hz /* Was: RS6000 */
#endif /* hz */
extern int debug;
/*
* These routines (init_systime, get_systime, step_systime, adj_systime)
* implement an interface between the (more or less) system independent
* bits of NTP and the peculiarities of dealing with the Unix system
* clock. These routines will run with good precision fairly independently
* of your kernel's value of tickadj. I couldn't tell the difference
* between tickadj==40 and tickadj==5 on a microvax, though I prefer
* to set tickadj == 500/hz when in doubt. At your option you
* may compile this so that your system's clock is always slewed to the
* correct time even for large corrections. Of course, all of this takes
* a lot of code which wouldn't be needed with a reasonable tickadj and
* a willingness to let the clock be stepped occasionally. Oh well.
*/
extern long adj_precision; /* adj precision in usec (tickadj) */
extern long tvu_maxslew; /* maximum adjust doable in one sec (usec) */
#ifdef SYS_WINNT
extern long units_per_tick; /* imported from lib/systime.c module */
#endif /* SYS_WINNT */
#if defined(GDT_SURVEYING)
#endif
/*
* Import sys_clock (it is updated in get_systime)
*/
extern long sys_clock;
extern int slewalways;
/*
* Export default_tick and default_tickadj (for ntp_config)
*/
u_long default_tick = 0;
u_long default_tickadj = 0;
/*
* init_systime - initialize the system clock support code, return
* clock precision.
*
* Note that this code obtains to kernel variables related to the local
* clock, tickadj and tick. The code knows how the Berkeley adjtime
* call works, and assumes these two variables are obtainable and are
* used in the same manner. Tick is supposed to be the number of
* microseconds which are added to the system clock at clock interrupt
* time when the time isn't being slewed. Tickadj is supposed to be
* the number of microseconds which are added or subtracted from tick when
* the time is being slewed.
*
* If either of these two variables is missing, or is there but is used
* for a purpose different than that described, you are SOL and may have
* to do some custom kludging.
*
* This really shouldn't be in here.
*/
void
{
/*
* Obtain the values
*/
#if !defined(VMS)
#else
{
}
#endif /* VMS */
#ifdef DEBUG
if (debug)
#endif
/*
* If tickadj or hz wasn't found, we're doomed. If hz is
* unreasonably small, forget it.
*/
exit(3);
}
if (tick > 65535) {
tick);
exit(3);
}
/*
* Estimate hz from tick
*/
#ifndef SYS_VXWORKS
#else
hz =sysClkRateGet();
#endif
#ifdef SYS_WINNT
hz += 1;
#endif /* SYS_WINNT */
/*
* Set adj_precision and the maximum slew based on this. Note
* that maxslew is set slightly shorter than it needs to be as
* insurance that all slews requested will complete in one second.
*/
#ifdef ADJTIME_IS_ACCURATE
adj_precision = 1;
#else
# if defined(SCO3_TICKADJ) || defined(SCO5_TICKADJ)
# else
# ifndef SYS_WINNT
# else
/* minimum adjustment is one 100 nanosecond unit at each clock tick */
# endif /* SYS_WINNT */
# endif /* not SCO[35]_TICKADJ */
#endif /* ADJTIME_IS_ACCURATE */
#ifdef NEED_HPUX_ADJTIME
/*
* when using adjtimed daemon, need to allow more time
* because daemon may not run right away
*/
#else
# if !defined(ADJTIME_IS_ACCURATE)
if (slewalways) {
/*
* give us more time if we are always slewing... just in case
*/
} else {
# else
# endif /* SYS_WINTNT */
}
# else
# else
# endif /* SYS_WINTNT */
# endif /* not ADJTIME_IS_ACCURATE */
#endif /* NEED_HPUX_ADJTIME */
if (tvu_maxslew > 999990) {
/*
* Don't let the maximum slew exceed 1 second in 4. This
* simplifies calculations a lot since we can then deal
* with less-than-one-second fractions.
*/
}
#ifdef DEBUG
if (debug)
"adj_precision = %ld, tvu_maxslew = %ld, tsf_maxslew = 0.%08lx\n",
#endif
/*
* Set the current offset to 0
*/
#if defined(GDT_SURVEYING)
/*
* Set the current increment
*/
#endif /* GDT_SURVEYING */
}
#if !defined(VMS)
# ifndef HZ
# define HZ DEFAULT_HZ
# endif
# ifdef NLIST_STRUCT
# ifdef NLIST_NAME_UNION
# define NL_B {{
# define NL_E }}
# else
# define NL_B {
# define NL_E }
# endif
# endif
#define K_FILLER_NAME "DavidLetterman"
/*
* clock_parms - return the local clock tickadj and tick parameters
*
*/
static void
{
int got_tick = 0;
int got_tickadj = 0;
int hz = 0;
int got_hz = 0;
# ifdef SYS_WINNT
# else /* not SYS_WINNT */
int mib[2];
struct clockinfo c;
int rc;
# endif /* HAVE_SYSCTL && CTL_KERN && KERN_CLOCKRATE */
# ifndef NOKMEM
{
# ifdef K_TICKADJ_NAME
# define N_TICKADJ 0
# else
# endif /* K_TICKADJ_NAME */
NL_E,
# ifdef K_TICK_NAME
# define N_TICK 1
# else
# endif /* K_TICK_NAME */
NL_E,
};
# ifdef HAVE_K_OPEN
# else /* not HAVE_K_OPEN */
# ifdef HAVE_KVM_OPEN
# else /* not HAVE_KVM_OPEN */
register int i;
int kmem;
# ifdef HAVE_BOOTFILE
const char *kernelname;
# else /* not HAVE_BOOTFILE */
static char *kernelnames[] =
{
"/kernel",
"/vmunix",
"/unix",
"/mach",
"/hp-ux",
"/386bsd",
"/netbsd",
"/bsd",
# ifdef KERNELFILE
# endif
};
# endif /* not HAVE_BOOTFILE */
# endif /* not HAVE_KVM_OPEN */
# endif /* not HAVE_K_OPEN */
# endif /* not NOKMEM */
# endif /* not SYS_WINNT */
# ifdef SYS_WINNT
{
*ptick = 0;
*ptickadj = 0;
return;
}
# else /* not SYS_WINNT */
ci_len = sizeof(c);
if (rc == -1)
{
}
++got_tick;
# ifdef HAVE_TICKADJ_IN_STRUCT_CLOCKINFO
++got_tickadj;
# endif /* HAVE_TICKADJ_IN_STRUCT_CLOCKINFO */
# ifdef HAVE_HZ_IN_STRUCT_CLOCKINFO
++got_hz;
# endif /* HAVE_HZ_IN_STRUCT_CLOCKINFO */
# endif /* HAVE_SYSCTL && CTL_KERN && KERN_CLOCKRATE */
if (!got_hz)
{
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
# endif /* HAVE_SYSCONF && _SC_CLK_TCK */
# ifdef OVERRIDE_HZ
hz = DEFAULT_HZ;
# endif
++got_hz;
}
{
# ifndef NOKMEM
# ifdef HAVE_K_OPEN /* { */
{
exit(3);
}
kusenlist(1);
{
exit(3);
}
# else /* } not HAVE_K_OPEN { */
# ifdef HAVE_KVM_OPEN /* { */
{
exit(3);
}
{
exit(3);
}
# else /* } not HAVE_KVM_OPEN { */
# ifdef HAVE_GETBOOTFILE
kernelname = getbootfile();
if (!kernelname)
{
exit(3);
}
{
exit(3);
}
{
exit(3);
}
# else /* not HAVE_GETBOOTFILE */
for (i = 0; kernelnames[i] != NULL; i++)
{
continue;
break;
}
if (kernelnames[i] == NULL)
{
}
# endif /* not HAVE_GETBOOTFILE */
if (kmem < 0)
{
#ifdef DEBUG
if (debug)
#endif
}
# endif /* } not HAVE_KVM_OPEN */
# endif /* } not HAVE_K_OPEN */
# endif /* not NOKMEM */
}
# endif /* not SYS_WINNT */
/* Skippy says we need to know TICK before handling TICKADJ */
if (got_tick != 1)
{
# if defined(HAVE_SYS_TIMEX_H) && defined(HAVE___ADJTIMEX)
# endif /* HAVE_SYS_TIMEX_H && HAVE___ADJTIMEX */
# ifdef HAVE_K_OPEN
{
}
else
{
}
# else /* not HAVE_K_OPEN */
# ifdef HAVE_KVM_OPEN
sizeof(*ptick))
{
}
else
{
}
# else /* not HAVE_KVM_OPEN */
{
}
else
{
{
}
else
{
{
}
else
{
# ifdef NLIST_EXTRA_INDIRECTION
/*
* Aix requires one more round of indirection
* if storage class a pointer.
*/
{
{
}
else
{
sizeof(*ptick))
{
}
else
{
}
}
}
# else /* not NLIST_EXTRA_INDIRECTION */
# endif /* not NLIST_EXTRA_INDIRECTION */
}
}
}
# endif /* not HAVE_KVM_OPEN */
# endif /* not HAVE_K_OPEN */
# ifdef TICK_NANO
if (got_tick)
{
*ptick /= 1000;
}
# endif /* TICK_NANO */
# endif /* not NOKMEM && N_TICK */
if (!got_tick && default_tick)
{
*ptick = default_tick;
}
# ifdef PRESET_TICK
if (!got_tick)
{
# if defined(HAVE_SYS_TIMEX_H) && defined(HAVE___ADJTIMEX)
# ifdef MOD_OFFSET
# else
# endif
__adjtimex(&txc);
# endif /* HAVE_SYS_TIMEX_H && HAVE___ADJTIMEX */
}
# endif /* PRESET_TICK */
if (got_tick != 1)
{
exit(3);
}
}
/* Skippy says we need to know TICK before handling TICKADJ */
if (got_tickadj != 1)
{
{
}
else
{
# ifdef HAVE_K_OPEN
sizeof(*ptickadj))
{
}
else
{
if (*ptickadj) ++got_tickadj;
}
# else /* not HAVE_K_OPEN */
# ifdef HAVE_KVM_OPEN
sizeof(*ptickadj))
{
}
else
{
if (*ptickadj) ++got_tickadj;
}
# else /* not HAVE_KVM_OPEN */
{
}
else
{
{
}
else
{
sizeof(*ptickadj))
{
}
else
{
# ifdef NLIST_EXTRA_INDIRECTION
/*
* Aix requires one more round of indirection
* if storage class a pointer.
*/
{
{
}
else
{
sizeof(*ptickadj))
{
}
else
{
if (*ptickadj) ++got_tickadj;
}
}
}
# else /* not NLIST_EXTRA_INDIRECTION */
if (*ptickadj) ++got_tickadj;
# endif /* not NLIST_EXTRA_INDIRECTION */
}
}
}
# endif /* not HAVE_KVM_OPEN */
# endif /* not HAVE_K_OPEN */
}
# ifdef TICKADJ_NANO
if (got_tickadj)
{
*ptickadj /= 1000;
if (*ptickadj == 0)
{
*ptickadj = 1;
}
}
# endif /* TICKADJ_NANO */
# ifdef SCO5_TICKADJ
if (got_tickadj)
{
}
# else /* not SCO5_TICKADJ */
# ifdef SCO3_TICKADJ
if (got_tickadj)
{
}
# endif /* SCO3_TICKADJ */
# endif/* not SCO5_TICKADJ */
# endif /* not NOKMEM && N_TICKADJ */
if (!got_tickadj && default_tickadj)
{
if (*ptickadj) ++got_tickadj;
}
# ifdef PRESET_TICKADJ
if (!got_tickadj)
{
if (*ptickadj) ++got_tickadj;
}
# endif /* PRESET_TICKADJ */
if (got_tickadj != 1)
{
exit(3);
}
}
# ifndef NOKMEM
# ifdef HAVE_K_OPEN
(void) K_close();
# else /* not HAVE_K_OPEN */
# ifdef HAVE_KVM_OPEN
{
exit(3);
}
# else /* not HAVE_KVM_OPEN */
# endif /* not HAVE_KVM_OPEN */
# endif /* not HAVE_K_OPEN */
# endif /* not NOKMEM */
# ifdef DEBUG
if (debug)
# endif
}
#endif /* not VMS */