On Sun, 27 Nov 2005, Robert Watson wrote:

 Add experimental low-precision clockid_t names corresponding to these
 clocks, but implemented using cached timestamps in kernel rather than
 a full time counter query.  This offers a minimum update rate of 1/HZ,
 but in practice will often be more frequent due to the frequency of
 time stamping in the kernel:

 New clockid_t name              Approximates existing clockid_t

 CLOCK_REALTIME_FAST             CLOCK_REALTIME
 CLOCK_MONOTONIC_FAST            CLOCK_MONOTONIC
 CLOCK_UPTIME_FAST               CLOCK_UPTIME

 Add one additional new clockid_t, CLOCK_SECOND, which returns the
 current second without performing a full time counter query or cache
 lookup overhead to make sure the cached timestamp is stable.  This is
 intended to support very low granularity consumers, such as time(3).

These changes are primarily intended to support the identification of time-associated bottlenecks and allow experimentation with application scoped reduction in quality of time use. Attached is a small LD_PRELOAD library to allow applications to be switched to the _FAST variants for gettimeofday(). Build and install, then set:

  LD_PRELOAD=/usr/lib/libwrapper.so ; export LD_PRELOAD

This is not intended to be the last word in how this should be done -- more, to facilitate some experimentation by providing some framework for experimentation (i.e., a sample API and code to tweak applications). I expect that the details will be subject to substantial change. :-)

Robert N M Watson
# $FreeBSD$

LIB=            wrapper
SHLIB_MAJOR=    1
SRCS=           wrapper.c

NO_MAN=

.include <bsd.lib.mk>
/*-
 * Copyright (c) 2005 Robert N. M. Watson
 * All rights reserved.
 *
 * 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.
 *
 * $FreeBSD$
 */

/*
 * Small wrapper library to substitute implementations of gettimeofday(2) and
 * time(3) with lower resolution variations.  time(3) is unconditionally
 * degraded, since it will return a truncated time anyway.  gettimeofday(3)
 * checks the TIMEWRAPPER environmental variable, which can be set to either
 * "PRECISE" or "FAST".
 */

#include <sys/time.h>

#include <stdlib.h>
#include <string.h>

static int              timewrapper_initialized;
static clockid_t        timewrapper_clock;

/*
 * Select whatever system default is present for CLOCK_REALTIME as the
 * default if the environmental variable is unset, or set to an invalid
 * value.
 */
#define TIMEWRAPPER_ENV         "TIMEWRAPPER"
#define TIMEWRAPPER_DEFAULT     CLOCK_REALTIME
#define TIMEWRAPPER_STRPRECISE  "PRECISE"
#define TIMEWRAPPER_STRFAST     "FAST"

static void
timewrapper_initialize(void)
{
        const char *whichclock_env;

        whichclock_env = getenv(TIMEWRAPPER_ENV);
        if (whichclock_env == NULL) {
                timewrapper_clock = TIMEWRAPPER_DEFAULT;
                timewrapper_initialized = 1;
                return;
        }

        if (strcmp(whichclock_env, TIMEWRAPPER_STRPRECISE) == 0)
                timewrapper_clock = CLOCK_REALTIME_PRECISE;
        else if (strcmp(whichclock_env, TIMEWRAPPER_STRFAST) == 0)
                timewrapper_clock = CLOCK_REALTIME_FAST;
        else
                timewrapper_clock = TIMEWRAPPER_DEFAULT;
        timewrapper_initialized = 1;
}

int
gettimeofday(struct timeval *tp, struct timezone *tzp)
{
        struct timespec ts;

        if (!timewrapper_initialized)
                timewrapper_initialize();

        /*
         * XXXRW: Not ideal, since returning EINVAL from gettimeofday() isn't
         * expected.  Fall back to the gettimeofday() system call instead?
         */
        if (clock_gettime(timewrapper_clock, &ts) < 0)
                return (-1);

        tp->tv_sec = ts.tv_sec;
        tp->tv_usec = ts.tv_nsec / 1000;

        return (0);
}

time_t
time(time_t *tloc)
{
        struct timespec ts;

        if (clock_gettime(CLOCK_SECOND, &ts) < 0) {
                if (tloc != NULL)
                        *tloc = -1;
                return (-1);
        }

        if (tloc != NULL)
                *tloc = ts.tv_sec;

        return (ts.tv_sec);
}
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to