| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 1 | /* | 
| Jens Axboe | f5cc024 | 2006-11-24 10:47:40 +0100 | [diff] [blame] | 2 |  * Clock functions | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 3 |  */ | 
| Jens Axboe | f5cc024 | 2006-11-24 10:47:40 +0100 | [diff] [blame] | 4 |  | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 5 | #include <unistd.h> | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 6 | #include <math.h> | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 7 | #include <sys/time.h> | 
| Bruce Cran | 03e20d6 | 2011-01-02 20:14:54 +0100 | [diff] [blame] | 8 | #include <time.h> | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 9 |  | 
 | 10 | #include "fio.h" | 
| Jens Axboe | be4ecfd | 2008-12-08 14:10:52 +0100 | [diff] [blame] | 11 | #include "smalloc.h" | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 12 |  | 
 | 13 | #include "hash.h" | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 14 | #include "os/os.h" | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 15 |  | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 16 | #ifdef ARCH_HAVE_CPU_CLOCK | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 17 | static unsigned long cycles_per_usec; | 
| Jens Axboe | 7133911 | 2012-12-21 22:54:56 +0100 | [diff] [blame] | 18 | static unsigned long inv_cycles_per_usec; | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 19 | #endif | 
| Jens Axboe | 4de98eb | 2013-01-01 10:59:04 +0100 | [diff] [blame] | 20 | int tsc_reliable = 0; | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 21 |  | 
 | 22 | struct tv_valid { | 
 | 23 | 	struct timeval last_tv; | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 24 | 	uint64_t last_cycles; | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 25 | 	int last_tv_valid; | 
 | 26 | }; | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 27 | #ifdef CONFIG_TLS_THREAD | 
 | 28 | static struct tv_valid __thread static_tv_valid; | 
 | 29 | #else | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 30 | static pthread_key_t tv_tls_key; | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 31 | #endif | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 32 |  | 
| Bruce Cran | 16de1bf | 2012-02-20 17:07:32 +0000 | [diff] [blame] | 33 | enum fio_cs fio_clock_source = FIO_PREFERRED_CLOCK_SOURCE; | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 34 | int fio_clock_source_set = 0; | 
| Jens Axboe | 01423ea | 2012-12-14 20:37:06 +0100 | [diff] [blame] | 35 | enum fio_cs fio_clock_source_inited = CS_INVAL; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 36 |  | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 37 | #ifdef FIO_DEBUG_TIME | 
 | 38 |  | 
 | 39 | #define HASH_BITS	8 | 
 | 40 | #define HASH_SIZE	(1 << HASH_BITS) | 
 | 41 |  | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 42 | static struct flist_head hash[HASH_SIZE]; | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 43 | static int gtod_inited; | 
 | 44 |  | 
 | 45 | struct gtod_log { | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 46 | 	struct flist_head list; | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 47 | 	void *caller; | 
 | 48 | 	unsigned long calls; | 
 | 49 | }; | 
 | 50 |  | 
 | 51 | static struct gtod_log *find_hash(void *caller) | 
 | 52 | { | 
 | 53 | 	unsigned long h = hash_ptr(caller, HASH_BITS); | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 54 | 	struct flist_head *entry; | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 55 |  | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 56 | 	flist_for_each(entry, &hash[h]) { | 
 | 57 | 		struct gtod_log *log = flist_entry(entry, struct gtod_log, | 
 | 58 | 									list); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 59 |  | 
 | 60 | 		if (log->caller == caller) | 
 | 61 | 			return log; | 
 | 62 | 	} | 
 | 63 |  | 
 | 64 | 	return NULL; | 
 | 65 | } | 
 | 66 |  | 
 | 67 | static struct gtod_log *find_log(void *caller) | 
 | 68 | { | 
 | 69 | 	struct gtod_log *log = find_hash(caller); | 
 | 70 |  | 
 | 71 | 	if (!log) { | 
 | 72 | 		unsigned long h; | 
 | 73 |  | 
 | 74 | 		log = malloc(sizeof(*log)); | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 75 | 		INIT_FLIST_HEAD(&log->list); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 76 | 		log->caller = caller; | 
 | 77 | 		log->calls = 0; | 
 | 78 |  | 
 | 79 | 		h = hash_ptr(caller, HASH_BITS); | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 80 | 		flist_add_tail(&log->list, &hash[h]); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 81 | 	} | 
 | 82 |  | 
 | 83 | 	return log; | 
 | 84 | } | 
 | 85 |  | 
 | 86 | static void gtod_log_caller(void *caller) | 
 | 87 | { | 
 | 88 | 	if (gtod_inited) { | 
 | 89 | 		struct gtod_log *log = find_log(caller); | 
 | 90 |  | 
 | 91 | 		log->calls++; | 
 | 92 | 	} | 
 | 93 | } | 
 | 94 |  | 
 | 95 | static void fio_exit fio_dump_gtod(void) | 
 | 96 | { | 
 | 97 | 	unsigned long total_calls = 0; | 
 | 98 | 	int i; | 
 | 99 |  | 
 | 100 | 	for (i = 0; i < HASH_SIZE; i++) { | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 101 | 		struct flist_head *entry; | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 102 | 		struct gtod_log *log; | 
 | 103 |  | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 104 | 		flist_for_each(entry, &hash[i]) { | 
 | 105 | 			log = flist_entry(entry, struct gtod_log, list); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 106 |  | 
| Jens Axboe | 5ec10ea | 2008-03-06 15:42:00 +0100 | [diff] [blame] | 107 | 			printf("function %p, calls %lu\n", log->caller, | 
 | 108 | 								log->calls); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 109 | 			total_calls += log->calls; | 
 | 110 | 		} | 
 | 111 | 	} | 
 | 112 |  | 
 | 113 | 	printf("Total %lu gettimeofday\n", total_calls); | 
 | 114 | } | 
 | 115 |  | 
 | 116 | static void fio_init gtod_init(void) | 
 | 117 | { | 
 | 118 | 	int i; | 
 | 119 |  | 
 | 120 | 	for (i = 0; i < HASH_SIZE; i++) | 
| Jens Axboe | 01743ee | 2008-06-02 12:19:19 +0200 | [diff] [blame] | 121 | 		INIT_FLIST_HEAD(&hash[i]); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 122 |  | 
 | 123 | 	gtod_inited = 1; | 
 | 124 | } | 
 | 125 |  | 
 | 126 | #endif /* FIO_DEBUG_TIME */ | 
 | 127 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 128 | #ifdef CONFIG_CLOCK_GETTIME | 
