/*- * Copyright (c) 2008 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "/zoo/kris/contention/dev/evilmem/evilmem.h" /* * 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". */ 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 struct evilmem *evilm; static void timewrapper_initialize(void) { const char *whichclock_env; int em_fd; #if 0 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; #endif timewrapper_clock = CLOCK_REALTIME_FAST; timewrapper_initialized = 1; em_fd = open("/dev/evilmem", O_RDONLY); if (em_fd < 0) err(-1, "open: evilmem"); /* XXXRW: Should have an ioctl to request page size for evilmem. */ evilm = mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED, em_fd, 0); if (evilm == MAP_FAILED) err(-1, "mmap"); close(em_fd); } 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 (evil_gettime(&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); } int evil_gettime(struct timespec *ts) { int em_generation_before, em_generation_after; if (evilm->em_magic != EVILMEM_MAGIC) errx(-1, "evilmem magic"); do { em_generation_before = evilm->em_generation_before; ts->tv_sec = evilm->em_time.tv_sec; ts->tv_nsec = evilm->em_time.tv_nsec; em_generation_after = evilm->em_generation_after; } while (em_generation_before != em_generation_after); return(0); } #if 0 em_ts = evilm->em_time; if (clock_gettime(CLOCK_REALTIME, &syscall_ts) < 0) err(-1, "clock_gettime"); printf("evilmem: %jd.%08jd\n", (intmax_t)em_ts.tv_sec, (intmax_t)em_ts.tv_nsec); printf("syscall: %jd.%08jd\n", (intmax_t)syscall_ts.tv_sec, (intmax_t)syscall_ts.tv_nsec); return (0); } #endif