From e2fa7956b87c23a8229926f39a3863ecd4d4752a Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Fri, 18 Sep 2009 19:47:51 +0000 Subject: Add timespec helper routines. --- configure.ac | 11 +++-- src/Makefile.am | 6 ++- src/sandglass_impl.h | 6 +++ src/timespec.c | 109 +++++++++++++++++++++++++++++++++++++++++++ src/tsc.c | 34 ++------------ tests/introspective-system.c | 21 ++++----- 6 files changed, 141 insertions(+), 46 deletions(-) create mode 100644 src/timespec.c diff --git a/configure.ac b/configure.ac index deea2b8..c767daa 100644 --- a/configure.ac +++ b/configure.ac @@ -41,19 +41,22 @@ AC_CANONICAL_HOST if echo $host_cpu | grep '86$' 2>&1 >/dev/null then - arch_x86="true" - AC_DEFINE([SANDGLASS_TSC]) + arch_x86=1 + tsc=1 fi if echo $host_cpu | grep 'x86_64$' 2>&1 >/dev/null then - arch_x86_64="true" - AC_DEFINE([SANDGLASS_TSC]) + arch_x86_64=1 + tsc=1 fi AM_CONDITIONAL([X86], [test "$arch_x86"]) AM_CONDITIONAL([X86_64], [test "$arch_x86_64"]) +AC_DEFINE([SANDGLASS_TSC], ["$tsc"]) +AM_CONDITIONAL([TSC], [test "$tsc"]) + dnl Generate Makefiles AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_FILES([Makefile diff --git a/src/Makefile.am b/src/Makefile.am index d1a0109..a91e2b6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,11 @@ nobase_include_HEADERS = sandglass.h libsandglass_la_SOURCES = sandglass.h \ sandglass_impl.h \ sandglass.c \ - tsc.c + timespec.c + +if TSC + libsandglass_la_SOURCES += tsc.c +endif if X86 libsandglass_la_SOURCES += x86/tsc-x86.s diff --git a/src/sandglass_impl.h b/src/sandglass_impl.h index cea95c3..07a3616 100644 --- a/src/sandglass_impl.h +++ b/src/sandglass_impl.h @@ -37,4 +37,10 @@ double sandglass_tsc_resolution(); unsigned int sandglass_tsc_loops(); #endif +void sandglass_get_currtime(struct timespec *ts); +void sandglass_timespec_add(struct timespec *ts, const struct timespec *d); +void sandglass_timespec_sub(struct timespec *ts, const struct timespec *d); +int sandglass_timespec_cmp(const struct timespec *a, const struct timespec *b); +void sandglass_spin(struct timespec *ts); + #endif /* SANDGLASS_IMPL_H_INCLUDED */ \ No newline at end of file diff --git a/src/timespec.c b/src/timespec.c new file mode 100644 index 0000000..f8ab791 --- /dev/null +++ b/src/timespec.c @@ -0,0 +1,109 @@ +/************************************************************************* + * Copyright (C) 2008 Tavian Barnes * + * * + * This file is part of The Sandglass Library. * + * * + * The Sandglass Library is free software; you can redistribute it * + * and/or modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either version * + * 3 of the License, or (at your option) any later version. * + * * + * The Sandglass Library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * . * + *************************************************************************/ + +#include "sandglass_impl.h" +#include "sandglass.h" +#include +#include +#include +#include + +void +sandglass_get_currtime(struct timespec *ts) +{ + static int monotonic = 0; + if (!monotonic) { + monotonic = sysconf(_SC_MONOTONIC_CLOCK); + } + + if (monotonic > 0) { + if (clock_gettime(CLOCK_MONOTONIC, ts) != 0) { + fprintf(stderr, + "libsandglass: couldn't get value of clock CLOCK_MONOTONIC\n"); + exit(EXIT_FAILURE); + } + } else { + if (clock_gettime(CLOCK_REALTIME, ts) != 0) { + fprintf(stderr, + "libsandglass: couldn't get value of clock CLOCK_REALTIME\n"); + exit(EXIT_FAILURE); + } + } +} + +void +sandglass_timespec_add(struct timespec *ts, const struct timespec *d) +{ + if (d->tv_nsec >= 1000000000L - ts->tv_nsec) { + ts->tv_nsec += d->tv_nsec - 1000000000L; + ++ts->tv_sec; + } else { + ts->tv_nsec += d->tv_nsec; + } + ts->tv_sec += d->tv_sec; +} + +void +sandglass_timespec_sub(struct timespec *ts, const struct timespec *d) +{ + if (d->tv_nsec > ts->tv_nsec) { + ts->tv_nsec -= d->tv_nsec - 1000000000L; + --ts->tv_sec; + } else { + ts->tv_nsec -= d->tv_nsec; + } + ts->tv_sec -= d->tv_sec; +} + +int +sandglass_timespec_cmp(const struct timespec *a, const struct timespec *b) +{ + if (a->tv_sec > b->tv_sec) + return 1; + else if (a->tv_sec == b->tv_sec) { + if (a->tv_nsec > b->tv_nsec) + return 1; + else if (a->tv_nsec == b->tv_nsec) + return 0; + else + return -1; + } + else + return -1; +} + +/* Spins for the time interval specified by ts */ +void +sandglass_spin(struct timespec *ts) +{ + struct timespec curr, until; + sandglass_get_currtime(&curr); + until = curr; + sandglass_timespec_add(&until, ts); + + /* Spin */ + do { + sandglass_get_currtime(&curr); + } while (sandglass_timespec_cmp(&curr, &until) < 0); + + /* Adjust ts to the time actually waited */ + sandglass_timespec_sub(&curr, &until); + sandglass_timespec_add(ts, &curr); +} diff --git a/src/tsc.c b/src/tsc.c index 28066a4..554a6d8 100644 --- a/src/tsc.c +++ b/src/tsc.c @@ -27,40 +27,14 @@ double sandglass_tsc_resolution() { - static long tsc = 0, grains1, grains2; - - int monotonic; - struct timespec ts; + static long tsc = 0; + static struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000L }; if (tsc == 0) { - monotonic = sysconf(_SC_MONOTONIC_CLOCK) > 0; - if (monotonic) { - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - return 0.0/0.0; - } else { - if (clock_gettime(CLOCK_REALTIME, &ts) != 0) - return 0.0/0.0; - } tsc = sandglass_get_tsc(); - grains1 = sandglass_timespec_grains(&ts); - grains2 = grains1; - - while (((grains2 >= grains1) ? grains2 - grains1 - : 1000000000L + (grains2 - grains1)) - < 10000000L) - { - if (monotonic) { - if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) - return 0.0/0.0; - } else { - if (clock_gettime(CLOCK_REALTIME, &ts) != 0) - return 0.0/0.0; - } - grains2 = ts.tv_nsec; - } - + sandglass_spin(&ts); tsc = sandglass_get_tsc() - tsc; } - return tsc*1.0e9/(grains2 - grains1); + return tsc*1.0e9/ts.tv_nsec; } diff --git a/tests/introspective-system.c b/tests/introspective-system.c index 8366623..21ffa4c 100644 --- a/tests/introspective-system.c +++ b/tests/introspective-system.c @@ -18,7 +18,8 @@ * . * *************************************************************************/ -#include +#include "../src/sandglass_impl.h" +#include "../src/sandglass.h" #include #include #include @@ -29,22 +30,20 @@ main() { sandglass_t sandglass; sandglass_attributes_t attr = { SANDGLASS_INTROSPECTIVE, SANDGLASS_SYSTEM }; - struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 100000000 }; + struct timespec tosleep; if (sandglass_create(&sandglass, &attr, &attr) != 0) { perror("sandglass_create()"); return EXIT_FAILURE; } - if (sandglass_begin(&sandglass) != 0) { - perror("sandglass_begin()"); - return EXIT_FAILURE; - } - while (nanosleep(&tosleep, &tosleep) != 0); - if (sandglass_elapse(&sandglass) != 0) { - perror("sandglass_elapse()"); - return EXIT_FAILURE; - } + sandglass_bench(&sandglass, { + tosleep.tv_sec = 0; + tosleep.tv_nsec = 100000000L; + sandglass_spin(&tosleep); + }); + + printf("%g\n", sandglass.grains/sandglass.resolution); return EXIT_SUCCESS; } -- cgit v1.2.3