On windows use the higher accuracy timegettime function to really get 1ms clock and timer accuracy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
diff --git a/util.c b/util.c
index ad32279..2f92a61 100644
--- a/util.c
+++ b/util.c
@@ -807,16 +807,30 @@ void thr_info_cancel(struct thr_info *thr)
/* This is a cgminer gettimeofday wrapper. Since we always call gettimeofday
* with tz set to NULL, and windows' default resolution is only 15ms, this
* gives us higher resolution times on windows. */
+#ifndef WIN32
void cgtime(struct timeval *tv)
{
-#ifdef WIN32
- timeBeginPeriod(1);
-#endif
gettimeofday(tv, NULL);
-#ifdef WIN32
- timeEndPeriod(1);
-#endif
}
+#else
+static void dtime_to_timeval(struct timeval *tv, DWORD dtime)
+{
+ ldiv_t tvdiv = ldiv(dtime, 1000);
+
+ tv->tv_sec = tvdiv.quot;
+ tv->tv_usec = tvdiv.rem * 1000;
+}
+
+void cgtime(struct timeval *tv)
+{
+ DWORD dtime;
+
+ //timeBeginPeriod(1);
+ dtime = timeGetTime();
+ //timeEndPeriod(1);
+ dtime_to_timeval(tv, dtime);
+}
+#endif
void subtime(struct timeval *a, struct timeval *b)
{
@@ -857,27 +871,33 @@ void timeval_to_spec(struct timespec *spec, const struct timeval *val)
void us_to_timeval(struct timeval *val, int64_t us)
{
- val->tv_sec = us / 1000000;
- val->tv_usec = us - (val->tv_sec * 1000000);
+ lldiv_t tvdiv = lldiv(us, 1000000);
+
+ val->tv_sec = tvdiv.quot;
+ val->tv_usec = tvdiv.rem;
}
void us_to_timespec(struct timespec *spec, int64_t us)
{
- spec->tv_sec = us / 1000000;
- spec->tv_nsec = (us - (spec->tv_sec * 1000000)) * 1000;
+ lldiv_t tvdiv = lldiv(us, 1000000);
+
+ spec->tv_sec = tvdiv.quot;
+ spec->tv_nsec = tvdiv.rem * 1000;
}
void ms_to_timespec(struct timespec *spec, int64_t ms)
{
- spec->tv_sec = ms / 1000;
- spec->tv_nsec = (ms - (spec->tv_sec * 1000)) * 1000000;
+ lldiv_t tvdiv = lldiv(ms, 1000);
+
+ spec->tv_sec = tvdiv.quot;
+ spec->tv_nsec = tvdiv.quot * 1000000;
}
void timeraddspec(struct timespec *a, const struct timespec *b)
{
a->tv_sec += b->tv_sec;
a->tv_nsec += b->tv_nsec;
- if (a->tv_nsec >+ 1000000000) {
+ if (a->tv_nsec >= 1000000000) {
a->tv_nsec -= 1000000000;
a->tv_sec++;
}
@@ -885,7 +905,7 @@ void timeraddspec(struct timespec *a, const struct timespec *b)
/* These are cgminer specific sleep functions that use an absolute nanosecond
* resolution timer to avoid poor usleep accuracy and overruns. */
-#ifdef CLOCK_MONOTONIC
+#ifndef WIN32
void cgsleep_prepare_r(struct timespec *ts_start)
{
clock_gettime(CLOCK_MONOTONIC, ts_start);
@@ -900,59 +920,46 @@ static void nanosleep_abstime(struct timespec *ts_end)
} while (ret == EINTR);
}
#else
-void cgsleep_prepare_r(struct timespec *ts_start)
+static void dtime_to_timespec(struct timespec *ts, DWORD dtime)
{
- struct timeval tv_start;
+ ldiv_t tsdiv = ldiv(dtime, 1000);
-#ifdef WIN32
- timeBeginPeriod(1);
-#endif
- gettimeofday(&tv_start, NULL);
- timeval_to_spec(ts_start, &tv_start);
+ ts->tv_sec = tsdiv.quot;
+ ts->tv_nsec = tsdiv.rem * 1000000;
}
-static uint64_t timespec_to_ns(struct timespec *ts)
+static DWORD timespec_to_dtime(const struct timespec *ts)
{
- uint64_t ret;
+ DWORD ret;
- ret = (uint64_t)ts->tv_sec * 1000000000;
- ret += ts->tv_nsec;
+ ret = ts->tv_sec * 1000;
+ ret += ts->tv_nsec / 1000000;
return ret;
}
-static uint64_t timeval_to_ns(struct timeval *tv)
+void cgsleep_prepare_r(struct timespec *ts_start)
{
- uint64_t ret;
-
- ret = (uint64_t)tv->tv_sec * 1000000000;
- ret += tv->tv_usec * 1000;
- return ret;
-}
+ DWORD dtime;
-static void ns_to_timespec(struct timespec *ts, uint64_t ns)
-{
- ts->tv_sec = ns / 1000000000;
- ts->tv_nsec = ns - ((uint64_t)ts->tv_sec * 1000000000ull);
+ timeBeginPeriod(1);
+ dtime = timeGetTime();
+ dtime_to_timespec(ts_start, dtime);
}
static void nanosleep_abstime(struct timespec *ts_end)
{
- uint64_t now_ns, end_ns, diff_ns;
+ DWORD now_ms, end_ms, diff_ms;
struct timespec ts_diff;
- struct timeval now;
- end_ns = timespec_to_ns(ts_end);
- gettimeofday(&now, NULL);
- now_ns = timeval_to_ns(&now);
- if (unlikely(now_ns >= end_ns))
+ end_ms = timespec_to_dtime(ts_end);
+ now_ms = timeGetTime();
+ if (unlikely(now_ms >= end_ms))
goto out;
- diff_ns = end_ns - now_ns;
- ns_to_timespec(&ts_diff, diff_ns);
+ diff_ms = end_ms - now_ms;
+ dtime_to_timespec(&ts_diff, diff_ms);
nanosleep(&ts_diff, NULL);
out:
-#ifdef WIN32
timeEndPeriod(1);
-#endif
}
#endif