Move clock_adjtime wrapping to clockadj.c.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
master
Miroslav Lichvar 2013-03-07 17:27:29 +01:00 committed by Richard Cochran
parent 58b1f3f37d
commit a29b1a4105
5 changed files with 134 additions and 106 deletions

55
clock.c
View File

@ -24,6 +24,7 @@
#include "bmc.h" #include "bmc.h"
#include "clock.h" #include "clock.h"
#include "clockadj.h"
#include "foreign.h" #include "foreign.h"
#include "mave.h" #include "mave.h"
#include "missing.h" #include "missing.h"
@ -404,52 +405,6 @@ static enum servo_state clock_no_adjust(struct clock *c)
return state; return state;
} }
static void clock_ppb(clockid_t clkid, double ppb)
{
struct timex tx;
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_FREQUENCY;
tx.freq = (long) (ppb * 65.536);
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to adjust the clock: %m");
}
static double clock_ppb_read(clockid_t clkid)
{
double f = 0.0;
struct timex tx;
memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to read out the clock frequency adjustment: %m");
else
f = tx.freq / 65.536;
return f;
}
static void clock_step(clockid_t clkid, int64_t ns)
{
struct timex tx;
int sign = 1;
if (ns < 0) {
sign = -1;
ns *= -1;
}
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_SETOFFSET | ADJ_NANO;
tx.time.tv_sec = sign * (ns / NS_PER_SEC);
tx.time.tv_usec = sign * (ns % NS_PER_SEC);
/*
* The value of a timeval is the sum of its fields, but the
* field tv_usec must always be non-negative.
*/
if (tx.time.tv_usec < 0) {
tx.time.tv_sec -= 1;
tx.time.tv_usec += 1000000000;
}
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to step clock: %m");
}
static void clock_update_grandmaster(struct clock *c) static void clock_update_grandmaster(struct clock *c)
{ {
struct parentDS *pds = &c->dad.pds; struct parentDS *pds = &c->dad.pds;
@ -580,7 +535,7 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
} }
if (c->clkid != CLOCK_INVALID) { if (c->clkid != CLOCK_INVALID) {
fadj = (int) clock_ppb_read(c->clkid); fadj = (int) clockadj_get_freq(c->clkid);
} }
c->servo = servo_create(servo, -fadj, max_adj, sw_ts); c->servo = servo_create(servo, -fadj, max_adj, sw_ts);
if (!c->servo) { if (!c->servo) {
@ -1035,13 +990,13 @@ enum servo_state clock_synchronize(struct clock *c,
case SERVO_UNLOCKED: case SERVO_UNLOCKED:
break; break;
case SERVO_JUMP: case SERVO_JUMP:
clock_ppb(c->clkid, -adj); clockadj_set_freq(c->clkid, -adj);
clock_step(c->clkid, -c->master_offset); clockadj_step(c->clkid, -c->master_offset);
c->t1 = tmv_zero(); c->t1 = tmv_zero();
c->t2 = tmv_zero(); c->t2 = tmv_zero();
break; break;
case SERVO_LOCKED: case SERVO_LOCKED:
clock_ppb(c->clkid, -adj); clockadj_set_freq(c->clkid, -adj);
break; break;
} }
return state; return state;

72
clockadj.c 100644
View File

@ -0,0 +1,72 @@
/**
* @file clockadj.c
* @note Copyright (C) 2013 Richard Cochran <richardcochran@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <string.h>
#include "clockadj.h"
#include "missing.h"
#include "print.h"
#define NS_PER_SEC 1000000000LL
void clockadj_set_freq(clockid_t clkid, double freq)
{
struct timex tx;
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_FREQUENCY;
tx.freq = (long) (freq * 65.536);
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to adjust the clock: %m");
}
double clockadj_get_freq(clockid_t clkid)
{
double f = 0.0;
struct timex tx;
memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to read out the clock frequency adjustment: %m");
else
f = tx.freq / 65.536;
return f;
}
void clockadj_step(clockid_t clkid, int64_t step)
{
struct timex tx;
int sign = 1;
if (step < 0) {
sign = -1;
step *= -1;
}
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_SETOFFSET | ADJ_NANO;
tx.time.tv_sec = sign * (step / NS_PER_SEC);
tx.time.tv_usec = sign * (step % NS_PER_SEC);
/*
* The value of a timeval is the sum of its fields, but the
* field tv_usec must always be non-negative.
*/
if (tx.time.tv_usec < 0) {
tx.time.tv_sec -= 1;
tx.time.tv_usec += 1000000000;
}
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to step clock: %m");
}

47
clockadj.h 100644
View File

@ -0,0 +1,47 @@
/**
* @file clockadj.h
* @brief Wraps clock_adjtime functionality.
* @note Copyright (C) 2013 Miroslav Lichvar <mlichvar@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef HAVE_CLOCKADJ_H
#define HAVE_CLOCKADJ_H
#include <inttypes.h>
#include <time.h>
/*
* Set clock's frequency offset.
* @param clkid A clock ID obtained using phc_open() or CLOCK_REALTIME.
* @param freq The frequency offset in parts per billion (ppb).
*/
void clockadj_set_freq(clockid_t clkid, double freq);
/*
* Read clock's frequency offset.
* @param clkid A clock ID obtained using phc_open() or CLOCK_REALTIME.
* @return The frequency offset in parts per billion (ppb).
*/
double clockadj_get_freq(clockid_t clkid);
/*
* Step clock's time.
* @param clkid A clock ID obtained using phc_open() or CLOCK_REALTIME.
* @param step The time step in nanoseconds.
*/
void clockadj_step(clockid_t clkid, int64_t step);
#endif

