-
Notifications
You must be signed in to change notification settings - Fork 4
/
Timer.h
142 lines (117 loc) · 3.09 KB
/
Timer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once
/*
Timer.h
Part of the GGC source code.
Copyright (C) 2014--2016, The University of Texas at Austin
See LICENSE.TXT for copyright license.
Author: Sreepathi Pai <[email protected]>
*/
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <stdio.h>
#if !(_POSIX_TIMERS > 0)
#error "POSIX timers not available"
#endif
#ifdef _POSIX_MONOTONIC_CLOCK
#ifdef CLOCK_MONOTONIC_RAW
static clockid_t CLOCKTYPE = CLOCK_MONOTONIC_RAW;
static const char* SCLOCKTYPE = "CLOCK_MONOTONIC_RAW";
#else
static clockid_t CLOCKTYPE = CLOCK_MONOTONIC
static const char* SCLOCKTYPE = "CLOCK_MONOTONIC";
#endif /* CLOCK_MONOTONIC_RAW */
#else
#warning "CLOCK_MONOTONIC is unavailable, using CLOCK_REALTIME"
static clockid CLOCKTYPE = CLOCK_REALTIME;
static const char* SCLOCKTYPE = "CLOCK_REALTIME";
#endif /* _POSIX_MONOTONIC_CLOCK */
#define NANOSEC 1000000000LL
namespace ggc {
class Timer {
char const *name;
struct timespec begin, end;
bool active, valid;
unsigned long long last;
unsigned long long total;
public:
Timer(const char *timer_name) {
name = timer_name;
active = false;
valid = false;
total = 0;
}
unsigned long long normalize(const struct timespec &t) const {
return t.tv_sec * NANOSEC + t.tv_nsec;
}
void reset() {
assert(!active);
total = 0;
last = 0;
}
void start() {
assert(!active);
active = true;
valid = false;
if(clock_gettime(CLOCKTYPE, &begin) == -1) {
if(errno == EINVAL) {
fprintf(stderr, "%s (%d) not available.\n", SCLOCKTYPE, CLOCKTYPE);
// exit?
}
}
}
void print() {
printf("%s %llu %llu\n", name, normalize(begin), normalize(end));
}
void stop() {
assert(active);
if(clock_gettime(CLOCKTYPE, &end) == -1) {
if(errno == EINVAL) {
fprintf(stderr, "%s (%d) not available.\n", SCLOCKTYPE, CLOCKTYPE);
// exit?
}
}
// assert(normalize(end) > normalize(begin) // paranoid level 2
last = normalize(end) - normalize(begin);
total += last;
active = false;
valid = true;
}
unsigned long long duration() const {
return last;
}
unsigned long long duration_ms() const {
return last * 1000 / NANOSEC;
}
unsigned long long duration_s() const {
return last / NANOSEC;
}
unsigned long long total_duration() const {
return total;
}
};
}
#if 0
__attribute__((constructor)) static void upgrade_timer(void) {
struct timespec res;
// see if CLOCK_MONOTONIC_RAW is available at runtime
#if defined(_POSIX_MONOTONIC_CLOCK) && defined(__linux__)
if(CLOCKTYPE == CLOCK_MONOTONIC) {
int rv;
clockid_t clockid;
#ifdef CLOCK_MONOTONIC_RAW
clockid = CLOCK_MONOTONIC_RAW;
#else
clockid = 4; // from bits/time.h
#endif
rv = clock_getres(clockid, &res);
if(rv == 0) {
//fprintf(stderr, "Using CLOCK_MONOTONIC_RAW for Timer.\n");
CLOCKTYPE = clockid;
SCLOCKTYPE = "CLOCK_MONOTONIC_RAW";
}
}
#endif
}
#endif