| Jens Axboe | 9ff1c07 | 2012-12-20 15:17:57 +0100 | [diff] [blame] | 129 | static int fill_clock_gettime(struct timespec *ts) | 
 | 130 | { | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 131 | #ifdef CONFIG_CLOCK_MONOTONIC | 
| Jens Axboe | 9ff1c07 | 2012-12-20 15:17:57 +0100 | [diff] [blame] | 132 | 	return clock_gettime(CLOCK_MONOTONIC, ts); | 
 | 133 | #else | 
 | 134 | 	return clock_gettime(CLOCK_REALTIME, ts); | 
 | 135 | #endif | 
 | 136 | } | 
| Jens Axboe | 1e97cce | 2006-12-05 11:44:16 +0100 | [diff] [blame] | 137 | #endif | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 138 |  | 
 | 139 | static void *__fio_gettime(struct timeval *tp) | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 140 | { | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 141 | 	struct tv_valid *tv; | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 142 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 143 | #ifdef CONFIG_TLS_THREAD | 
 | 144 | 	tv = &static_tv_valid; | 
 | 145 | #else | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 146 | 	tv = pthread_getspecific(tv_tls_key); | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 147 | #endif | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 148 |  | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 149 | 	switch (fio_clock_source) { | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 150 | #ifdef CONFIG_GETTIMEOFDAY | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 151 | 	case CS_GTOD: | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 152 | 		gettimeofday(tp, NULL); | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 153 | 		break; | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 154 | #endif | 
 | 155 | #ifdef CONFIG_CLOCK_GETTIME | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 156 | 	case CS_CGETTIME: { | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 157 | 		struct timespec ts; | 
 | 158 |  | 
| Jens Axboe | 9ff1c07 | 2012-12-20 15:17:57 +0100 | [diff] [blame] | 159 | 		if (fill_clock_gettime(&ts) < 0) { | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 160 | 			log_err("fio: clock_gettime fails\n"); | 
 | 161 | 			assert(0); | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 162 | 		} | 
 | 163 |  | 
 | 164 | 		tp->tv_sec = ts.tv_sec; | 
 | 165 | 		tp->tv_usec = ts.tv_nsec / 1000; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 166 | 		break; | 
 | 167 | 		} | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 168 | #endif | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 169 | #ifdef ARCH_HAVE_CPU_CLOCK | 
 | 170 | 	case CS_CPUCLOCK: { | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 171 | 		uint64_t usecs, t; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 172 |  | 
 | 173 | 		t = get_cpu_clock(); | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 174 | 		if (tv && t < tv->last_cycles) { | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 175 | 			dprint(FD_TIME, "CPU clock going back in time\n"); | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 176 | 			t = tv->last_cycles; | 
 | 177 | 		} else if (tv) | 
 | 178 | 			tv->last_cycles = t; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 179 |  | 
| Jens Axboe | 7133911 | 2012-12-21 22:54:56 +0100 | [diff] [blame] | 180 | 		usecs = (t * inv_cycles_per_usec) / 16777216UL; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 181 | 		tp->tv_sec = usecs / 1000000; | 
 | 182 | 		tp->tv_usec = usecs % 1000000; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 183 | 		break; | 
 | 184 | 		} | 
 | 185 | #endif | 
 | 186 | 	default: | 
 | 187 | 		log_err("fio: invalid clock source %d\n", fio_clock_source); | 
 | 188 | 		break; | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 189 | 	} | 
