Skip to content

Commit

Permalink
Move clock_adjtime wrapping to clockadj.c.
Browse files Browse the repository at this point in the history
Signed-off-by: Miroslav Lichvar <[email protected]>
  • Loading branch information
mlichvar authored and richardcochran committed Mar 20, 2013
1 parent 58b1f3f commit a29b1a4
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 106 deletions.
55 changes: 5 additions & 50 deletions clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "bmc.h"
#include "clock.h"
#include "clockadj.h"
#include "foreign.h"
#include "mave.h"
#include "missing.h"
Expand Down Expand Up @@ -404,52 +405,6 @@ static enum servo_state clock_no_adjust(struct clock *c)
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)
{
struct parentDS *pds = &c->dad.pds;
Expand Down Expand Up @@ -580,7 +535,7 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count,
}

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);
if (!c->servo) {
Expand Down Expand Up @@ -1035,13 +990,13 @@ enum servo_state clock_synchronize(struct clock *c,
case SERVO_UNLOCKED:
break;
case SERVO_JUMP:
clock_ppb(c->clkid, -adj);
clock_step(c->clkid, -c->master_offset);
clockadj_set_freq(c->clkid, -adj);
clockadj_step(c->clkid, -c->master_offset);
c->t1 = tmv_zero();
c->t2 = tmv_zero();
break;
case SERVO_LOCKED:
clock_ppb(c->clkid, -adj);
clockadj_set_freq(c->clkid, -adj);
break;
}
return state;
Expand Down
72 changes: 72 additions & 0 deletions clockadj.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* @file clockadj.c
* @note Copyright (C) 2013 Richard Cochran <[email protected]>
*
* 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 changes: 47 additions & 0 deletions clockadj.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @file clockadj.h
* @brief Wraps clock_adjtime functionality.
* @note Copyright (C) 2013 Miroslav Lichvar <[email protected]>
*
* 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
10 changes: 5 additions & 5 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ VER = -DVER=$(version)
CFLAGS = -Wall $(VER) $(INC) $(DEBUG) $(FEAT_CFLAGS) $(EXTRA_CFLAGS)
LDLIBS = -lm -lrt $(EXTRA_LDFLAGS)
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 \
print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.o udp.o udp6.o \
uds.o util.o version.o
OBJ = bmc.o clock.o clockadj.o config.o fsm.o ptp4l.o mave.o msg.o phc.o \
pi.o port.o print.o raw.o servo.o sk.o stats.o tlv.o tmtab.o transport.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
SRC = $(OBJECTS:.o=.c)
Expand All @@ -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 \
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 \
sysoff.o tlv.o transport.o udp.o udp6.o uds.o util.o version.o
phc2sys: clockadj.o msg.o phc2sys.o pmc_common.o print.o pi.o servo.o raw.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

Expand Down
56 changes: 5 additions & 51 deletions phc2sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <inttypes.h>

#include <linux/pps.h>
#include <linux/ptp_clock.h>

#include "clockadj.h"
#include "ds.h"
#include "fsm.h"
#include "missing.h"
Expand Down Expand Up @@ -78,52 +78,6 @@ static clockid_t clock_open(char *device)
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,
int64_t *offset, uint64_t *ts, int64_t *delay)
{
Expand Down Expand Up @@ -224,10 +178,10 @@ static void update_clock(struct clock *clock,
case SERVO_UNLOCKED:
break;
case SERVO_JUMP:
clock_step(clock->clkid, -offset);
clockadj_step(clock->clkid, -offset);
/* Fall through. */
case SERVO_LOCKED:
clock_ppb(clock->clkid, -ppb);
clockadj_set_freq(clock->clkid, -ppb);
break;
}

Expand Down Expand Up @@ -669,10 +623,10 @@ int main(int argc, char *argv[])
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
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);

Expand Down

0 comments on commit a29b1a4

Please sign in to comment.