Make the cgsleep functions build on windows.
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 171 172
diff --git a/configure.ac b/configure.ac
index ddf5cae..938e589 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,7 @@ case $target in
DLOPEN_FLAGS=""
WS2_LIBS="-lws2_32"
MM_LIBS="-lwinmm"
+ RT_LIBS=""
AC_DEFINE([_WIN32_WINNT], [0x0501], "WinNT version for XP+ support")
;;
powerpc-*-darwin*)
diff --git a/util.c b/util.c
index a84d278..6537582 100644
--- a/util.c
+++ b/util.c
@@ -885,83 +885,111 @@ void timeraddspec(struct timespec *a, const struct timespec *b)
/* These are cgminer specific sleep functions that use an absolute nanosecond
* resolution timer to avoid pool usleep accuracy and overruns. */
-void cgsleep_ms(int ms)
+#ifdef CLOCK_MONOTONIC
+void cgsleep_prepare_r(struct timespec *ts_start)
+{
+ clock_gettime(CLOCK_MONOTONIC, ts_start);
+}
+
+static void nanosleep_abstime(struct timespec *ts_end)
{
- struct timespec ts_start, ts_end;
int ret;
-#ifdef WIN32
- timeBeginPeriod(1);
-#endif
- clock_gettime(CLOCK_MONOTONIC, &ts_start);
- ms_to_timespec(&ts_end, ms);
- timeraddspec(&ts_end, &ts_start);
do {
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_end, NULL);
+ ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_end, NULL);
} while (ret == EINTR);
-#ifdef WIN32
- timeEndPeriod(1);
-#endif
}
-
-void cgsleep_us(int64_t us)
+#else
+void cgsleep_prepare_r(struct timespec *ts_start)
{
- struct timespec ts_start, ts_end;
- int ret;
+ struct timeval tv_start;
#ifdef WIN32
timeBeginPeriod(1);
#endif
- clock_gettime(CLOCK_MONOTONIC, &ts_start);
- us_to_timespec(&ts_end, us);
- timeraddspec(&ts_end, &ts_start);
- do {
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_end, NULL);
- } while (ret == EINTR);
+ gettimeofday(&tv_start, NULL);
+ timeval_to_spec(ts_start, &tv_start);
+}
+
+static uint64_t timespec_to_ns(struct timespec *ts)
+{
+ uint64_t ret;
+
+ ret = (uint64_t)ts->tv_sec * 1000000000;
+ ret += ts->tv_nsec;
+ return ret;
+}
+
+static uint64_t timeval_to_ns(struct timeval *tv)
+{
+ uint64_t ret;
+
+ ret = (uint64_t)tv->tv_sec * 1000000000;
+ ret += tv->tv_usec * 1000;
+ return ret;
+}
+
+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);
+}
+
+static void nanosleep_abstime(struct timespec *ts_end)
+{
+ uint64_t now_ns, end_ns, diff_ns;
+ 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))
+ return;
+ diff_ns = end_ns - now_ns;
+ ns_to_timespec(&ts_diff, diff_ns);
+ nanosleep(&ts_diff, NULL);
#ifdef WIN32
timeEndPeriod(1);
#endif
}
+#endif
/* Reentrant version of cgsleep functions allow start time to be set separately
* from the beginning of the actual sleep, allowing scheduling delays to be
* counted in the sleep. */
-void cgsleep_prepare_r(struct timespec *ts_start)
-{
-#ifdef WIN32
- timeBeginPeriod(1);
-#endif
- clock_gettime(CLOCK_MONOTONIC, ts_start);
-}
-
void cgsleep_ms_r(struct timespec *ts_start, int ms)
{
struct timespec ts_end;
- int ret;
ms_to_timespec(&ts_end, ms);
timeraddspec(&ts_end, ts_start);
- do {
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_end, NULL);
- } while (ret == EINTR);
-#ifdef WIN32
- timeEndPeriod(1);
-#endif
+ nanosleep_abstime(&ts_end);
}
void cgsleep_us_r(struct timespec *ts_start, int us)
{
struct timespec ts_end;
- int ret;
us_to_timespec(&ts_end, us);
timeraddspec(&ts_end, ts_start);
- do {
- ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts_end, NULL);
- } while (ret == EINTR);
-#ifdef WIN32
- timeEndPeriod(1);
-#endif
+ nanosleep_abstime(&ts_end);
+}
+
+void cgsleep_ms(int ms)
+{
+ struct timespec ts_start;
+
+ cgsleep_prepare_r(&ts_start);
+ cgsleep_ms_r(&ts_start, ms);
+}
+
+void cgsleep_us(int64_t us)
+{
+ struct timespec ts_start;
+
+ cgsleep_prepare_r(&ts_start);
+ cgsleep_us_r(&ts_start, us);
}
/* Provide a ms based sleep that uses nanosleep to avoid poor usleep accuracy