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" | |
9 | #include "os.h" | |
10 | ||
11 | #include "hash.h" | |
12 | ||
13 | static int clock_gettime_works = 1; | |
14 | ||
15 | #ifdef FIO_DEBUG_TIME | |
16 | ||
17 | #define HASH_BITS 8 | |
18 | #define HASH_SIZE (1 << HASH_BITS) | |
19 | ||
20 | static struct list_head hash[HASH_SIZE]; | |
21 | static int gtod_inited; | |
22 | ||
23 | struct gtod_log { | |
24 | struct list_head list; | |
25 | void *caller; | |
26 | unsigned long calls; | |
27 | }; | |
28 | ||
29 | static struct gtod_log *find_hash(void *caller) | |
30 | { | |
31 | unsigned long h = hash_ptr(caller, HASH_BITS); | |
32 | struct list_head *entry; | |
33 | ||
34 | list_for_each(entry, &hash[h]) { | |
35 | struct gtod_log *log = list_entry(entry, struct gtod_log, list); | |
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)); | |
52 | INIT_LIST_HEAD(&log->list); | |
53 | log->caller = caller; | |
54 | log->calls = 0; | |
55 | ||
56 | h = hash_ptr(caller, HASH_BITS); | |
57 | list_add_tail(&log->list, &hash[h]); | |
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++) { | |
78 | struct list_head *entry; | |
79 | struct gtod_log *log; | |
80 | ||
81 | list_for_each(entry, &hash[i]) { | |
82 | log = list_entry(entry, struct gtod_log, list); | |
83 | ||
84 | printf("function %p, calls %lu\n", log->caller, log->calls); | |
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 | } |