Browse Source

Further integrate cgsleep API into BFGMiner's timer system, so clock_nanosleep is only used on platforms with CLOCK_MONOTONIC

Luke Dashjr 12 years ago
parent
commit
c0fe28a556
2 changed files with 37 additions and 72 deletions
  1. 36 71
      util.c
  2. 1 1
      util.h

+ 36 - 71
util.c

@@ -1054,6 +1054,7 @@ void setup_pthread_cancel_workaround()
 #endif
 #endif
 
 
 static void _now_gettimeofday(struct timeval *);
 static void _now_gettimeofday(struct timeval *);
+static void _cgsleep_us_r_nanosleep(cgtimer_t *, int64_t);
 
 
 #ifdef HAVE_POOR_GETTIMEOFDAY
 #ifdef HAVE_POOR_GETTIMEOFDAY
 static struct timeval tv_timeofday_offset;
 static struct timeval tv_timeofday_offset;
@@ -1116,6 +1117,7 @@ void _now_is_not_set(__maybe_unused struct timeval *tv)
 }
 }
 
 
 void (*timer_set_now)(struct timeval *tv) = _now_is_not_set;
 void (*timer_set_now)(struct timeval *tv) = _now_is_not_set;
+void (*cgsleep_us_r)(cgtimer_t *, int64_t) = _cgsleep_us_r_nanosleep;
 
 
 #ifdef HAVE_CLOCK_GETTIME_MONOTONIC
 #ifdef HAVE_CLOCK_GETTIME_MONOTONIC
 static clockid_t bfg_timer_clk;
 static clockid_t bfg_timer_clk;
@@ -1133,6 +1135,20 @@ void _now_clock_gettime(struct timeval *tv)
 	};
 	};
 }
 }
 
 
+static
+void _cgsleep_us_r_monotonic(cgtimer_t *tv_start, int64_t us)
+{
+	struct timeval tv_end[1];
+	struct timespec ts_end[1];
+	int ret;
+	
+	timer_set_delay(tv_end, tv_start, us);
+	timeval_to_spec(ts_end, tv_end);
+	do {
+		ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_end, NULL);
+	} while (ret == EINTR);
+}
+
 static
 static
 bool _bfg_try_clock_gettime(clockid_t clk)
 bool _bfg_try_clock_gettime(clockid_t clk)
 {
 {
@@ -1158,7 +1174,10 @@ void bfg_init_time()
 	else
 	else
 #endif
 #endif
 	if (_bfg_try_clock_gettime(CLOCK_MONOTONIC))
 	if (_bfg_try_clock_gettime(CLOCK_MONOTONIC))
+	{
 		applog(LOG_DEBUG, "Timers: Using clock_gettime(CLOCK_MONOTONIC)");
 		applog(LOG_DEBUG, "Timers: Using clock_gettime(CLOCK_MONOTONIC)");
+		cgsleep_us_r = _cgsleep_us_r_monotonic;
+	}
 	else
 	else
 #endif
 #endif
 #ifdef WIN32
 #ifdef WIN32
@@ -1255,40 +1274,6 @@ void timeraddspec(struct timespec *a, const struct timespec *b)
 }
 }
 
 
 #ifndef WIN32
 #ifndef WIN32
