From owner-svn-src-all@FreeBSD.ORG Sun Nov 20 01:20:51 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 574AE106564A; Sun, 20 Nov 2011 01:20:51 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 45AA98FC12; Sun, 20 Nov 2011 01:20:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id pAK1KpIR068701; Sun, 20 Nov 2011 01:20:51 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pAK1KphT068695; Sun, 20 Nov 2011 01:20:51 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <201111200120.pAK1KphT068695@svn.freebsd.org> From: Lawrence Stewart Date: Sun, 20 Nov 2011 01:20:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227745 - in head/sys: conf kern sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Nov 2011 01:20:51 -0000 Author: lstewart Date: Sun Nov 20 01:20:50 2011 New Revision: 227745 URL: http://svn.freebsd.org/changeset/base/227745 Log: Provide high-level functions to access the feed-forward absolute and difference clocks. Each routine can output an upper bound on the absolute time or time interval requested. Different flavours of absolute time can be requested, for example with or without leap seconds, monotonic or not, etc. Committed on behalf of Julien Ridoux and Darryl Veitch from the University of Melbourne, Australia, as part of the FreeBSD Foundation funded "Feed-Forward Clock Synchronization Algorithms" project. For more information, see http://www.synclab.org/radclock/ Submitted by: Julien Ridoux (jridoux at unimelb edu au) Added: head/sys/kern/kern_ffclock.c (contents, props changed) Modified: head/sys/conf/files head/sys/sys/timeffc.h Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Sun Nov 20 01:18:47 2011 (r227744) +++ head/sys/conf/files Sun Nov 20 01:20:50 2011 (r227745) @@ -2341,6 +2341,7 @@ kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fail.c standard +kern/kern_ffclock.c optional ffclock kern/kern_fork.c standard kern/kern_gzio.c optional gzio kern/kern_hhook.c standard Added: head/sys/kern/kern_ffclock.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/kern/kern_ffclock.c Sun Nov 20 01:20:50 2011 (r227745) @@ -0,0 +1,129 @@ +/*- + * Copyright (c) 2011 The University of Melbourne + * All rights reserved. + * + * This software was developed by Julien Ridoux at the University of Melbourne + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +extern struct ffclock_estimate ffclock_estimate; +extern struct bintime ffclock_boottime; + +/* + * Feed-forward clock absolute time. This should be the preferred way to read + * the feed-forward clock for "wall-clock" type time. The flags allow to compose + * various flavours of absolute time (e.g. with or without leap seconds taken + * into account). If valid pointers are provided, the ffcounter value and an + * upper bound on clock error associated with the bintime are provided. + * NOTE: use ffclock_convert_abs() to differ the conversion of a ffcounter value + * read earlier. + */ +void +ffclock_abstime(ffcounter *ffcount, struct bintime *bt, + struct bintime *error_bound, uint32_t flags) +{ + struct ffclock_estimate cest; + ffcounter ffc; + ffcounter update_ffcount; + ffcounter ffdelta_error; + + /* Get counter and corresponding time. */ + if ((flags & FFCLOCK_FAST) == FFCLOCK_FAST) + ffclock_last_tick(&ffc, bt, flags); + else { + ffclock_read_counter(&ffc); + ffclock_convert_abs(ffc, bt, flags); + } + + /* Current ffclock estimate, use update_ffcount as generation number. */ + do { + update_ffcount = ffclock_estimate.update_ffcount; + bcopy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); + } while (update_ffcount != ffclock_estimate.update_ffcount); + + /* + * Leap second adjustment. Total as seen by synchronisation algorithm + * since it started. cest.leapsec_next is the ffcounter prediction of + * when the next leapsecond occurs. + */ + if ((flags & FFCLOCK_LEAPSEC) == FFCLOCK_LEAPSEC) { + bt->sec -= cest.leapsec_total; + if (ffc > cest.leapsec_next) + bt->sec -= cest.leapsec; + } + + /* Boot time adjustment, for uptime/monotonic clocks. */ + if ((flags & FFCLOCK_UPTIME) == FFCLOCK_UPTIME) { + bintime_sub(bt, &ffclock_boottime); + } + + /* Compute error bound if a valid pointer has been passed. */ + if (error_bound) { + ffdelta_error = ffc - cest.update_ffcount; + ffclock_convert_diff(ffdelta_error, error_bound); + /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ + bintime_mul(error_bound, cest.errb_rate * + (uint64_t)18446744073709LL); + /* 18446744073 = int(2^64 / 1e9), since err_abs in [ns] */ + bintime_addx(error_bound, cest.errb_abs * + (uint64_t)18446744073LL); + } + + if (ffcount) + *ffcount = ffc; +} + +/* + * Feed-forward difference clock. This should be the preferred way to convert a + * time interval in ffcounter values into a time interval in seconds. If a valid + * pointer is passed, an upper bound on the error in computing the time interval + * in seconds is provided. + */ +void +ffclock_difftime(ffcounter ffdelta, struct bintime *bt, + struct bintime *error_bound) +{ + ffcounter update_ffcount; + uint32_t err_rate; + + ffclock_convert_diff(ffdelta, bt); + + if (error_bound) { + do { + update_ffcount = ffclock_estimate.update_ffcount; + err_rate = ffclock_estimate.errb_rate; + } while (update_ffcount != ffclock_estimate.update_ffcount); + + ffclock_convert_diff(ffdelta, error_bound); + /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ + bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL); + } +} Modified: head/sys/sys/timeffc.h ============================================================================== --- head/sys/sys/timeffc.h Sun Nov 20 01:18:47 2011 (r227744) +++ head/sys/sys/timeffc.h Sun Nov 20 01:20:50 2011 (r227745) @@ -105,6 +105,29 @@ void ffclock_last_tick(ffcounter *ffcoun void ffclock_convert_abs(ffcounter ffcount, struct bintime *bt, uint32_t flags); void ffclock_convert_diff(ffcounter ffdelta, struct bintime *bt); +/* + * Feed-forward clock routines. + * + * These functions rely on the timecounters and ffclock_estimates stored in + * fftimehands. Note that the error_bound parameter is not the error of the + * clock but an upper bound on the error of the absolute time or time interval + * returned. + * + * ffclock_abstime(): retrieves current time as counter value and convert this + * timestamp in seconds. The value (in seconds) of the converted timestamp + * depends on the flags passed: for a given counter value, different + * conversions are possible. Different clock models can be selected by + * combining flags (for example (FFCLOCK_LERP|FFCLOCK_UPTIME) produces + * linearly interpolated uptime). + * ffclock_difftime(): computes a time interval in seconds based on an interval + * measured in ffcounter units. This should be the preferred way to measure + * small time intervals very accurately. + */ +void ffclock_abstime(ffcounter *ffcount, struct bintime *bt, + struct bintime *error_bound, uint32_t flags); +void ffclock_difftime(ffcounter ffdelta, struct bintime *bt, + struct bintime *error_bound); + #endif /* _KERNEL */ #endif /* __BSD_VISIBLE */ #endif /* _SYS_TIMEFF_H_ */