Browse Source

Merge commit '2e2033a' into bfgminer

Luke Dashjr 10 years ago
parent
commit
87723cfd41
6 changed files with 115 additions and 63 deletions
  1. 0 1
      driver-avalonmm.c
  2. 70 41
      driver-stratum.c
  3. 28 18
      miner.c
  4. 1 0
      miner.h
  5. 15 3
      work2d.c
  6. 1 0
      work2d.h

+ 0 - 1
driver-avalonmm.c

@@ -509,7 +509,6 @@ bool avalonmm_update_swork_from_pool(struct cgpu_info * const master_dev, struct
 	stratum_work_cpy(&mmjob->swork, &pool->swork);
 	cg_runlock(&pool->data_lock);
 	timer_set_now(&mmjob->tv_prepared);
-	mmjob->swork.data_lock_p = NULL;
 	if (!avalonmm_send_swork(fd, chain, &mmjob->swork, mmjob->jobid, &mmjob->nonce_diff))
 	{
 		avalonmm_free_job(mmjob);

+ 70 - 41
driver-stratum.c

@@ -101,8 +101,6 @@ void stratumsrv_send_set_difficulty(struct stratumsrv_conn * const conn, const f
 	bufferevent_write(bev, buf, bufsz);
 }
 
-#define _ssm_gen_dummy_work work2d_gen_dummy_work
-
 static
 float stratumsrv_choose_share_pdiff(const struct stratumsrv_conn * const conn, const struct mining_algorithm * const malgo)
 {
@@ -112,27 +110,75 @@ float stratumsrv_choose_share_pdiff(const struct stratumsrv_conn * const conn, c
 	return conn_pdiff;
 }
 
+static void stratumsrv_boot_all_subscribed(const char *);
+static void _ssj_free(struct stratumsrv_job *);
+static void stratumsrv_job_pruner();
+
 static
-bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
+bool stratumsrv_update_notify_str(struct pool * const pool)
 {
+	const bool clean = _ssm_cur_job_work.pool ? stale_work(&_ssm_cur_job_work, true) : true;
+	struct timeval tv_now;
+	
 	cg_rlock(&pool->data_lock);
 	
+	if (!pool_has_usable_swork(pool))
+	{
+fail:
+		cg_runlock(&pool->data_lock);
+		applog(LOG_WARNING, "SSM: No usable 2D work upstream!");
+		if (clean)
+			stratumsrv_boot_all_subscribed("Current upstream pool does not have usable 2D work");
+		return false;
+	}
+	
+	timer_set_now(&tv_now);
+	
+	{
+		struct work work;
+		work2d_gen_dummy_work_for_stale_check(&work, &pool->swork, &tv_now, NULL);
+		
+		const bool is_stale = stale_work(&work, false);
+		
+		clean_work(&work);
+		
+		if (is_stale) {
+			cg_runlock(&pool->data_lock);
+			applog(LOG_DEBUG, "SSM: Ignoring work update notification while pool %d has stale swork", pool->pool_no);
+			return false;
+		}
+	}
+	
 	struct stratumsrv_conn *conn;
 	const struct stratum_work * const swork = &pool->swork;
 	const int n2size = pool->swork.n2size;
+	const size_t coinb2_offset = swork->nonce2_offset + n2size;
+	const size_t coinb2_len = bytes_len(&swork->coinbase) - swork->nonce2_offset - n2size;
+	
+	if (_ssm_last_ssj &&
+	    !(memcmp(&swork->header1[0], &_ssm_last_ssj->swork.header1[0], 0x24)
+	   || swork->nonce2_offset != _ssm_last_ssj->swork.nonce2_offset
+	   || bytes_len(&swork->coinbase) != bytes_len(&_ssm_last_ssj->swork.coinbase)
+	   || memcmp(bytes_buf(&swork->coinbase), bytes_buf(&_ssm_last_ssj->swork.coinbase), swork->nonce2_offset)
+	   || memcmp(&bytes_buf(&swork->coinbase)[coinb2_offset], &bytes_buf(&_ssm_last_ssj->swork.coinbase)[coinb2_offset], coinb2_len)
+	   || memcmp(swork->diffbits, _ssm_last_ssj->swork.diffbits, 4)
+	)) {
+		cg_runlock(&pool->data_lock);
+		applog(LOG_DEBUG, "SSM: Updating with (near?-)identical work2d; skipping...");
+		return false;
+	}
+	
 	char my_job_id[33];
 	int i;
 	struct stratumsrv_job *ssj;
 	ssize_t n2pad = work2d_pad_xnonce_size(swork);
 	if (n2pad < 0)
 	{
-		cg_runlock(&pool->data_lock);
-		return false;
+		goto fail;
 	}
 	size_t coinb1in_lenx = swork->nonce2_offset * 2;
 	size_t n2padx = n2pad * 2;
 	size_t coinb1_lenx = coinb1in_lenx + n2padx;
-	size_t coinb2_len = bytes_len(&swork->coinbase) - swork->nonce2_offset - n2size;
 	size_t coinb2_lenx = coinb2_len * 2;
 	sprintf(my_job_id, "%"PRIx64"-%"PRIx64, (uint64_t)time(NULL), _ssm_jobid++);
 	// NOTE: The buffer has up to 2 extra/unused bytes:
@@ -147,7 +193,7 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
 	bin2hex(coinb1, bytes_buf(&swork->coinbase), swork->nonce2_offset);
 	work2d_pad_xnonce(&coinb1[coinb1in_lenx], swork, true);
 	coinb1[coinb1_lenx] = '\0';
-	bin2hex(coinb2, &bytes_buf(&swork->coinbase)[swork->nonce2_offset + n2size], coinb2_len);
+	bin2hex(coinb2, &bytes_buf(&swork->coinbase)[coinb2_offset], coinb2_len);
 	p += sprintf(p, "{\"params\":[\"%s\",\"%s\",\"%s\",\"%s\",[", my_job_id, prevhash, coinb1, coinb2);
 	for (i = 0; i < swork->merkles; ++i)
 	{
@@ -172,17 +218,30 @@ bool stratumsrv_update_notify_str(struct pool * const pool, bool clean)
 	*ssj = (struct stratumsrv_job){
 		.my_job_id = strdup(my_job_id),
 	};
-	timer_set_now(&ssj->tv_prepared);
+	ssj->tv_prepared = tv_now;
 	stratum_work_cpy(&ssj->swork, swork);
 	
 	cg_runlock(&pool->data_lock);
 	
-	ssj->swork.data_lock_p = NULL;
+	if (clean)
+	{
+		struct stratumsrv_job *ssj, *tmp;
+		
+		applog(LOG_DEBUG, "SSM: Current replacing job stale, pruning all jobs");
+		HASH_ITER(hh, _ssm_jobs, ssj, tmp)
+		{
+			HASH_DEL(_ssm_jobs, ssj);
+			_ssj_free(ssj);
+		}
+	}
+	else
+		stratumsrv_job_pruner();
+	
 	HASH_ADD_KEYPTR(hh, _ssm_jobs, ssj->my_job_id, strlen(ssj->my_job_id), ssj);
 	
 	if (likely(_ssm_cur_job_work.pool))
 		clean_work(&_ssm_cur_job_work);
-	_ssm_gen_dummy_work(&_ssm_cur_job_work, &ssj->swork, &ssj->tv_prepared, NULL, 0);
+	work2d_gen_dummy_work_for_stale_check(&_ssm_cur_job_work, &ssj->swork, &ssj->tv_prepared, NULL);
 	
 	_ssm_notify_sz = p - buf;
 	assert(_ssm_notify_sz <= bufsz);
@@ -329,7 +388,6 @@ static
 void _stratumsrv_update_notify(evutil_socket_t fd, short what, __maybe_unused void *p)
 {
 	struct pool *pool = current_pool();
-	bool clean;
 	
 	if (fd == _ssm_update_notifier[0])
 	{
@@ -338,37 +396,8 @@ void _stratumsrv_update_notify(evutil_socket_t fd, short what, __maybe_unused vo
 		applog(LOG_DEBUG, "SSM: Update triggered by notifier");
 	}
 	
-	clean = _ssm_cur_job_work.pool ? stale_work(&_ssm_cur_job_work, true) : true;
-	if (clean)
-	{
-		struct stratumsrv_job *ssj, *tmp;
-		
-		applog(LOG_DEBUG, "SSM: Current replacing job stale, pruning all jobs");
-		HASH_ITER(hh, _ssm_jobs, ssj, tmp)
-		{
-			HASH_DEL(_ssm_jobs, ssj);
-			_ssj_free(ssj);
-		}
-	}
-	else
-		stratumsrv_job_pruner();
-	
-	if (!pool_has_usable_swork(pool))
-	{
-		applog(LOG_WARNING, "SSM: No usable 2D work upstream!");
-		if (clean)
-			stratumsrv_boot_all_subscribed("Current upstream pool does not have usable 2D work");
-		goto out;
-	}
-	
-	if (!stratumsrv_update_notify_str(pool, clean))
-	{
-		applog(LOG_WARNING, "SSM: Failed to subdivide upstream stratum notify!");
-		if (clean)
-			stratumsrv_boot_all_subscribed("Current upstream pool does not have active stratum");
-	}
+	stratumsrv_update_notify_str(pool);
 	
-out: ;
 	struct timeval tv_scantime = {
 		.tv_sec = opt_scantime,
 	};

+ 28 - 18
miner.c

@@ -1173,6 +1173,7 @@ struct pool *add_pool2(struct mining_goal_info * const goal)
 	if (unlikely(pthread_cond_init(&pool->cr_cond, bfg_condattr)))
 		quit(1, "Failed to pthread_cond_init in add_pool");
 	cglock_init(&pool->data_lock);
+	pool->swork.data_lock_p = &pool->data_lock;
 	mutex_init(&pool->stratum_lock);
 	timer_unset(&pool->swork.tv_transparency);
 	pool->swork.pool = pool;
@@ -10272,6 +10273,7 @@ void stratum_work_cpy(struct stratum_work * const dst, const struct stratum_work
 	dst->job_id = maybe_strdup(src->job_id);
 	bytes_cpy(&dst->coinbase, &src->coinbase);
 	bytes_cpy(&dst->merkle_bin, &src->merkle_bin);
+	dst->data_lock_p = NULL;
 }
 
 void stratum_work_clean(struct stratum_work * const swork)
@@ -10306,7 +10308,6 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	clean_work(work);
 	
 	cg_wlock(&pool->data_lock);
-	pool->swork.data_lock_p = &pool->data_lock;
 	
 	const int n2size = pool->swork.n2size;
 	bytes_resize(&work->nonce2, n2size);
@@ -10331,11 +10332,8 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 
 void gen_stratum_work2(struct work *work, struct stratum_work *swork)
 {
-	unsigned char *coinbase, merkle_root[32], merkle_sha[64];
-	uint8_t *merkle_bin;
-	uint32_t *data32, *swap32;
-	int i;
-
+	unsigned char *coinbase;
+	
 	/* Generate coinbase */
 	coinbase = bytes_buf(&swork->coinbase);
 	memcpy(&coinbase[swork->nonce2_offset], bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
@@ -10343,7 +10341,29 @@ void gen_stratum_work2(struct work *work, struct stratum_work *swork)
 	/* Downgrade to a read lock to read off the variables */
 	if (swork->data_lock_p)
 		cg_dwlock(swork->data_lock_p);
+	
+	gen_stratum_work3(work, swork, swork->data_lock_p);
+	
+	if (opt_debug)
+	{
+		char header[161];
+		char nonce2hex[(bytes_len(&work->nonce2) * 2) + 1];
+		bin2hex(header, work->data, 80);
+		bin2hex(nonce2hex, bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
+		applog(LOG_DEBUG, "Generated stratum header %s", header);
+		applog(LOG_DEBUG, "Work job_id %s nonce2 %s", work->job_id, nonce2hex);
+	}
+}
 
+void gen_stratum_work3(struct work * const work, struct stratum_work * const swork, cglock_t * const data_lock_p)
+{
+	unsigned char *coinbase, merkle_root[32], merkle_sha[64];
+	uint8_t *merkle_bin;
+	uint32_t *data32, *swap32;
+	int i;
+	
+	coinbase = bytes_buf(&swork->coinbase);
+	
 	/* Generate merkle root */
 	gen_hash(coinbase, merkle_root, bytes_len(&swork->coinbase));
 	memcpy(merkle_sha, merkle_root, 32);
@@ -10370,18 +10390,8 @@ void gen_stratum_work2(struct work *work, struct stratum_work *swork)
 	memcpy(work->target, swork->target, sizeof(work->target));
 	work->job_id = maybe_strdup(swork->job_id);
 	work->nonce1 = maybe_strdup(swork->nonce1);
-	if (swork->data_lock_p)
-		cg_runlock(swork->data_lock_p);
-
-	if (opt_debug)
-	{
-		char header[161];
-		char nonce2hex[(bytes_len(&work->nonce2) * 2) + 1];
-		bin2hex(header, work->data, 80);
-		bin2hex(nonce2hex, bytes_buf(&work->nonce2), bytes_len(&work->nonce2));
-		applog(LOG_DEBUG, "Generated stratum header %s", header);
-		applog(LOG_DEBUG, "Work job_id %s nonce2 %s", work->job_id, nonce2hex);
-	}
+	if (data_lock_p)
+		cg_runlock(data_lock_p);
 
 	calc_midstate(work);
 

+ 1 - 0
miner.h

@@ -1543,6 +1543,7 @@ extern void stratum_work_cpy(struct stratum_work *dst, const struct stratum_work
 extern void stratum_work_clean(struct stratum_work *);
 extern bool pool_has_usable_swork(const struct pool *);
 extern void gen_stratum_work2(struct work *, struct stratum_work *);
+extern void gen_stratum_work3(struct work *, struct stratum_work *, cglock_t *data_lock_p);
 extern void inc_hw_errors3(struct thr_info *thr, const struct work *work, const uint32_t *bad_nonce_p, float nonce_diff);
 static inline
 void inc_hw_errors2(struct thr_info * const thr, const struct work * const work, const uint32_t *bad_nonce_p)

+ 15 - 3
work2d.c

@@ -71,15 +71,21 @@ void *work2d_pad_xnonce(void * const buf_, const struct stratum_work * const swo
 	return &buf[pad];
 }
 
-void work2d_gen_dummy_work(struct work * const work, struct stratum_work * const swork, const struct timeval * const tvp_prepared, const void * const xnonce2, const uint32_t xnonce1)
+static void work2d_gen_dummy_work_prepare(struct work * const work, struct stratum_work * const swork, const struct timeval * const tvp_prepared)
 {
-	uint8_t *p, *s;
-	
 	*work = (struct work){
 		.pool = swork->pool,
 		.work_restart_id = swork->work_restart_id,
 		.tv_staged = *tvp_prepared,
 	};
+}
+
+void work2d_gen_dummy_work(struct work * const work, struct stratum_work * const swork, const struct timeval * const tvp_prepared, const void * const xnonce2, const uint32_t xnonce1)
+{
+	uint8_t *p, *s;
+	
+	work2d_gen_dummy_work_prepare(work, swork, tvp_prepared);
+	
 	bytes_resize(&work->nonce2, swork->n2size);
 	s = bytes_buf(&work->nonce2);
 	p = &s[swork->n2size - work2d_xnonce2sz];
@@ -95,6 +101,12 @@ void work2d_gen_dummy_work(struct work * const work, struct stratum_work * const
 	gen_stratum_work2(work, swork);
 }
 
+void work2d_gen_dummy_work_for_stale_check(struct work * const work, struct stratum_work * const swork, const struct timeval * const tvp_prepared, cglock_t * const data_lock_p)
+{
+	work2d_gen_dummy_work_prepare(work, swork, tvp_prepared);
+	gen_stratum_work3(work, swork, data_lock_p);
+}
+
 bool work2d_submit_nonce(struct thr_info * const thr, struct stratum_work * const swork, const struct timeval * const tvp_prepared, const void * const xnonce2, const uint32_t xnonce1, const uint32_t nonce, const uint32_t ntime, bool * const out_is_stale, const float nonce_diff)
 {
 	struct work _work, *work;

+ 1 - 0
work2d.h

@@ -16,6 +16,7 @@ extern void release_work2d_(uint32_t xnonce1);
 extern int work2d_pad_xnonce_size(const struct stratum_work *);
 extern void *work2d_pad_xnonce(void *buf, const struct stratum_work *, bool hex);
 extern void work2d_gen_dummy_work(struct work *, struct stratum_work *, const struct timeval *tvp_prepared, const void *xnonce2, uint32_t xnonce1);
+extern void work2d_gen_dummy_work_for_stale_check(struct work *, struct stratum_work *, const struct timeval *tvp_prepared, cglock_t *data_lock_p);
 extern bool work2d_submit_nonce(struct thr_info *, struct stratum_work *, const struct timeval *tvp_prepared, const void *xnonce2, uint32_t xnonce1, uint32_t nonce, uint32_t ntime, bool *out_is_stale, float nonce_diff);
 
 #endif