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