| Jens Axboe | 3e48892 | 2008-11-13 12:07:20 +0100 | [diff] [blame] | 190 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 191 | 	return tv; | 
 | 192 | } | 
 | 193 |  | 
 | 194 | #ifdef FIO_DEBUG_TIME | 
 | 195 | void fio_gettime(struct timeval *tp, void *caller) | 
 | 196 | #else | 
 | 197 | void fio_gettime(struct timeval *tp, void fio_unused *caller) | 
 | 198 | #endif | 
 | 199 | { | 
 | 200 | 	struct tv_valid *tv; | 
 | 201 |  | 
 | 202 | #ifdef FIO_DEBUG_TIME | 
 | 203 | 	if (!caller) | 
 | 204 | 		caller = __builtin_return_address(0); | 
 | 205 |  | 
 | 206 | 	gtod_log_caller(caller); | 
 | 207 | #endif | 
 | 208 | 	if (fio_tv) { | 
 | 209 | 		memcpy(tp, fio_tv, sizeof(*tp)); | 
 | 210 | 		return; | 
 | 211 | 	} | 
 | 212 |  | 
 | 213 | 	tv = __fio_gettime(tp); | 
 | 214 |  | 
| Jens Axboe | 3e48892 | 2008-11-13 12:07:20 +0100 | [diff] [blame] | 215 | 	/* | 
 | 216 | 	 * If Linux is using the tsc clock on non-synced processors, | 
 | 217 | 	 * sometimes time can appear to drift backwards. Fix that up. | 
 | 218 | 	 */ | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 219 | 	if (tv) { | 
 | 220 | 		if (tv->last_tv_valid) { | 
 | 221 | 			if (tp->tv_sec < tv->last_tv.tv_sec) | 
 | 222 | 				tp->tv_sec = tv->last_tv.tv_sec; | 
 | 223 | 			else if (tv->last_tv.tv_sec == tp->tv_sec && | 
 | 224 | 				 tp->tv_usec < tv->last_tv.tv_usec) | 
 | 225 | 				tp->tv_usec = tv->last_tv.tv_usec; | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 226 | 		} | 
| Jens Axboe | 93f0b09 | 2012-12-18 09:41:59 +0100 | [diff] [blame] | 227 | 		tv->last_tv_valid = 1; | 
 | 228 | 		memcpy(&tv->last_tv, tp, sizeof(*tp)); | 
| Jens Axboe | 3e48892 | 2008-11-13 12:07:20 +0100 | [diff] [blame] | 229 | 	} | 
| Jens Axboe | 02bcaa8 | 2006-11-24 10:42:00 +0100 | [diff] [blame] | 230 | } | 
| Jens Axboe | be4ecfd | 2008-12-08 14:10:52 +0100 | [diff] [blame] | 231 |  | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 232 | #ifdef ARCH_HAVE_CPU_CLOCK | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 233 | static unsigned long get_cycles_per_usec(void) | 
 | 234 | { | 
 | 235 | 	struct timeval s, e; | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 236 | 	uint64_t c_s, c_e; | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 237 | 	enum fio_cs old_cs = fio_clock_source; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 238 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 239 | #ifdef CONFIG_CLOCK_GETTIME | 
 | 240 | 	fio_clock_source = CS_CGETTIME; | 
 | 241 | #else | 
 | 242 | 	fio_clock_source = CS_GTOD; | 
 | 243 | #endif | 
 | 244 | 	__fio_gettime(&s); | 
| Jens Axboe | 9ff1c07 | 2012-12-20 15:17:57 +0100 | [diff] [blame] | 245 |  | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 246 | 	c_s = get_cpu_clock(); | 
 | 247 | 	do { | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 248 | 		uint64_t elapsed; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 249 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 250 | 		__fio_gettime(&e); | 
| Jens Axboe | 9ff1c07 | 2012-12-20 15:17:57 +0100 | [diff] [blame] | 251 |  | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 252 | 		elapsed = utime_since(&s, &e); | 
| Jens Axboe | 486332e | 2012-12-10 08:07:14 +0100 | [diff] [blame] | 253 | 		if (elapsed >= 1280) { | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 254 | 			c_e = get_cpu_clock(); | 
 | 255 | 			break; | 
 | 256 | 		} | 
 | 257 | 	} while (1); | 
 | 258 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 259 | 	fio_clock_source = old_cs; | 
| Jens Axboe | c011000 | 2012-12-10 08:29:03 +0100 | [diff] [blame] | 260 | 	return (c_e - c_s + 127) >> 7; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 261 | } | 
 | 262 |  | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 263 | #define NR_TIME_ITERS	50 | 
 | 264 |  | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 265 | static int calibrate_cpu_clock(void) | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 266 | { | 
 | 267 | 	double delta, mean, S; | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 268 | 	uint64_t avg, cycles[NR_TIME_ITERS]; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 269 | 	int i, samples; | 
 | 270 |  | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 271 | 	cycles[0] = get_cycles_per_usec(); | 
 | 272 | 	S = delta = mean = 0.0; | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 273 | 	for (i = 0; i < NR_TIME_ITERS; i++) { | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 274 | 		cycles[i] = get_cycles_per_usec(); | 
 | 275 | 		delta = cycles[i] - mean; | 
 | 276 | 		if (delta) { | 
 | 277 | 			mean += delta / (i + 1.0); | 
 | 278 | 			S += delta * (cycles[i] - mean); | 
 | 279 | 		} | 
 | 280 | 	} | 
 | 281 |  | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 282 | 	/* | 
 | 283 | 	 * The most common platform clock breakage is returning zero | 
 | 284 | 	 * indefinitely. Check for that and return failure. | 
 | 285 | 	 */ | 
 | 286 | 	if (!cycles[0] && !cycles[NR_TIME_ITERS - 1]) | 
 | 287 | 		return 1; | 
 | 288 |  | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 289 | 	S = sqrt(S / (NR_TIME_ITERS - 1.0)); | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 290 |  | 
 | 291 | 	samples = avg = 0; | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 292 | 	for (i = 0; i < NR_TIME_ITERS; i++) { | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 293 | 		double this = cycles[i]; | 
 | 294 |  | 
| Bruce Cran | 03e20d6 | 2011-01-02 20:14:54 +0100 | [diff] [blame] | 295 | 		if ((fmax(this, mean) - fmin(this, mean)) > S) | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 296 | 			continue; | 
 | 297 | 		samples++; | 
 | 298 | 		avg += this; | 
 | 299 | 	} | 
 | 300 |  | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 301 | 	S /= (double) NR_TIME_ITERS; | 
| Jens Axboe | 89db727 | 2012-12-10 08:29:56 +0100 | [diff] [blame] | 302 | 	mean /= 10.0; | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 303 |  | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 304 | 	for (i = 0; i < NR_TIME_ITERS; i++) | 
| Jens Axboe | 4b91ee8 | 2013-02-25 10:18:33 +0100 | [diff] [blame] | 305 | 		dprint(FD_TIME, "cycles[%d]=%llu\n", i, | 
 | 306 | 					(unsigned long long) cycles[i] / 10); | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 307 |  | 
| Jens Axboe | d7abad3 | 2012-12-10 10:15:59 +0100 | [diff] [blame] | 308 | 	avg /= samples; | 
| Jens Axboe | b0ff22d | 2013-01-01 13:38:18 +0100 | [diff] [blame] | 309 | 	avg = (avg + 5) / 10; | 
| Jens Axboe | 4b91ee8 | 2013-02-25 10:18:33 +0100 | [diff] [blame] | 310 | 	dprint(FD_TIME, "avg: %llu\n", (unsigned long long) avg); | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 311 | 	dprint(FD_TIME, "mean=%f, S=%f\n", mean, S); | 
 | 312 |  | 
 | 313 | 	cycles_per_usec = avg; | 
| Jens Axboe | 7133911 | 2012-12-21 22:54:56 +0100 | [diff] [blame] | 314 | 	inv_cycles_per_usec = 16777216UL / cycles_per_usec; | 
 | 315 | 	dprint(FD_TIME, "inv_cycles_per_usec=%lu\n", inv_cycles_per_usec); | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 316 | 	return 0; | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 317 | } | 
 | 318 | #else | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 319 | static int calibrate_cpu_clock(void) | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 320 | { | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 321 | 	return 1; | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 322 | } | 
 | 323 | #endif | 
 | 324 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 325 | #ifndef CONFIG_TLS_THREAD | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 326 | void fio_local_clock_init(int is_thread) | 
 | 327 | { | 
 | 328 | 	struct tv_valid *t; | 
 | 329 |  | 
 | 330 | 	t = calloc(sizeof(*t), 1); | 
 | 331 | 	if (pthread_setspecific(tv_tls_key, t)) | 
 | 332 | 		log_err("fio: can't set TLS key\n"); | 
 | 333 | } | 
 | 334 |  | 
 | 335 | static void kill_tv_tls_key(void *data) | 
 | 336 | { | 
 | 337 | 	free(data); | 
 | 338 | } | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 339 | #else | 
 | 340 | void fio_local_clock_init(int is_thread) | 
 | 341 | { | 
 | 342 | } | 
 | 343 | #endif | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 344 |  | 