View File

@ -29,9 +29,9 @@ VER = -DVER=$(version)
CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS) CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS)
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS) LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
PRG = ptp4l pmc phc2sys hwstamp_ctl PRG = ptp4l pmc phc2sys hwstamp_ctl
OBJ = bmc.o clock.o config.o fsm.o ptp4l.o mave.o msg.o phc.o pi.o port.o \ OBJ = bmc.o clock.o clockadj.o config.o fsm.o ptp4l.o mave.o msg.o phc.o \
print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o \ pi.o port.o print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o \
uds.o util.o version.o udp.o udp6.o uds.o util.o version.o
OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o OBJECTS = $(OBJ) hwstamp_ctl.o phc2sys.o pmc.o pmc_common.o sysoff.o
SRC = $(OBJECTS:.o=.c) SRC = $(OBJECTS:.o=.c)
@ -52,8 +52,8 @@ ptp4l: $(OBJ)
pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \ pmc: msg.o pmc.o pmc_common.o print.o raw.o sk.o tlv.o transport.o udp.o \
udp6.o uds.o util.o version.o udp6.o uds.o util.o version.o
phc2sys: msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.o sk.o stats.o \ phc2sys: clockadj.o msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.o \
sysoff.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o sk.o stats.o sysoff.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o
hwstamp_ctl: hwstamp_ctl.o version.o hwstamp_ctl: hwstamp_ctl.o version.o

View File

@ -27,13 +27,13 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#include <inttypes.h> #include <inttypes.h>
#include <linux/pps.h> #include <linux/pps.h>
#include <linux/ptp_clock.h> #include <linux/ptp_clock.h>
#include "clockadj.h"
#include "ds.h" #include "ds.h"
#include "fsm.h" #include "fsm.h"
#include "missing.h" #include "missing.h"
@ -78,52 +78,6 @@ static clockid_t clock_open(char *device)
return FD_TO_CLOCKID(fd); return FD_TO_CLOCKID(fd);
} }
static void clock_ppb(clockid_t clkid, double ppb)
{
struct timex tx;
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_FREQUENCY;
tx.freq = (long) (ppb * 65.536);
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to adjust the clock: %m");
}
static double clock_ppb_read(clockid_t clkid)
{
double f = 0.0;
struct timex tx;
memset(&tx, 0, sizeof(tx));
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to read out the clock frequency adjustment: %m");
else
f = tx.freq / 65.536;
return f;
}
static void clock_step(clockid_t clkid, int64_t ns)
{
struct timex tx;
int sign = 1;
if (ns < 0) {
sign = -1;
ns *= -1;
}
memset(&tx, 0, sizeof(tx));
tx.modes = ADJ_SETOFFSET | ADJ_NANO;
tx.time.tv_sec = sign * (ns / NS_PER_SEC);
tx.time.tv_usec = sign * (ns % NS_PER_SEC);
/*
* The value of a timeval is the sum of its fields, but the
* field tv_usec must always be non-negative.
*/
if (tx.time.tv_usec < 0) {
tx.time.tv_sec -= 1;
tx.time.tv_usec += 1000000000;
}
if (clock_adjtime(clkid, &tx) < 0)
pr_err("failed to step clock: %m");
}
static int read_phc(clockid_t clkid, clockid_t sysclk, int readings, static int read_phc(clockid_t clkid, clockid_t sysclk, int readings,
int64_t *offset, uint64_t *ts, int64_t *delay) int64_t *offset, uint64_t *ts, int64_t *delay)
{ {
@ -224,10 +178,10 @@ static void update_clock(struct clock *clock,
case SERVO_UNLOCKED: case SERVO_UNLOCKED:
break; break;
case SERVO_JUMP: case SERVO_JUMP:
clock_step(clock->clkid, -offset); clockadj_step(clock->clkid, -offset);
/* Fall through. */ /* Fall through. */
case SERVO_LOCKED: case SERVO_LOCKED:
clock_ppb(clock->clkid, -ppb); clockadj_set_freq(clock->clkid, -ppb);
break; break;
} }
@ -669,10 +623,10 @@ int main(int argc, char *argv[])
close_pmc(&dst_clock); close_pmc(&dst_clock);
} }
ppb = clock_ppb_read(dst_clock.clkid); ppb = clockadj_get_freq(dst_clock.clkid);
/* The reading may silently fail and return 0, reset the frequency to /* The reading may silently fail and return 0, reset the frequency to
make sure ppb is the actual frequency of the clock. */ make sure ppb is the actual frequency of the clock. */
clock_ppb(dst_clock.clkid, ppb); clockadj_set_freq(dst_clock.clkid, ppb);
dst_clock.servo = servo_create(CLOCK_SERVO_PI, -ppb, max_ppb, 0); dst_clock.servo = servo_create(CLOCK_SERVO_PI, -ppb, max_ppb, 0);