sys: add null driver

Add a new clock driver that doesn't actually try to adjust the clock.
It allows chronyd to run without the capability to adjust/set the system
clock, e.g. in some containers. It can be enabled by the -x option.
This commit is contained in:
Miroslav Lichvar 2017-03-09 18:16:56 +01:00
parent 0ff449e6a6
commit c44346096c
7 changed files with 202 additions and 5 deletions

View file

@ -37,7 +37,7 @@ HASH_OBJ = @HASH_OBJ@
OBJS = array.o cmdparse.o conf.o local.o logging.o main.o memory.o \
reference.o regress.o rtc.o sched.o sources.o sourcestats.o stubs.o \
sys.o smooth.o tempcomp.o util.o $(HASH_OBJ)
smooth.o sys.o sys_null.o tempcomp.o util.o $(HASH_OBJ)
EXTRA_OBJS=@EXTRA_OBJECTS@

View file

@ -151,6 +151,13 @@ support this option.
This option will lock *chronyd* into RAM so that it will never be paged out.
This mode is only supported on Linux.
*-x*::
This option disables the control of the system clock. *chronyd* will not make
any adjustments of the clock, but it will still track its offset and frequency
relative to the estimated true time, and be able to operate as an NTP server.
This allows *chronyd* to run without the capability to adjust or set the system
clock (e.g. in some containers).
*-v*::
With this option *chronyd* will print version number to the terminal and exit.

6
main.c
View file

@ -376,7 +376,7 @@ int main
int do_init_rtc = 0, restarted = 0, timeout = 0;
int other_pid;
int scfilter_level = 0, lock_memory = 0, sched_priority = 0;
int system_log = 1;
int clock_control = 1, system_log = 1;
int config_args = 0;
do_platform_checks();
@ -435,6 +435,8 @@ int main
++argv, --argc;
if (argc == 0 || sscanf(*argv, "%d", &timeout) != 1 || timeout <= 0)
LOG_FATAL("Bad timeout");
} else if (!strcmp("-x", *argv)) {
clock_control = 0;
} else if (!strcmp("-4", *argv)) {
address_family = IPADDR_INET4;
} else if (!strcmp("-6", *argv)) {
@ -499,7 +501,7 @@ int main
PRV_Initialise();
LCL_Initialise();
SCH_Initialise();
SYS_Initialise();
SYS_Initialise(clock_control);
RTC_Initialise(do_init_rtc);
SRC_Initialise();
RCL_Initialise();

16
sys.c
View file

@ -30,6 +30,7 @@
#include "sysincl.h"
#include "sys.h"
#include "sys_null.h"
#include "logging.h"
#if defined(LINUX)
@ -44,9 +45,18 @@
/* ================================================== */
static int null_driver;
/* ================================================== */
void
SYS_Initialise(void)
SYS_Initialise(int clock_control)
{
null_driver = !clock_control;
if (null_driver) {
SYS_Null_Initialise();
return;
}
#if defined(LINUX)
SYS_Linux_Initialise();
#elif defined(SOLARIS)
@ -65,6 +75,10 @@ SYS_Initialise(void)
void
SYS_Finalise(void)
{
if (null_driver) {
SYS_Null_Finalise();
return;
}
#if defined(LINUX)
SYS_Linux_Finalise();
#elif defined(SOLARIS)

2
sys.h
View file

@ -30,7 +30,7 @@
#define GOT_SYS_H
/* Called at the start of the run to do initialisation */
extern void SYS_Initialise(void);
extern void SYS_Initialise(int clock_control);
/* Called at the end of the run to do final clean-up */
extern void SYS_Finalise(void);

140
sys_null.c Normal file
View file

@ -0,0 +1,140 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2017
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Null clock driver for operation with no clock control.
*/
#include "config.h"
#include "sysincl.h"
#include "sys_null.h"
#include "local.h"
#include "localp.h"
#include "logging.h"
#include "util.h"
/* Current frequency offset of the system clock (in ppm) */
static double freq;
/* Offset of the system clock at the last update */
static double offset_register;
/* Time of the last update */
static struct timespec last_update;
/* Minimum interval between updates when frequency is constant */
#define MIN_UPDATE_INTERVAL 1000.0
/* ================================================== */
static void
update_offset(void)
{
struct timespec now;
double duration;
LCL_ReadRawTime(&now);
duration = UTI_DiffTimespecsToDouble(&now, &last_update);
offset_register += 1.0e-6 * freq * duration;
last_update = now;
DEBUG_LOG("System clock offset=%e freq=%f", offset_register, freq);
}
/* ================================================== */
static double
read_frequency(void)
{
return freq;
}
/* ================================================== */
static double
set_frequency(double freq_ppm)
{
update_offset();
freq = freq_ppm;
return freq;
}
/* ================================================== */
static void
accrue_offset(double offset, double corr_rate)
{
offset_register += offset;
}
/* ================================================== */
static int
apply_step_offset(double offset)
{
return 0;
}
/* ================================================== */
static void
offset_convert(struct timespec *raw, double *corr, double *err)
{
double duration;
duration = UTI_DiffTimespecsToDouble(raw, &last_update);
if (duration > MIN_UPDATE_INTERVAL) {
update_offset();
duration = 0.0;
}
*corr = -1.0e-6 * freq * duration - offset_register;
if (err)
*err = 0.0;
}
/* ================================================== */
void
SYS_Null_Initialise(void)
{
offset_register = 0.0;
LCL_ReadRawTime(&last_update);
lcl_RegisterSystemDrivers(read_frequency, set_frequency, accrue_offset,
apply_step_offset, offset_convert, NULL, NULL);
LOG(LOGS_INFO, "Disabled control of system clock");
}
/* ================================================== */
void
SYS_Null_Finalise(void)
{
}

34
sys_null.h Normal file
View file

@ -0,0 +1,34 @@
/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Miroslav Lichvar 2017
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Header file for null clock driver
*/
#ifndef GOT_SYS_NULL_H
#define GOT_SYS_NULL_H
extern void SYS_Null_Initialise(void);
extern void SYS_Null_Finalise(void);
#endif