| Jens Axboe | 09a3240 | 2010-08-15 15:01:51 -0400 | [diff] [blame] | 345 | void fio_clock_init(void) | 
 | 346 | { | 
| Jens Axboe | 01423ea | 2012-12-14 20:37:06 +0100 | [diff] [blame] | 347 | 	if (fio_clock_source == fio_clock_source_inited) | 
 | 348 | 		return; | 
 | 349 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 350 | #ifndef CONFIG_TLS_THREAD | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 351 | 	if (pthread_key_create(&tv_tls_key, kill_tv_tls_key)) | 
 | 352 | 		log_err("fio: can't create TLS key\n"); | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 353 | #endif | 
| Jens Axboe | 5d87939 | 2012-12-18 09:12:27 +0100 | [diff] [blame] | 354 |  | 
| Jens Axboe | 01423ea | 2012-12-14 20:37:06 +0100 | [diff] [blame] | 355 | 	fio_clock_source_inited = fio_clock_source; | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 356 |  | 
 | 357 | 	if (calibrate_cpu_clock()) | 
 | 358 | 		tsc_reliable = 0; | 
| Jens Axboe | fa80fea | 2012-12-09 20:29:00 +0100 | [diff] [blame] | 359 |  | 
 | 360 | 	/* | 
 | 361 | 	 * If the arch sets tsc_reliable != 0, then it must be good enough | 
 | 362 | 	 * to use as THE clock source. For x86 CPUs, this means the TSC | 
 | 363 | 	 * runs at a constant rate and is synced across CPU cores. | 
 | 364 | 	 */ | 
 | 365 | 	if (tsc_reliable) { | 
 | 366 | 		if (!fio_clock_source_set) | 
 | 367 | 			fio_clock_source = CS_CPUCLOCK; | 
 | 368 | 	} else if (fio_clock_source == CS_CPUCLOCK) | 
 | 369 | 		log_info("fio: clocksource=cpu may not be reliable\n"); | 
| Jens Axboe | c223da8 | 2010-03-24 13:23:53 +0100 | [diff] [blame] | 370 | } | 
 | 371 |  | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 372 | uint64_t utime_since(struct timeval *s, struct timeval *e) | 
