Commit | Line | Data |
---|---|---|
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 | 12 | static int clock_gettime_works; |
02bcaa8c JA |
13 | |
14 | #ifdef FIO_DEBUG_TIME | |
15 | ||
16 | #define HASH_BITS 8 | |
17 | #define HASH_SIZE (1 << HASH_BITS) | |
18 | ||
01743ee1 | 19 | static struct flist_head hash[HASH_SIZE]; |
02bcaa8c JA |
20 | static int gtod_inited; |
21 | ||
22 | struct gtod_log { | |
01743ee1 | 23 | struct flist_head list; |
02bcaa8c JA |
24 | void *caller; |
25 | unsigned long calls; | |
26 | }; | |
27 | ||
28 | static struct gtod_log *find_hash(void *caller) | |
29 | { | |
30 | unsigned long h = hash_ptr(caller, HASH_BITS); | |
01743ee1 | 31 | struct flist_head *entry; |
02bcaa8c | 32 | |
01743ee1 JA |
33 | flist_for_each(entry, &hash[h]) { |
34 | struct gtod_log *log = flist_entry(entry, struct gtod_log, | |
35 | list); | |
02bcaa8c JA |
36 | |
37 | if (log->caller == caller) | |
38 | return log; | |
39 | } | |
40 | ||
41 | return NULL; | |
42 | } | |
43 | ||
44 | static struct gtod_log *find_log(void *caller) | |
45 | { | |
46 | struct gtod_log *log = find_hash(caller); | |
47 | ||
48 | if (!log) { | |
49 | unsigned long h; | |
50 | ||
51 | log = malloc(sizeof(*log)); | |
01743ee1 | 52 | INIT_FLIST_HEAD(&log->list); |
02bcaa8c JA |
53 | log->caller = caller; |
54 | log->calls = 0; | |
55 | ||
56 | h = hash_ptr(caller, HASH_BITS); | |
01743ee1 | 57 | flist_add_tail(&log->list, &hash[h]); |
02bcaa8c JA |
58 | } |
59 | ||
60 | return log; | |
61 | } | |
62 | ||
63 | static void gtod_log_caller(void *caller) | |
64 | { | |
65 | if (gtod_inited) { | |
66 | struct gtod_log *log = find_log(caller); | |
67 | ||
68 | log->calls++; | |
69 | } | |
70 | } | |
71 | ||
72 | static void fio_exit fio_dump_gtod(void) | |
73 | { | |
74 | unsigned long total_calls = 0; | |
75 | int i; | |
76 | ||
77 | for (i = 0; i < HASH_SIZE; i++) { | |
01743ee1 | 78 | struct flist_head *entry; |
02bcaa8c JA |
79 | struct gtod_log *log; |
80 | ||
01743ee1 JA |
81 | flist_for_each(entry, &hash[i]) { |
82 | log = flist_entry(entry, struct gtod_log, list); | |
02bcaa8c | 83 | |
5ec10eaa JA |
84 | printf("function %p, calls %lu\n", log->caller, |
85 | log->calls); | |
02bcaa8c JA |
86 | total_calls += log->calls; |
87 | } | |
88 | } | |
89 | ||
90 | printf("Total %lu gettimeofday\n", total_calls); | |
91 | } | |
92 | ||
93 | static void fio_init gtod_init(void) | |
94 | { | |
95 | int i; | |
96 | ||
97 | for (i = 0; i < HASH_SIZE; i++) | |
01743ee1 | 98 | INIT_FLIST_HEAD(&hash[i]); |
02bcaa8c JA |
99 | |
100 | gtod_inited = 1; | |
101 | } | |
102 | ||
103 | #endif /* FIO_DEBUG_TIME */ | |
104 | ||
1e97cce9 | 105 | #ifdef FIO_DEBUG_TIME |
02bcaa8c | 106 | void fio_gettime(struct timeval *tp, void *caller) |
1e97cce9 JA |
107 | #else |
108 | void fio_gettime(struct timeval *tp, void fio_unused *caller) | |
109 | #endif | |
02bcaa8c JA |
110 | { |
111 | #ifdef FIO_DEBUG_TIME | |
112 | if (!caller) | |
113 | caller = __builtin_return_address(0); | |
114 | ||
115 | gtod_log_caller(caller); | |
02bcaa8c | 116 | #endif |
7e326f3b JA |
117 | if (!clock_gettime_works) { |
118 | gtod: | |
02bcaa8c | 119 | gettimeofday(tp, NULL); |
7e326f3b | 120 | } else { |
02bcaa8c JA |
121 | struct timespec ts; |
122 | ||
123 | if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) { | |
124 | clock_gettime_works = 0; | |
7e326f3b | 125 | goto gtod; |
02bcaa8c JA |
126 | } |
127 | ||
128 | tp->tv_sec = ts.tv_sec; | |
129 | tp->tv_usec = ts.tv_nsec / 1000; | |
130 | } | |
131 | } |