Commit 0b5edb24f9be881a26588b84fa1a713a757c9906

Con Kolivas 2013-08-18T10:36:25

Make the nmsleep and nusleep functions use the new cgsleep functions internally till functions are migrated to the new cgsleep API.

diff --git a/util.c b/util.c
index 77956e3..6b72823 100644
--- a/util.c
+++ b/util.c
@@ -804,53 +804,6 @@ void thr_info_cancel(struct thr_info *thr)
 	cgsem_destroy(&thr->sem);
 }
 
-/* Provide a ms based sleep that uses nanosleep to avoid poor usleep accuracy
- * on SMP machines */
-void nmsleep(unsigned int msecs)
-{
-	struct timespec twait, tleft;
-	int ret;
-	ldiv_t d;
-
-#ifdef WIN32
-	timeBeginPeriod(1);
-#endif
-	d = ldiv(msecs, 1000);
-	tleft.tv_sec = d.quot;
-	tleft.tv_nsec = d.rem * 1000000;
-	do {
-		twait.tv_sec = tleft.tv_sec;
-		twait.tv_nsec = tleft.tv_nsec;
-		ret = nanosleep(&twait, &tleft);
-	} while (ret == -1 && errno == EINTR);
-#ifdef WIN32
-	timeEndPeriod(1);
-#endif
-}
-
-/* Same for usecs */
-void nusleep(unsigned int usecs)
-{
-	struct timespec twait, tleft;
-	int ret;
-	ldiv_t d;
-
-#ifdef WIN32
-	timeBeginPeriod(1);
-#endif
-	d = ldiv(usecs, 1000000);
-	tleft.tv_sec = d.quot;
-	tleft.tv_nsec = d.rem * 1000;
-	do {
-		twait.tv_sec = tleft.tv_sec;
-		twait.tv_nsec = tleft.tv_nsec;
-		ret = nanosleep(&twait, &tleft);
-	} while (ret == -1 && errno == EINTR);
-#ifdef WIN32
-	timeEndPeriod(1);
-#endif
-}
-
 /* 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. */
@@ -930,6 +883,8 @@ 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)
 {
 	struct timespec ts_start, ts_end;
@@ -943,6 +898,44 @@ void cgsleep_ms(int ms)
 	} while (ret == EINTR);
 }
 
+void cgsleep_us(int64_t us)
+{
+	struct timespec ts_start, ts_end;
+	int ret;
+
+	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);
+}
+
+/* Provide a ms based sleep that uses nanosleep to avoid poor usleep accuracy
+ * on SMP machines */
+void nmsleep(unsigned int msecs)
+{
+#ifdef WIN32
+	timeBeginPeriod(1);
+#endif
+	cgsleep_ms((int)msecs);
+#ifdef WIN32
+	timeEndPeriod(1);
+#endif
+}
+
+/* Same for usecs */
+void nusleep(unsigned int usecs)
+{
+#ifdef WIN32
+	timeBeginPeriod(1);
+#endif
+	cgsleep_us((int64_t)usecs);
+#ifdef WIN32
+	timeEndPeriod(1);
+#endif
+}
+
 /* Returns the microseconds difference between end and start times as a double */
 double us_tdiff(struct timeval *end, struct timeval *start)
 {
diff --git a/util.h b/util.h
index e5d2e44..9d8e90f 100644
--- a/util.h
+++ b/util.h
@@ -85,6 +85,7 @@ void us_to_timespec(struct timespec *spec, int64_t us);
 void ms_to_timespec(struct timespec *spec, int64_t ms);
 void timeraddspec(struct timespec *a, const struct timespec *b);
 void cgsleep_ms(int ms);
+void cgsleep_us(int64_t us);
 double us_tdiff(struct timeval *end, struct timeval *start);
 double tdiff(struct timeval *end, struct timeval *start);
 bool stratum_send(struct pool *pool, char *s, ssize_t len);