| Jens Axboe | be4ecfd | 2008-12-08 14:10:52 +0100 | [diff] [blame] | 373 | { | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 374 | 	long sec, usec; | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 375 | 	uint64_t ret; | 
| Jens Axboe | be4ecfd | 2008-12-08 14:10:52 +0100 | [diff] [blame] | 376 |  | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 377 | 	sec = e->tv_sec - s->tv_sec; | 
 | 378 | 	usec = e->tv_usec - s->tv_usec; | 
 | 379 | 	if (sec > 0 && usec < 0) { | 
 | 380 | 		sec--; | 
 | 381 | 		usec += 1000000; | 
 | 382 | 	} | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 383 |  | 
 | 384 | 	/* | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 385 | 	 * time warp bug on some kernels? | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 386 | 	 */ | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 387 | 	if (sec < 0 || (sec == 0 && usec < 0)) | 
 | 388 | 		return 0; | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 389 |  | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 390 | 	ret = sec * 1000000ULL + usec; | 
 | 391 |  | 
 | 392 | 	return ret; | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 393 | } | 
 | 394 |  | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 395 | uint64_t utime_since_now(struct timeval *s) | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 396 | { | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 397 | 	struct timeval t; | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 398 |  | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 399 | 	fio_gettime(&t, NULL); | 
 | 400 | 	return utime_since(s, &t); | 
 | 401 | } | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 402 |  | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 403 | uint64_t mtime_since(struct timeval *s, struct timeval *e) | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 404 | { | 
 | 405 | 	long sec, usec, ret; | 
 | 406 |  | 
 | 407 | 	sec = e->tv_sec - s->tv_sec; | 
 | 408 | 	usec = e->tv_usec - s->tv_usec; | 
 | 409 | 	if (sec > 0 && usec < 0) { | 
 | 410 | 		sec--; | 
 | 411 | 		usec += 1000000; | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 412 | 	} | 
 | 413 |  | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 414 | 	if (sec < 0 || (sec == 0 && usec < 0)) | 
 | 415 | 		return 0; | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 416 |  | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 417 | 	sec *= 1000UL; | 
 | 418 | 	usec /= 1000UL; | 
 | 419 | 	ret = sec + usec; | 
 | 420 |  | 
| Jens Axboe | 783a3eb | 2012-02-09 10:27:10 +0100 | [diff] [blame] | 421 | 	return ret; | 
 | 422 | } | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 423 |  | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 424 | uint64_t mtime_since_now(struct timeval *s) | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 425 | { | 
 | 426 | 	struct timeval t; | 
 | 427 | 	void *p = __builtin_return_address(0); | 
 | 428 |  | 
 | 429 | 	fio_gettime(&t, p); | 
 | 430 | 	return mtime_since(s, &t); | 
 | 431 | } | 
 | 432 |  | 
