summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/sandglass.c159
-rw-r--r--src/sandglass.h80
-rw-r--r--src/sandglass_impl.h8
-rw-r--r--src/tsc.c2
-rw-r--r--tests/introspective-cputime.c5
-rw-r--r--tests/introspective-system.c5
-rw-r--r--tests/monotonic-cputime.c5
-rw-r--r--tests/monotonic-realticks.c3
-rw-r--r--tests/monotonic-system.c5
-rw-r--r--tests/noprecache.c5
10 files changed, 94 insertions, 183 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 */
diff --git a/src/tsc.c b/src/tsc.c
index 135cd2a..713008c 100644
--- a/src/tsc.c
+++ b/src/tsc.c
@@ -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 };
diff --git a/tests/introspective-cputime.c b/tests/introspective-cputime.c
index 7ce9a36..3f4158e 100644
--- a/tests/introspective-cputime.c
+++ b/tests/introspective-cputime.c
@@ -29,17 +29,16 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_INTROSPECTIVE, SANDGLASS_CPUTIME };
struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 111111111L };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_introspective(&sandglass, SANDGLASS_CPUTIME) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
sandglass_bench(&sandglass, sandglass_spin(&tosleep));
- printf("%.15g\n", sandglass.grains/sandglass.resolution);
+ printf("%.15g\n", sandglass.grains/sandglass.freq);
return EXIT_SUCCESS;
}
diff --git a/tests/introspective-system.c b/tests/introspective-system.c
index 81e3397..5dee23a 100644
--- a/tests/introspective-system.c
+++ b/tests/introspective-system.c
@@ -29,17 +29,16 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_INTROSPECTIVE, SANDGLASS_SYSTEM };
struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 111111111L };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_introspective(&sandglass, SANDGLASS_SYSTEM) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
sandglass_bench(&sandglass, sandglass_spin(&tosleep));
- printf("%.15g\n", sandglass.grains/sandglass.resolution);
+ printf("%.15g\n", sandglass.grains/sandglass.freq);
return EXIT_SUCCESS;
}
diff --git a/tests/monotonic-cputime.c b/tests/monotonic-cputime.c
index d0a7de1..f034df3 100644
--- a/tests/monotonic-cputime.c
+++ b/tests/monotonic-cputime.c
@@ -29,17 +29,16 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_CPUTIME };
struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 111111111L };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_monotonic(&sandglass, SANDGLASS_CPUTIME) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
sandglass_bench(&sandglass, sandglass_spin(&tosleep));
- printf("%.15g\n", sandglass.grains/sandglass.resolution);
+ printf("%.15g\n", sandglass.grains/sandglass.freq);
return EXIT_SUCCESS;
}
diff --git a/tests/monotonic-realticks.c b/tests/monotonic-realticks.c
index 51404f5..5fff86e 100644
--- a/tests/monotonic-realticks.c
+++ b/tests/monotonic-realticks.c
@@ -30,9 +30,8 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_CPUTIME };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_monotonic(&sandglass, SANDGLASS_CPUTIME) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
diff --git a/tests/monotonic-system.c b/tests/monotonic-system.c
index 0774908..d8ffba9 100644
--- a/tests/monotonic-system.c
+++ b/tests/monotonic-system.c
@@ -29,17 +29,16 @@ int
main()
{
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_SYSTEM };
struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 111111111L };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_monotonic(&sandglass, SANDGLASS_SYSTEM) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
sandglass_bench(&sandglass, sandglass_spin(&tosleep));
- printf("%.15g\n", sandglass.grains/sandglass.resolution);
+ printf("%.15g\n", sandglass.grains/sandglass.freq);
return EXIT_SUCCESS;
}
diff --git a/tests/noprecache.c b/tests/noprecache.c
index 071920d..e48929d 100644
--- a/tests/noprecache.c
+++ b/tests/noprecache.c
@@ -31,10 +31,9 @@ main()
{
int i = 0;
sandglass_t sandglass;
- sandglass_attributes_t attr = { SANDGLASS_MONOTONIC, SANDGLASS_CPUTIME };
struct timespec tosleep = { .tv_sec = 0, .tv_nsec = 111111111L };
- if (sandglass_create(&sandglass, &attr, &attr) != 0) {
+ if (sandglass_init_monotonic(&sandglass, SANDGLASS_SYSTEM) != 0) {
perror("sandglass_create()");
return EXIT_FAILURE;
}
@@ -49,7 +48,7 @@ main()
"sandglass_bench_noprecache() evaluated routine %d times!\n", i);
}
- printf("%.15g\n", sandglass.grains/sandglass.resolution);
+ printf("%.15g\n", sandglass.grains/sandglass.freq);
return EXIT_SUCCESS;
}