Commit a4c96d759a84929beb6f9307848f89798d10a03d

Con Kolivas 2013-11-05T21:09:08

Use cgsem timed waits in avalon driver to not miss any queued wake ups to account for async messages coming during a flush work.

diff --git a/driver-avalon.c b/driver-avalon.c
index 796085a..f634d0c 100644
--- a/driver-avalon.c
+++ b/driver-avalon.c
@@ -1187,9 +1187,10 @@ static void *avalon_send_tasks(void *userdata)
 		}
 
 		avalon_rotate_array(avalon);
-		pthread_cond_signal(&info->qcond);
 		mutex_unlock(&info->qlock);
 
+		cgsem_post(&info->qsem);
+
 		if (unlikely(idled)) {
 			applog(LOG_WARNING, "%s%i: Idled %d miners",
 			       avalon->drv->name, avalon->device_id, idled);
@@ -1271,9 +1272,10 @@ static void *bitburner_send_tasks(void *userdata)
 		}
 
 		bitburner_rotate_array(avalon);
-		pthread_cond_signal(&info->qcond);
 		mutex_unlock(&info->qlock);
 
+		cgsem_post(&info->qsem);
+
 		if (unlikely(idled)) {
 			applog(LOG_WARNING, "%s%i: Idled %d miners",
 			       avalon->drv->name, avalon->device_id, idled);
@@ -1303,8 +1305,7 @@ static bool avalon_prepare(struct thr_info *thr)
 	info->thr = thr;
 	mutex_init(&info->lock);
 	mutex_init(&info->qlock);
-	if (unlikely(pthread_cond_init(&info->qcond, NULL)))
-		quit(1, "Failed to pthread_cond_init avalon qcond");
+	cgsem_init(&info->qsem);
 
 	if (pthread_create(&info->read_thr, NULL, avalon_get_results, (void *)avalon))
 		quit(1, "Failed to create avalon read_thr");
@@ -1513,22 +1514,15 @@ static int64_t avalon_scanhash(struct thr_info *thr)
 	struct cgpu_info *avalon = thr->cgpu;
 	struct avalon_info *info = avalon->device_data;
 	const int miner_count = info->miner_count;
-	struct timeval now, then, tdiff;
-	int64_t hash_count, us_timeout;
-	struct timespec abstime;
+	int64_t hash_count, ms_timeout;
 
 	/* Half nonce range */
-	us_timeout = 0x80000000ll / info->asic_count / info->frequency;
-	us_to_timeval(&tdiff, us_timeout);
-	cgtime(&now);
-	timeradd(&now, &tdiff, &then);
-	timeval_to_spec(&abstime, &then);
+	ms_timeout = 0x80000000ll / info->asic_count / info->frequency / 1000;
 
 	/* Wait until avalon_send_tasks signals us that it has completed
-	 * sending its work or a full nonce range timeout has occurred */
-	mutex_lock(&info->qlock);
-	pthread_cond_timedwait(&info->qcond, &info->qlock, &abstime);
-	mutex_unlock(&info->qlock);
+	 * sending its work or a full nonce range timeout has occurred. We use
+	 * cgsems to never miss a wakeup. */
+	cgsem_mswait(&info->qsem, ms_timeout);
 
 	mutex_lock(&info->lock);
 	hash_count = 0xffffffffull * (uint64_t)info->nonces;
@@ -1567,8 +1561,10 @@ static void avalon_flush_work(struct cgpu_info *avalon)
 	mutex_lock(&info->qlock);
 	/* Will overwrite any work queued */
 	avalon->queued = 0;
-	pthread_cond_signal(&info->qcond);
 	mutex_unlock(&info->qlock);
+
+	/* Signal main loop we need more work */
+	cgsem_post(&info->qsem);
 }
 
 static struct api_data *avalon_api_stats(struct cgpu_info *cgpu)
diff --git a/driver-avalon.h b/driver-avalon.h
index e84ddbb..05ad849 100644
--- a/driver-avalon.h
+++ b/driver-avalon.h
@@ -145,7 +145,7 @@ struct avalon_info {
 	pthread_t write_thr;
 	pthread_mutex_t lock;
 	pthread_mutex_t qlock;
-	pthread_cond_t qcond;
+	cgsem_t qsem;
 	int nonces;
 
 	int auto_queued;