diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/sandglass.c | 159 | ||||
-rw-r--r-- | src/sandglass.h | 80 | ||||
-rw-r--r-- | src/sandglass_impl.h | 8 | ||||
-rw-r--r-- | src/tsc.c | 2 |
4 files changed, 83 insertions, 166 deletions
diff --git a/src/sandglass.c b/src/sandglass.c index 6a492c3..7ffe511 100644 --- a/src/sandglass.c +++ b/src/sandglass.c @@ -24,130 +24,61 @@ #include <time.h> #include <errno.h> -static int sandglass_real_create(sandglass_t *sandglass, - const sandglass_attributes_t *attr); - -/* Create a timer */ int -sandglass_create(sandglass_t *sandglass, - const sandglass_attributes_t *min, - const sandglass_attributes_t *max) +sandglass_init_introspective(sandglass_t *sandglass, sandglass_resolution_t res) { - sandglass_attributes_t realmin, realmax; - - /* Get our real min and max values */ - - if (min) - realmin = *min; - else { - /* min defaults to { SANDGLASS_INTROSPECTIVE, SANDGLASS_SYSTEM } */ - realmin.incrementation = SANDGLASS_INTROSPECTIVE; - realmin.resolution = SANDGLASS_SYSTEM; - } - - if (max) - realmax = *max; - else { - /* max defaults to the greater of min and { SANDGLASS_INTROSPECTIVE, - SANDGLASS_CPUTIME } */ - if (realmin.incrementation > SANDGLASS_INTROSPECTIVE - || (realmin.incrementation == SANDGLASS_INTROSPECTIVE - && realmin.resolution > SANDGLASS_CPUTIME)) - realmax = realmin; - else { - realmax.incrementation = SANDGLASS_INTROSPECTIVE; - realmax.resolution = SANDGLASS_CPUTIME; - } - } - - /* Ensure max >= min */ - if (realmax.incrementation < realmin.incrementation - || (realmax.incrementation == realmin.incrementation - && realmax.resolution < realmin.resolution)) - { - errno = EINVAL; - return -1; - } - - /* Now search for available timers, starting from max */ - - while (sandglass_real_create(sandglass, &realmax) != 0) { - /* Once we reach the minimum attributes, bail out */ - if (realmax.incrementation == realmin.incrementation - && realmax.resolution == realmin.resolution) - { + switch (res) { + case SANDGLASS_CPUTIME: + if (sysconf(_SC_THREAD_CPUTIME) > 0 || sysconf(_SC_CPUTIME) > 0) { + sandglass->freq = 1e9; + sandglass->loops = 1; + } else { errno = ENOTSUP; return -1; } + break; - /* Try the next lowest allowable settings */ - if (realmax.resolution) - --realmax.resolution; - else { - if (realmax.incrementation) { - --realmax.incrementation; - realmax.resolution = SANDGLASS_CPUTIME; - } else { - errno = ENOTSUP; - return -1; - } - } + case SANDGLASS_SYSTEM: + sandglass->freq = CLOCKS_PER_SEC; + sandglass->loops = 1; + break; + + default: + errno = EINVAL; + return -1; } + sandglass->incrementation = SANDGLASS_INTROSPECTIVE; + sandglass->resolution = res; return 0; } -static int -sandglass_real_create(sandglass_t *sandglass, - const sandglass_attributes_t *attr) +int +sandglass_init_monotonic(sandglass_t *sandglass, sandglass_resolution_t res) { - switch (attr->incrementation) { - case SANDGLASS_MONOTONIC: - switch (attr->resolution) { - case SANDGLASS_CPUTIME: + switch (res) { + case SANDGLASS_CPUTIME: #ifdef SANDGLASS_TSC - sandglass->resolution = sandglass_tsc_resolution(); - sandglass->loops = sandglass_tsc_loops(); - break; + sandglass->freq = sandglass_tsc_freq(); + sandglass->loops = sandglass_tsc_loops(); + break; #else - return -1; + errno = ENOTSUP; + return -1; #endif - case SANDGLASS_SYSTEM: - sandglass->resolution = 1e9; - sandglass->loops = 1; - break; + case SANDGLASS_SYSTEM: + sandglass->freq = 1e9; + sandglass->loops = 1; + break; - default: - return -1; - } - break; - - case SANDGLASS_INTROSPECTIVE: - switch (attr->resolution) { - case SANDGLASS_CPUTIME: - if (sysconf(_SC_THREAD_CPUTIME) > 0 || sysconf(_SC_CPUTIME) > 0) { - sandglass->resolution = 1e9; - sandglass->loops = 1; - } else - return -1; - break; - - case SANDGLASS_SYSTEM: - sandglass->resolution = CLOCKS_PER_SEC; - sandglass->loops = 1; - break; - - default: - return -1; - } - break; - - default: - return -1; + default: + errno = EINVAL; + return -1; } - sandglass->attributes = *attr; + sandglass->incrementation = SANDGLASS_MONOTONIC; + sandglass->resolution = res; return 0; } @@ -167,7 +98,7 @@ sandglass_elapse(sandglass_t *sandglass) { long oldgrains = sandglass->grains; - if (sandglass_real_gettime(sandglass) != 0) + if (sandglass_real_gettime(sandglass)) return -1; sandglass->grains -= oldgrains; @@ -185,14 +116,15 @@ sandglass_real_gettime(sandglass_t *sandglass) struct timespec ts; clock_t clock_ticks; - switch (sandglass->attributes.incrementation) { + switch (sandglass->incrementation) { case SANDGLASS_MONOTONIC: - switch (sandglass->attributes.resolution) { + switch (sandglass->resolution) { case SANDGLASS_CPUTIME: #ifdef SANDGLASS_TSC sandglass->grains = sandglass_get_tsc(); break; #else + errno = ENOTSUP; return -1; #endif @@ -209,12 +141,13 @@ sandglass_real_gettime(sandglass_t *sandglass) break; default: + errno = EINVAL; return -1; } break; case SANDGLASS_INTROSPECTIVE: - switch (sandglass->attributes.resolution) { + switch (sandglass->resolution) { case SANDGLASS_CPUTIME: if (sysconf(_SC_THREAD_CPUTIME) > 0) { if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) @@ -222,8 +155,10 @@ sandglass_real_gettime(sandglass_t *sandglass) } else if (sysconf(_SC_CPUTIME) > 0) { if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != 0) return -1; - } else + } else { + errno = EINVAL; return -1; + } sandglass->grains = ts.tv_nsec; sandglass->adjustment = 1000000000L; break; @@ -231,15 +166,17 @@ sandglass_real_gettime(sandglass_t *sandglass) case SANDGLASS_SYSTEM: if ((clock_ticks = clock()) == -1) return -1; - sandglass->grains = clock(); + sandglass->grains = clock_ticks; break; default: + errno = EINVAL; return -1; } break; default: + errno = EINVAL; return -1; } diff --git a/src/sandglass.h b/src/sandglass.h index 7b7577b..5456391 100644 --- a/src/sandglass.h +++ b/src/sandglass.h @@ -31,8 +31,24 @@ extern "C" { #endif -/* A type to represent a clock's time measurement attributes */ -enum sandglass_incrementation_t +/* A type to represent a clock's timing resolution */ +typedef enum sandglass_resolution_t +{ + /* + * Rely on the kernel to provide time information; less precise, more + * portable + */ + SANDGLASS_SYSTEM, + + /* + * Get timing information directly from the processor; more precise, less + * portable + */ + SANDGLASS_CPUTIME +} sandglass_resolution_t; + +/* An internal type to represent a clock's time measurement attributes */ +typedef enum sandglass_incrementation_t { /* * A clock which only increments during the current process's execution. Less @@ -48,45 +64,20 @@ enum sandglass_incrementation_t * while being timed. */ SANDGLASS_MONOTONIC -}; -typedef enum sandglass_incrementation_t sandglass_incrementation_t; - -/* A type to represent a clock's timing resolution */ -enum sandglass_resolution_t -{ - /* - * Rely on the kernel to provide time information; less precise, more - * portable. Uses times(). - */ - SANDGLASS_SYSTEM, +} sandglass_incrementation_t; - /* - * Get timing information directly from the processor; more precise, less - * portable. Uses the CLOCK_THREAD_CPUTIME_ID clock for - * SANDGLASS_INTROSPECTIVE mode, and the raw TSC for SANDGLASS_MONOTONIC. - */ - SANDGLASS_CPUTIME -}; -typedef enum sandglass_resolution_t sandglass_resolution_t; - -/* Attributes of a clock */ -struct sandglass_attributes_t +/* An high resolution timer */ +typedef struct sandglass_t { + /* The attributes of the clock */ sandglass_incrementation_t incrementation; sandglass_resolution_t resolution; -}; -typedef struct sandglass_attributes_t sandglass_attributes_t; - -struct sandglass_t -{ - /* The attributes of the clock */ - sandglass_attributes_t attributes; /* Units of time which have passed */ long grains; - /* grains/resolution should give elapsed time in seconds */ - double resolution; + /* grains/freq should give elapsed time in seconds */ + double freq; /* * Internal fields @@ -101,24 +92,13 @@ struct sandglass_t /* A field used by sandglass_bench() to store the overhead of sandglass_begin()/_elapse(), and of looping */ long baseline; -}; -typedef struct sandglass_t sandglass_t; +} sandglass_t; -/* - * Creates a timer with at least the precision of `min', and at most the - * precision of `max'. Precisions are compared first by incrementation type: - * all monotonic timers are considered more precise than introspective timers. - * Then, higher resolution timers take precidence. - * - * If `min' is NULL, it defaults to { SANDGLASS_INTROSPECTIVE, - * SANDGLASS_SYSTEM }. - * - * If `max' is NULL, it defaults to at least `min', but not less than - * { SANDGLASS_INTROSPECTIVE, SANDGLASS_CPUTIME }. - */ -int sandglass_create(sandglass_t *sandglass, - const sandglass_attributes_t *min, - const sandglass_attributes_t *max); +/* Create a timer */ +int sandglass_init_introspective(sandglass_t *sandglass, + sandglass_resolution_t res); +int sandglass_init_monotonic(sandglass_t *sandglass, + sandglass_resolution_t res); int sandglass_begin(sandglass_t *sandglass); int sandglass_elapse(sandglass_t *sandglass); diff --git a/src/sandglass_impl.h b/src/sandglass_impl.h index 689c6bf..accb332 100644 --- a/src/sandglass_impl.h +++ b/src/sandglass_impl.h @@ -31,9 +31,9 @@ #ifdef SANDGLASS_TSC /* Read the time stamp counter */ long sandglass_get_tsc(); -/* Get the timing resolution of the TSC */ -double sandglass_tsc_resolution(); -/* Get the necessary number of loops for SANDGLASS_REALTICKS */ +/* Get the frequency of the TSC */ +double sandglass_tsc_freq(); +/* Get the necessary number of loops for sandglass_bench_fine() */ unsigned int sandglass_tsc_loops(); #endif @@ -43,4 +43,4 @@ 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(const struct timespec *ts); -#endif /* SANDGLASS_IMPL_H_INCLUDED */
\ No newline at end of file +#endif /* SANDGLASS_IMPL_H_INCLUDED */ @@ -25,7 +25,7 @@ /* Gets the number of clock ticks per second */ double -sandglass_tsc_resolution() +sandglass_tsc_freq() { static long tsc = 0; static struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000L }; |