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 | ||
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 | ||
5ec10eaa JA |
83 | printf("function %p, calls %lu\n", log->caller, |
84 | log->calls); | |
02bcaa8c JA |
85 | total_calls += log->calls; |
86 | } | |
87 | } | |
88 | ||
89 | printf("Total %lu gettimeofday\n", total_calls); | |
90 | } | |
91 | ||
92 | static void fio_init gtod_init(void) | |
93 | { | |
94 | int i; | |
95 | ||
96 | for (i = 0; i < HASH_SIZE; i++) | |
97 | INIT_LIST_HEAD(&hash[i]); | |
98 | ||
99 | gtod_inited = 1; | |
100 | } | |
101 | ||
102 | #endif /* FIO_DEBUG_TIME */ | |
103 | ||
1e97cce9 | 104 | #ifdef FIO_DEBUG_TIME |
02bcaa8c | 105 | void fio_gettime(struct timeval *tp, void *caller) |
1e97cce9 JA |
106 | #else |
107 | void fio_gettime(struct timeval *tp, void fio_unused *caller) | |
108 | #endif | |
02bcaa8c JA |
109 | { |
110 | #ifdef FIO_DEBUG_TIME | |
111 | if (!caller) | |
112 | caller = __builtin_return_address(0); | |
113 | ||
114 | gtod_log_caller(caller); | |
02bcaa8c | 115 | #endif |
7e326f3b JA |
116 | if (!clock_gettime_works) { |
117 | gtod: | |
02bcaa8c | 118 | gettimeofday(tp, NULL); |
7e326f3b | 119 | } else { |
02bcaa8c JA |
120 | struct timespec ts; |
121 | ||
122 | if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0) { | |
123 | clock_gettime_works = 0; | |
7e326f3b | 124 | goto gtod; |
02bcaa8c JA |
125 | } |
126 | ||
127 | tp->tv_sec = ts.tv_sec; | |
128 | tp->tv_usec = ts.tv_nsec / 1000; | |
129 | } | |
130 | } |