Commit | Line | Data |
---|---|---|
39ab7da2 JA |
1 | #include <unistd.h> |
2 | #include <math.h> | |
3 | #include <sys/time.h> | |
4 | #include <time.h> | |
5 | ||
6 | #include "fio.h" | |
7 | #include "smalloc.h" | |
8 | ||
5be4c944 | 9 | struct timeval *fio_tv = NULL; |
39ab7da2 | 10 | int fio_gtod_offload = 0; |
39ab7da2 | 11 | static pthread_t gtod_thread; |
8a2b393b JA |
12 | #ifdef FIO_HAVE_CPU_AFFINITY |
13 | static os_cpu_mask_t fio_gtod_cpumask; | |
14 | #endif | |
39ab7da2 JA |
15 | |
16 | void fio_gtod_init(void) | |
17 | { | |
79c896a1 JA |
18 | if (fio_tv) |
19 | return; | |
20 | ||
39ab7da2 | 21 | fio_tv = smalloc(sizeof(struct timeval)); |
fba5c5ff JA |
22 | if (!fio_tv) |
23 | log_err("fio: smalloc pool exhausted\n"); | |
39ab7da2 JA |
24 | } |
25 | ||
26 | static void fio_gtod_update(void) | |
27 | { | |
27325ed5 JA |
28 | if (fio_tv) { |
29 | struct timeval __tv; | |
30 | ||
31 | gettimeofday(&__tv, NULL); | |
32 | fio_tv->tv_sec = __tv.tv_sec; | |
33 | write_barrier(); | |
34 | fio_tv->tv_usec = __tv.tv_usec; | |
35 | write_barrier(); | |
36 | } | |
39ab7da2 JA |
37 | } |
38 | ||
79c896a1 JA |
39 | struct gtod_cpu_data { |
40 | struct fio_mutex *mutex; | |
41 | unsigned int cpu; | |
42 | }; | |
43 | ||
39ab7da2 JA |
44 | static void *gtod_thread_main(void *data) |
45 | { | |
46 | struct fio_mutex *mutex = data; | |
47 | ||
79c896a1 | 48 | fio_setaffinity(gettid(), fio_gtod_cpumask); |
39ab7da2 JA |
49 | fio_mutex_up(mutex); |
50 | ||
51 | /* | |
52 | * As long as we have jobs around, update the clock. It would be nice | |
53 | * to have some way of NOT hammering that CPU with gettimeofday(), | |
54 | * but I'm not sure what to use outside of a simple CPU nop to relax | |
55 | * it - we don't want to lose precision. | |
56 | */ | |
57 | while (threads) { | |
58 | fio_gtod_update(); | |
59 | nop; | |
60 | } | |
61 | ||
62 | return NULL; | |
63 | } | |
64 | ||
65 | int fio_start_gtod_thread(void) | |
66 | { | |
67 | struct fio_mutex *mutex; | |
68 | pthread_attr_t attr; | |
69 | int ret; | |
70 | ||
71 | mutex = fio_mutex_init(FIO_MUTEX_LOCKED); | |
72 | if (!mutex) | |
73 | return 1; | |
74 | ||
75 | pthread_attr_init(&attr); | |
76 | pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); | |
80fa0520 | 77 | ret = pthread_create(>od_thread, &attr, gtod_thread_main, mutex); |
39ab7da2 JA |
78 | pthread_attr_destroy(&attr); |
79 | if (ret) { | |
80 | log_err("Can't create gtod thread: %s\n", strerror(ret)); | |
81 | goto err; | |
82 | } | |
83 | ||
84 | ret = pthread_detach(gtod_thread); | |
85 | if (ret) { | |
86 | log_err("Can't detatch gtod thread: %s\n", strerror(ret)); | |
87 | goto err; | |
88 | } | |
89 | ||
90 | dprint(FD_MUTEX, "wait on startup_mutex\n"); | |
91 | fio_mutex_down(mutex); | |
92 | dprint(FD_MUTEX, "done waiting on startup_mutex\n"); | |
93 | err: | |
94 | fio_mutex_remove(mutex); | |
95 | return ret; | |
96 | } | |
97 | ||
79c896a1 JA |
98 | void fio_gtod_set_cpu(unsigned int cpu) |
99 | { | |
2a2f27b8 | 100 | #ifdef FIO_HAVE_CPU_AFFINITY |
79c896a1 | 101 | fio_cpu_set(&fio_gtod_cpumask, cpu); |
2a2f27b8 | 102 | #endif |
79c896a1 | 103 | } |