Commit fd7b21ed56b9dcfa9082bdcf95ad382f2916f0e3

ckolivas 2012-07-02T10:54:20

Use a pthread conditional that is broadcast whenever work restarts are required. Create a generic wait function waiting a specified time on that conditional that returns if the condition is met or a specified time passed to it has elapsed. Use this to do smarter polling in bitforce to abort work, queue more work, and check for results to minimise time spent working needlessly.

diff --git a/cgminer.c b/cgminer.c
index 09e5dd7..043ee12 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -174,6 +174,9 @@ pthread_rwlock_t netacc_lock;
 static pthread_mutex_t lp_lock;
 static pthread_cond_t lp_cond;
 
+pthread_mutex_t restart_lock;
+pthread_cond_t restart_cond;
+
 double total_mhashes_done;
 static struct timeval total_tv_start, total_tv_end;
 
@@ -2472,8 +2475,26 @@ static void discard_stale(void)
 	subtract_queued(nonclone);
 }
 
-static bool queue_request(struct thr_info *thr, bool needed);
+bool queue_request(struct thr_info *thr, bool needed);
 
+/* A generic wait function for threads that poll that will wait a specified
+ * time tdiff waiting on the pthread conditional that is broadcast when a
+ * work restart is required. Returns the value of pthread_cond_timedwait
+ * which is zero if the condition was met or ETIMEDOUT if not.
+ */
+int restart_wait(struct timeval *tdiff)
+{
+	struct timeval now, then;
+	struct timespec abstime;
+
+	gettimeofday(&now, NULL);
+	timeradd(&now, tdiff, &then);
+	abstime.tv_sec = then.tv_sec;
+	abstime.tv_nsec = then.tv_usec * 1000;
+	mutex_lock(&restart_lock);
+	return pthread_cond_timedwait(&restart_cond, &restart_lock, &abstime);
+}
+	
 static void restart_threads(void)
 {
 	int i;
@@ -2485,6 +2506,10 @@ static void restart_threads(void)
 
 	for (i = 0; i < mining_threads; i++)
 		work_restart[i].restart = 1;
+
+	mutex_lock(&restart_lock);
+	pthread_cond_broadcast(&restart_cond);
+	mutex_unlock(&restart_lock);
 }
 
 static void set_curblock(char *hexstr, unsigned char *hash)
@@ -3568,7 +3593,7 @@ static void control_tclear(bool *var)
 
 static bool queueing;
 
-static bool queue_request(struct thr_info *thr, bool needed)
+bool queue_request(struct thr_info *thr, bool needed)
 {
 	struct workio_cmd *wc;
 	struct timeval now;
@@ -4997,6 +5022,10 @@ int main(int argc, char *argv[])
 	if (unlikely(pthread_cond_init(&lp_cond, NULL)))
 		quit(1, "Failed to pthread_cond_init lp_cond");
 
+	mutex_init(&restart_lock);
+	if (unlikely(pthread_cond_init(&restart_cond, NULL)))
+		quit(1, "Failed to pthread_cond_init restart_cond");
+
 	sprintf(packagename, "%s %s", PACKAGE, VERSION);
 
 #ifdef WANT_CPUMINE
diff --git a/driver-bitforce.c b/driver-bitforce.c
index 08595a7..902b5a3 100644
--- a/driver-bitforce.c
+++ b/driver-bitforce.c
@@ -139,6 +139,7 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
 
 	char pdevbuf[0x100];
 	unsigned char ob[61] = ">>>>>>>>12345678901234567890123456789012123456789012>>>>>>>>";
+	struct timeval tdiff;
 	int i;
 	char *pnoncebuf;
 	char *s;
@@ -195,9 +196,28 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
 		}
 	}
 
-	usleep(4500000);
-	i = 4500;
-	while (1) {
+	/* Initially wait 2/3 of the average cycle time so we can request more
+	 * work before full scan is up ~ 3.4 seconds */
+	tdiff.tv_sec = 3;
+	tdiff.tv_usec = 4000000;
+	if (!restart_wait(&tdiff))
+		return 0;
+	queue_request(thr, false);
+	i = 3400;
+
+	/* Now wait another second; no bistream should be finished by now */
+	tdiff.tv_sec = 1;
+	tdiff.tv_usec = 0;
+	if (!restart_wait(&tdiff))
+		return 0;
+	i += 1000;
+
+	/* Now start looking for results. Stupid polling every 10ms... */
+	tdiff.tv_sec = 0;
+	tdiff.tv_usec = 10000;
+	while (42) {
+		int rc = restart_wait(&tdiff);
+
 		BFwrite(fdDev, "ZFX", 3);
 		BFgets(pdevbuf, sizeof(pdevbuf), fdDev);
 		if (unlikely(!pdevbuf[0])) {
@@ -206,7 +226,8 @@ static uint64_t bitforce_scanhash(struct thr_info *thr, struct work *work, uint6
 		}
 		if (pdevbuf[0] != 'B')
 		    break;
-		usleep(10000);
+		if (!rc)
+			return 0;
 		i += 10;
 	}
 	applog(LOG_DEBUG, "BitForce waited %dms until %s\n", i, pdevbuf);
diff --git a/miner.h b/miner.h
index 0520cbc..9965a98 100644
--- a/miner.h
+++ b/miner.h
@@ -559,7 +559,12 @@ struct work_restart {
 	char			padding[128 - sizeof(unsigned long)];
 };
 
+extern pthread_mutex_t restart_lock;
+extern pthread_cond_t restart_cond;
+
 extern void thread_reportin(struct thr_info *thr);
+extern bool queue_request(struct thr_info *thr, bool needed);
+extern int restart_wait(struct timeval *tdiff);
 
 extern void kill_work(void);