Properly strip end-of-option blanks
[fio.git] / gettime.c
CommitLineData
02bcaa8c 1/*
f5cc024a 2 * Clock functions
02bcaa8c 3 */
f5cc024a 4
02bcaa8c
JA
5#include <unistd.h>
6#include <sys/time.h>
7
8#include "fio.h"
02bcaa8c
JA
9
10#include "hash.h"
11
5ec10eaa 12static int clock_gettime_works;
3e488920
JA
13static struct timeval last_tv;
14static int last_tv_valid;
02bcaa8c
JA
15
16#ifdef FIO_DEBUG_TIME
17
18#define HASH_BITS 8
19#define HASH_SIZE (1 << HASH_BITS)
20
01743ee1 21static struct flist_head hash[HASH_SIZE];
02bcaa8c
JA
22static int gtod_inited;
23
24struct gtod_log {
01743ee1 25 struct flist_head list;
02bcaa8c
JA
26 void *caller;
27 unsigned long calls;
28};
29
30static struct gtod_log *find_hash(void *caller)
31{
32 unsigned long h = hash_ptr(caller, HASH_BITS);
01743ee1 33 struct flist_head *entry;
02bcaa8c 34
01743ee1
JA
35 flist_for_each(entry, &hash[h]) {
36 struct gtod_log *log = flist_entry(entry, struct gtod_log,
37 list);
02bcaa8c
JA
38
39 if (log->caller == caller)
40 return log;
41 }
42
43 return NULL;
44}
45
46static struct gtod_log *find_log(void *caller)
47{
48 struct gtod_log *log = find_hash(caller);
49
50 if (!log) {
51 unsigned long h;
52
53 log = malloc(sizeof(*log));
01743ee1 54 INIT_FLIST_HEAD(&log->list);
02bcaa8c
JA
55 log->caller = caller;
56 log->calls = 0;
57
58 h = hash_ptr(caller, HASH_BITS);
01743ee1 59 flist_add_tail(&log->list, &hash[h]);
02bcaa8c
JA
60 }
61
62 return log;
63}
64
65static void gtod_log_caller(void *caller)
66{
67 if (gtod_inited) {
68 struct gtod_log *log = find_log(caller);
69
70 log->calls++;
71 }
72}
73
74static void fio_exit fio_dump_gtod(void)
75{
76 unsigned long total_calls = 0;
77 int i;
78
79 for (i = 0; i < HASH_SIZE; i++) {
01743ee1 80 struct flist_head *entry;
02bcaa8c
JA
81 struct gtod_log *log;
82
01743ee1
JA
83 flist_for_each(entry, &hash[i]) {
84 log = flist_entry(entry, struct gtod_log, list);
02bcaa8c 85
5ec10eaa
JA
86 printf("function %p, calls %lu\n", log->caller,
87 log->calls);
02bcaa8c
JA
88 total_calls += log->calls;
89 }
90 }
91
92 printf("Total %lu gettimeofday\n", total_calls);
93}
94
95static void fio_init gtod_init(void)
96{
97 int i;
98
99 for (i = 0; i < HASH_SIZE; i++)
01743ee1 100 INIT_FLIST_HEAD(&hash[i]);
02bcaa8c
JA
101
102 gtod_inited = 1;
103}
104
105#endif /* FIO_DEBUG_TIME */
106
1e97cce9 107#ifdef FIO_DEBUG_TIME
02bcaa8c 108void fio_gettime(struct timeval *tp, void *caller)
1e97cce9
JA
109#else
110void fio_gettime(struct timeval *tp, void fio_unused *caller)
111#endif
02bcaa8c
JA
112{
113#ifdef FIO_DEBUG_TIME
114 if (!caller)
115 caller = __builtin_return_address(0);
116
117 gtod_log_caller(caller);
02bcaa8c 118#endif
7e326f3b
JA
119 if (!clock_gettime_works) {
120gtod:
02bcaa8c 121 gettimeofday(tp, NULL);
7e326f3b 122 } else {
02bcaa8c
JA
123 struct timespec ts;
124
125 if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) {
126 clock_gettime_works = 0;
7e326f3b 127 goto gtod;
02bcaa8c
JA
128 }
129
130 tp->tv_sec = ts.tv_sec;
131 tp->tv_usec = ts.tv_nsec / 1000;
132 }
3e488920
JA
133
134 /*
135 * If Linux is using the tsc clock on non-synced processors,
136 * sometimes time can appear to drift backwards. Fix that up.
137 */
138 if (last_tv_valid) {
139 if (tp->tv_sec < last_tv.tv_sec)
140 tp->tv_sec = last_tv.tv_sec;
141 else if (last_tv.tv_sec == tp->tv_sec &&
142 tp->tv_usec < last_tv.tv_usec)
143 tp->tv_usec = last_tv.tv_usec;
144 }
145 last_tv_valid = 1;
146 memcpy(&last_tv, tp, sizeof(*tp));
02bcaa8c 147}