#ifdef ARCH_HAVE_CPU_CLOCK
static unsigned long cycles_per_usec;
-static unsigned long last_cycles;
int tsc_reliable = 0;
#endif
-static struct timeval last_tv;
-static int last_tv_valid;
+
+struct tv_valid {
+ struct timeval last_tv;
+ int last_tv_valid;
+ unsigned long last_cycles;
+};
+static pthread_key_t tv_tls_key;
enum fio_cs fio_clock_source = FIO_PREFERRED_CLOCK_SOURCE;
int fio_clock_source_set = 0;
void fio_gettime(struct timeval *tp, void fio_unused *caller)
#endif
{
+ struct tv_valid *tv;
+
#ifdef FIO_DEBUG_TIME
if (!caller)
caller = __builtin_return_address(0);
return;
}
+ tv = pthread_getspecific(tv_tls_key);
+
switch (fio_clock_source) {
case CS_GTOD:
gettimeofday(tp, NULL);
unsigned long long usecs, t;
t = get_cpu_clock();
- if (t < last_cycles) {
+ if (tv && t < tv->last_cycles) {
dprint(FD_TIME, "CPU clock going back in time\n");
- t = last_cycles;
- }
+ t = tv->last_cycles;
+ } else if (tv)
+ tv->last_cycles = t;
usecs = t / cycles_per_usec;
tp->tv_sec = usecs / 1000000;
tp->tv_usec = usecs % 1000000;
- last_cycles = t;
break;
}
#endif
* If Linux is using the tsc clock on non-synced processors,
* sometimes time can appear to drift backwards. Fix that up.
*/
- if (last_tv_valid) {
- if (tp->tv_sec < last_tv.tv_sec)
- tp->tv_sec = last_tv.tv_sec;
- else if (last_tv.tv_sec == tp->tv_sec &&
- tp->tv_usec < last_tv.tv_usec)
- tp->tv_usec = last_tv.tv_usec;
+ if (tv) {
+ if (tv->last_tv_valid) {
+ if (tp->tv_sec < tv->last_tv.tv_sec)
+ tp->tv_sec = tv->last_tv.tv_sec;
+ else if (tv->last_tv.tv_sec == tp->tv_sec &&
+ tp->tv_usec < tv->last_tv.tv_usec)
+ tp->tv_usec = tv->last_tv.tv_usec;
+ }
+ tv->last_tv_valid = 1;
+ memcpy(&tv->last_tv, tp, sizeof(*tp));
}
- last_tv_valid = 1;
- memcpy(&last_tv, tp, sizeof(*tp));
}
#ifdef ARCH_HAVE_CPU_CLOCK
}
#endif
+void fio_local_clock_init(int is_thread)
+{
+ struct tv_valid *t;
+
+ t = calloc(sizeof(*t), 1);
+ if (pthread_setspecific(tv_tls_key, t))
+ log_err("fio: can't set TLS key\n");
+}
+
+static void kill_tv_tls_key(void *data)
+{
+ free(data);
+}
+
void fio_clock_init(void)
{
if (fio_clock_source == fio_clock_source_inited)
return;
- last_tv_valid = 0;
+ if (pthread_key_create(&tv_tls_key, kill_tv_tls_key))
+ log_err("fio: can't create TLS key\n");
+
fio_clock_source_inited = fio_clock_source;
calibrate_cpu_clock();
uint64_t seq = 0;
int i;
+ fio_debug |= 1U << FD_TIME;
+ calibrate_cpu_clock();
+ fio_debug &= ~(1U << FD_TIME);
+
threads = malloc(nr_cpus * sizeof(struct clock_thread));
tentries = CLOCK_ENTRIES * nr_cpus;
entries = malloc(tentries * sizeof(struct clock_entry));