-static void nanosleep_abstime(struct timespec *ts_end)
-{
-	int ret;
-
-	do {
-		ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, ts_end, NULL);
-	} while (ret == EINTR);
-}
-
-/* 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_ms_r(cgtimer_t *tv_start, int ms)
-{
-	struct timespec ts_start[1];
-	struct timespec ts_end;
-
-	timeval_to_spec(ts_start, tv_start);
-	ms_to_timespec(&ts_end, ms);
-	timeraddspec(&ts_end, ts_start);
-	nanosleep_abstime(&ts_end);
-}
-
-void cgsleep_us_r(cgtimer_t *tv_start, int64_t us)
-{
-	struct timespec ts_start[1];
-	struct timespec ts_end;
-
-	timeval_to_spec(ts_start, tv_start);
-	us_to_timespec(&ts_end, us);
-	timeraddspec(&ts_end, ts_start);
-	nanosleep_abstime(&ts_end);
-}
-
 static
 static
 void _now_gettimeofday(struct timeval *tv)
 void _now_gettimeofday(struct timeval *tv)
 {
 {
@@ -1321,50 +1306,30 @@ void _now_gettimeofday(struct timeval *tv)
 	tv->tv_sec = lidiv.quot;
 	tv->tv_sec = lidiv.quot;
 	tv->tv_usec = lidiv.rem / 10;
 	tv->tv_usec = lidiv.rem / 10;
 }
 }
-
-/* Subtract b from a */
-static void timersubspec(struct timespec *a, const struct timespec *b)
-{
-	a->tv_sec -= b->tv_sec;
-	a->tv_nsec -= b->tv_nsec;
-	if (a->tv_nsec < 0) {
-		a->tv_nsec += 1000000000;
-		a->tv_sec--;
-	}
-}
-
-static void cgsleep_spec(struct timespec *ts_diff, const struct timespec *ts_start)
-{
-	struct timespec now;
-
-	timeraddspec(ts_diff, ts_start);
-	cgtimer_time(&now);
-	timersubspec(ts_diff, &now);
-	if (unlikely(ts_diff->tv_sec < 0))
-		return;
-	nanosleep(ts_diff, NULL);
-}
+#endif
 
 
 void cgsleep_ms_r(cgtimer_t *tv_start, int ms)
 void cgsleep_ms_r(cgtimer_t *tv_start, int ms)
 {
 {
-	struct timespec ts_start;
-	struct timespec ts_diff;
-
-	timeval_to_spec(&ts_start, tv_start);
-	ms_to_timespec(&ts_diff, ms);
-	cgsleep_spec(&ts_diff, ts_start);
+	cgsleep_us_r(tv_start, ((int64_t)ms) * 1000);
 }
 }
 
 
-void cgsleep_us_r(cgtimer_t *tv_start, int64_t us)
+static
+void _cgsleep_us_r_nanosleep(cgtimer_t *tv_start, int64_t us)
 {
 {
-	struct timespec ts_start;
-	struct timespec ts_diff;
-
-	timeval_to_spec(&ts_start, tv_start);
-	us_to_timespec(&ts_diff, us);
-	cgsleep_spec(&ts_diff, ts_start);
+	struct timeval tv_timer[1], tv[1];
+	struct timespec ts[1];
+	
+	timer_set_delay(tv_timer, tv_start, us);
+	while (true)
+	{
+		timer_set_now(tv);
+		if (!timercmp(tv_timer, tv, >))
+			return;
+		timersub(tv_timer, tv, tv);
+		timeval_to_spec(ts, tv);
+		nanosleep(ts, NULL);
+	}
 }
 }
-#endif
 
 
 void cgsleep_ms(int ms)
 void cgsleep_ms(int ms)
 {
 {

+ 1 - 1
util.h

@@ -135,7 +135,7 @@ void cgsleep_us(int64_t us);
 #define cgtimer_time(ts_start) timer_set_now(ts_start)
 #define cgtimer_time(ts_start) timer_set_now(ts_start)
 #define cgsleep_prepare_r(ts_start) cgtimer_time(ts_start)
 #define cgsleep_prepare_r(ts_start) cgtimer_time(ts_start)
 void cgsleep_ms_r(cgtimer_t *ts_start, int ms);
 void cgsleep_ms_r(cgtimer_t *ts_start, int ms);
-void cgsleep_us_r(cgtimer_t *ts_start, int64_t us);
+void (*cgsleep_us_r)(cgtimer_t *ts_start, int64_t us);
 
 
 static inline
 static inline
 int cgtimer_to_ms(cgtimer_t *cgt)
 int cgtimer_to_ms(cgtimer_t *cgt)