| Jens Axboe | aa60bc5 | 2013-01-04 13:24:52 +0100 | [diff] [blame] | 433 | uint64_t time_since_now(struct timeval *s) | 
| Jens Axboe | 39ab7da | 2012-11-06 22:10:43 +0100 | [diff] [blame] | 434 | { | 
 | 435 | 	return mtime_since_now(s) / 1000; | 
 | 436 | } | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 437 |  | 
| Jens Axboe | 67bf982 | 2013-01-10 11:23:19 +0100 | [diff] [blame] | 438 | #if defined(FIO_HAVE_CPU_AFFINITY) && defined(ARCH_HAVE_CPU_CLOCK)  && \ | 
 | 439 |     defined(CONFIG_SFAA) | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 440 |  | 
 | 441 | #define CLOCK_ENTRIES	100000 | 
 | 442 |  | 
 | 443 | struct clock_entry { | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 444 | 	uint32_t seq; | 
 | 445 | 	uint32_t cpu; | 
| Jens Axboe | ba458c2 | 2013-01-21 05:38:22 -0700 | [diff] [blame] | 446 | 	uint64_t tsc; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 447 | }; | 
 | 448 |  | 
 | 449 | struct clock_thread { | 
 | 450 | 	pthread_t thread; | 
 | 451 | 	int cpu; | 
 | 452 | 	pthread_mutex_t lock; | 
 | 453 | 	pthread_mutex_t started; | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 454 | 	uint32_t *seq; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 455 | 	struct clock_entry *entries; | 
 | 456 | }; | 
 | 457 |  | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 458 | static inline uint32_t atomic32_inc_return(uint32_t *seq) | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 459 | { | 
 | 460 | 	return 1 + __sync_fetch_and_add(seq, 1); | 
 | 461 | } | 
 | 462 |  | 
 | 463 | static void *clock_thread_fn(void *data) | 
 | 464 | { | 
 | 465 | 	struct clock_thread *t = data; | 
 | 466 | 	struct clock_entry *c; | 
 | 467 | 	os_cpu_mask_t cpu_mask; | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 468 | 	uint32_t last_seq; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 469 | 	int i; | 
 | 470 |  | 
 | 471 | 	memset(&cpu_mask, 0, sizeof(cpu_mask)); | 
 | 472 | 	fio_cpu_set(&cpu_mask, t->cpu); | 
 | 473 |  | 
 | 474 | 	if (fio_setaffinity(gettid(), cpu_mask) == -1) { | 
 | 475 | 		log_err("clock setaffinity failed\n"); | 
 | 476 | 		return (void *) 1; | 
 | 477 | 	} | 
 | 478 |  | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 479 | 	pthread_mutex_lock(&t->lock); | 
| Jens Axboe | b9b3498 | 2012-12-17 14:23:47 +0100 | [diff] [blame] | 480 | 	pthread_mutex_unlock(&t->started); | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 481 |  | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 482 | 	last_seq = 0; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 483 | 	c = &t->entries[0]; | 
 | 484 | 	for (i = 0; i < CLOCK_ENTRIES; i++, c++) { | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 485 | 		uint32_t seq; | 
 | 486 | 		uint64_t tsc; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 487 |  | 
 | 488 | 		c->cpu = t->cpu; | 
 | 489 | 		do { | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 490 | 			seq = atomic32_inc_return(t->seq); | 
 | 491 | 			if (seq < last_seq) | 
 | 492 | 				break; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 493 | 			tsc = get_cpu_clock(); | 
 | 494 | 		} while (seq != *t->seq); | 
 | 495 |  | 
 | 496 | 		c->seq = seq; | 
 | 497 | 		c->tsc = tsc; | 
 | 498 | 	} | 
 | 499 |  | 
| Jens Axboe | 0f78b22 | 2013-02-26 13:54:20 +0100 | [diff] [blame] | 500 | 	log_info("cs: cpu%3d: %llu clocks seen\n", t->cpu, | 
 | 501 | 		(unsigned long long) t->entries[i - 1].tsc - t->entries[0].tsc); | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 502 |  | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 503 | 	/* | 
 | 504 | 	 * The most common platform clock breakage is returning zero | 
 | 505 | 	 * indefinitely. Check for that and return failure. | 
 | 506 | 	 */ | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 507 | 	if (!t->entries[i - 1].tsc && !t->entries[0].tsc) | 
| Jens Axboe | e259879 | 2013-02-24 21:29:35 +0100 | [diff] [blame] | 508 | 		return (void *) 1; | 
 | 509 |  | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 510 | 	return NULL; | 
 | 511 | } | 
 | 512 |  | 
 | 513 | static int clock_cmp(const void *p1, const void *p2) | 
 | 514 | { | 
 | 515 | 	const struct clock_entry *c1 = p1; | 
 | 516 | 	const struct clock_entry *c2 = p2; | 
 | 517 |  | 
| Jens Axboe | b9b3498 | 2012-12-17 14:23:47 +0100 | [diff] [blame] | 518 | 	if (c1->seq == c2->seq) | 
 | 519 | 		log_err("cs: bug in atomic sequence!\n"); | 
 | 520 |  | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 521 | 	return c1->seq - c2->seq; | 
 | 522 | } | 
 | 523 |  | 
 | 524 | int fio_monotonic_clocktest(void) | 
 | 525 | { | 
 | 526 | 	struct clock_thread *threads; | 
 | 527 | 	unsigned int nr_cpus = cpus_online(); | 
 | 528 | 	struct clock_entry *entries; | 
 | 529 | 	unsigned long tentries, failed; | 
| Bruce Cran | 80da8a8 | 2013-02-21 14:16:17 +0100 | [diff] [blame] | 530 | 	struct clock_entry *prev, *this; | 
| Jens Axboe | 58002f9 | 2013-02-25 10:23:58 +0100 | [diff] [blame] | 531 | 	uint32_t seq = 0; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 532 | 	int i; | 
 | 533 |  | 
| Jens Axboe | d5e3f5d | 2013-01-18 20:13:45 +0100 | [diff] [blame] | 534 | 	log_info("cs: reliable_tsc: %s\n", tsc_reliable ? "yes" : "no"); | 
 | 535 |  | 
| Jens Axboe | 4f1d43c | 2012-12-17 14:29:28 +0100 | [diff] [blame] | 536 | 	fio_debug |= 1U << FD_TIME; | 
 | 537 | 	calibrate_cpu_clock(); | 
 | 538 | 	fio_debug &= ~(1U << FD_TIME); | 
 | 539 |  | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 540 | 	threads = malloc(nr_cpus * sizeof(struct clock_thread)); | 
 | 541 | 	tentries = CLOCK_ENTRIES * nr_cpus; | 
 | 542 | 	entries = malloc(tentries * sizeof(struct clock_entry)); | 
 | 543 |  | 
 | 544 | 	log_info("cs: Testing %u CPUs\n", nr_cpus); | 
 | 545 |  | 
 | 546 | 	for (i = 0; i < nr_cpus; i++) { | 
 | 547 | 		struct clock_thread *t = &threads[i]; | 
 | 548 |  | 
 | 549 | 		t->cpu = i; | 
 | 550 | 		t->seq = &seq; | 
 | 551 | 		t->entries = &entries[i * CLOCK_ENTRIES]; | 
 | 552 | 		pthread_mutex_init(&t->lock, NULL); | 
 | 553 | 		pthread_mutex_init(&t->started, NULL); | 
 | 554 | 		pthread_mutex_lock(&t->lock); | 
 | 555 | 		pthread_create(&t->thread, NULL, clock_thread_fn, t); | 
 | 556 | 	} | 
 | 557 |  | 
 | 558 | 	for (i = 0; i < nr_cpus; i++) { | 
 | 559 | 		struct clock_thread *t = &threads[i]; | 
 | 560 |  | 
 | 561 | 		pthread_mutex_lock(&t->started); | 
 | 562 | 	} | 
 | 563 |  | 
 | 564 | 	for (i = 0; i < nr_cpus; i++) { | 
 | 565 | 		struct clock_thread *t = &threads[i]; | 
 | 566 |  | 
 | 567 | 		pthread_mutex_unlock(&t->lock); | 
 | 568 | 	} | 
 | 569 |  | 
 | 570 | 	for (failed = i = 0; i < nr_cpus; i++) { | 
 | 571 | 		struct clock_thread *t = &threads[i]; | 
 | 572 | 		void *ret; | 
 | 573 |  | 
 | 574 | 		pthread_join(t->thread, &ret); | 
 | 575 | 		if (ret) | 
 | 576 | 			failed++; | 
 | 577 | 	} | 
 | 578 | 	free(threads); | 
 | 579 |  | 
 | 580 | 	if (failed) { | 
 | 581 | 		log_err("Clocksource test: %u threads failed\n", failed); | 
 | 582 | 		goto err; | 
 | 583 | 	} | 
 | 584 |  | 
 | 585 | 	qsort(entries, tentries, sizeof(struct clock_entry), clock_cmp); | 
 | 586 |  | 
 | 587 | 	for (failed = i = 0; i < tentries; i++) { | 
| Bruce Cran | 80da8a8 | 2013-02-21 14:16:17 +0100 | [diff] [blame] | 588 | 		this = &entries[i]; | 
| Jens Axboe | 7d11f87 | 2012-12-17 12:03:29 +0100 | [diff] [blame] | 589 |  | 
 | 590 | 		if (!i) { | 
 | 591 | 			prev = this; | 
 | 592 | 			continue; | 
 | 593 | 		} | 
 | 594 |  | 
 | 595 | 		if (prev->tsc > this->tsc) { | 
 | 596 | 			uint64_t diff = prev->tsc - this->tsc; | 
 | 597 |  | 
 | 598 | 			log_info("cs: CPU clock mismatch (diff=%lu):\n", diff); | 
 | 599 | 			log_info("\t CPU%3lu: TSC=%lu, SEQ=%lu\n", prev->cpu, prev->tsc, prev->seq); | 
 | 600 | 			log_info("\t CPU%3lu: TSC=%lu, SEQ=%lu\n", this->cpu, this->tsc, this->seq); | 
 | 601 | 			failed++; | 
 | 602 | 		} | 
 | 603 |  | 
 | 604 | 		prev = this; | 
 | 605 | 	} | 
 | 606 |  | 
 | 607 | 	if (failed) | 
 | 608 | 		log_info("cs: Failed: %lu\n", failed); | 
 | 609 | 	else | 
 | 610 | 		log_info("cs: Pass!\n"); | 
 | 611 |  | 
 | 612 | err: | 
 | 613 | 	free(entries); | 
 | 614 | 	return !!failed; | 
 | 615 | } | 
 | 616 |  | 
 | 617 | #else /* defined(FIO_HAVE_CPU_AFFINITY) && defined(ARCH_HAVE_CPU_CLOCK) */ | 
 | 618 |  | 
 | 619 | int fio_monotonic_clocktest(void) | 
 | 620 | { | 
 | 621 | 	log_info("cs: current platform does not support CPU clocks\n"); | 
 | 622 | 	return 0; | 
 | 623 | } | 
 | 624 |  | 
 | 625 | #endif |