139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include <unistd.h>
239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include <math.h>
339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include <sys/time.h>
439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include <time.h>
539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include "fio.h"
739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe#include "smalloc.h"
839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
95be4c944e83b32c0c6842130df3dc1d46cd6eb1fJens Axboestruct timeval *fio_tv = NULL;
1039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboeint fio_gtod_offload = 0;
1139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboeint fio_gtod_cpu = -1;
1239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboestatic pthread_t gtod_thread;
1339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
1439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboevoid fio_gtod_init(void)
1539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe{
1639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	fio_tv = smalloc(sizeof(struct timeval));
17fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe	if (!fio_tv)
18fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe		log_err("fio: smalloc pool exhausted\n");
1939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe}
2039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
2139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboestatic void fio_gtod_update(void)
2239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe{
23fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe	if (fio_tv)
24fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe		gettimeofday(fio_tv, NULL);
2539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe}
2639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
2739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboestatic void *gtod_thread_main(void *data)
2839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe{
2939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	struct fio_mutex *mutex = data;
3039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
3139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	fio_mutex_up(mutex);
3239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
3339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	/*
3439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	 * As long as we have jobs around, update the clock. It would be nice
3539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	 * to have some way of NOT hammering that CPU with gettimeofday(),
3639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	 * but I'm not sure what to use outside of a simple CPU nop to relax
3739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	 * it - we don't want to lose precision.
3839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	 */
3939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	while (threads) {
4039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		fio_gtod_update();
4139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		nop;
4239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	}
4339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
4439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	return NULL;
4539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe}
4639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
4739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboeint fio_start_gtod_thread(void)
4839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe{
4939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	struct fio_mutex *mutex;
5039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	pthread_attr_t attr;
5139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	int ret;
5239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
5339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	mutex = fio_mutex_init(FIO_MUTEX_LOCKED);
5439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	if (!mutex)
5539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		return 1;
5639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
5739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	pthread_attr_init(&attr);
5839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
5939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	ret = pthread_create(&gtod_thread, &attr, gtod_thread_main, NULL);
6039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	pthread_attr_destroy(&attr);
6139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	if (ret) {
6239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		log_err("Can't create gtod thread: %s\n", strerror(ret));
6339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		goto err;
6439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	}
6539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
6639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	ret = pthread_detach(gtod_thread);
6739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	if (ret) {
6839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		log_err("Can't detatch gtod thread: %s\n", strerror(ret));
6939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe		goto err;
7039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	}
7139ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
7239ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	dprint(FD_MUTEX, "wait on startup_mutex\n");
7339ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	fio_mutex_down(mutex);
7439ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	dprint(FD_MUTEX, "done waiting on startup_mutex\n");
7539ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboeerr:
7639ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	fio_mutex_remove(mutex);
7739ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe	return ret;
7839ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe}
7939ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
8039ab7da23768081db50b0026e0c2a8e38752e7a4Jens Axboe
81