Commit 2d49a9a5d767b85981ce73f1832e0eae06d0d52f

Jeff Garzik 2011-03-17T22:02:28

Introduce ability to interrupt hash scanners in the middle of scanning.

diff --git a/cpu-miner.c b/cpu-miner.c
index 652c35b..7cd6e74 100644
--- a/cpu-miner.c
+++ b/cpu-miner.c
@@ -90,6 +90,7 @@ static char *rpc_url;
 static char *userpass;
 static struct thr_info *thr_info;
 static int work_thr_id;
+struct work_restart *work_restart = NULL;
 
 
 struct option_help {
@@ -514,7 +515,7 @@ static void *miner_thread(void *userdata)
 		/* scan nonces for a proof-of-work hash */
 		switch (opt_algo) {
 		case ALGO_C:
-			rc = scanhash_c(work.midstate, work.data + 64,
+			rc = scanhash_c(thr_id, work.midstate, work.data + 64,
 				        work.hash1, work.hash, work.target,
 					max_nonce, &hashes_done);
 			break;
@@ -522,7 +523,7 @@ static void *miner_thread(void *userdata)
 #ifdef WANT_X8664_SSE2
 		case ALGO_SSE2_64: {
 			unsigned int rc5 =
-			        scanhash_sse2_64(work.midstate, work.data + 64,
+			        scanhash_sse2_64(thr_id, work.midstate, work.data + 64,
 						 work.hash1, work.hash,
 						 work.target,
 					         max_nonce, &hashes_done);
@@ -534,7 +535,7 @@ static void *miner_thread(void *userdata)
 #ifdef WANT_SSE2_4WAY
 		case ALGO_4WAY: {
 			unsigned int rc4 =
-				ScanHash_4WaySSE2(work.midstate, work.data + 64,
+				ScanHash_4WaySSE2(thr_id, work.midstate, work.data + 64,
 						  work.hash1, work.hash,
 						  work.target,
 						  max_nonce, &hashes_done);
@@ -545,19 +546,19 @@ static void *miner_thread(void *userdata)
 
 #ifdef WANT_VIA_PADLOCK
 		case ALGO_VIA:
-			rc = scanhash_via(work.data, work.target,
+			rc = scanhash_via(thr_id, work.data, work.target,
 					  max_nonce, &hashes_done);
 			break;
 #endif
 		case ALGO_CRYPTOPP:
-			rc = scanhash_cryptopp(work.midstate, work.data + 64,
+			rc = scanhash_cryptopp(thr_id, work.midstate, work.data + 64,
 				        work.hash1, work.hash, work.target,
 					max_nonce, &hashes_done);
 			break;
 
 #ifdef WANT_CRYPTOPP_ASM32
 		case ALGO_CRYPTOPP_ASM32:
-			rc = scanhash_asm32(work.midstate, work.data + 64,
+			rc = scanhash_asm32(thr_id, work.midstate, work.data + 64,
 				        work.hash1, work.hash, work.target,
 					max_nonce, &hashes_done);
 			break;
@@ -595,6 +596,14 @@ out:
 	return NULL;
 }
 
+void restart_threads(void)
+{
+	int i;
+
+	for (i = 0; i < opt_n_threads; i++)
+		work_restart[i].restart = 1;
+}
+
 static void show_usage(void)
 {
 	int i;
@@ -761,6 +770,10 @@ int main (int argc, char *argv[])
 	if (!thr_info)
 		return 1;
 
+	work_restart = calloc(opt_n_threads, sizeof(*work_restart));
+	if (!work_restart)
+		return 1;
+
 	work_thr_id = opt_n_threads;
 	thr = &thr_info[work_thr_id];
 	thr->id = opt_n_threads;
diff --git a/miner.h b/miner.h
index 52be480..6556f2a 100644
--- a/miner.h
+++ b/miner.h
@@ -74,33 +74,33 @@ extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
 extern char *bin2hex(const unsigned char *p, size_t len);
 extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
 
-extern unsigned int ScanHash_4WaySSE2(const unsigned char *pmidstate,
+extern unsigned int ScanHash_4WaySSE2(int, const unsigned char *pmidstate,
 	unsigned char *pdata, unsigned char *phash1, unsigned char *phash,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *nHashesDone);
 
-extern unsigned int scanhash_sse2_amd64(const unsigned char *pmidstate,
+extern unsigned int scanhash_sse2_amd64(int, const unsigned char *pmidstate,
 	unsigned char *pdata, unsigned char *phash1, unsigned char *phash,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *nHashesDone);
 
-extern bool scanhash_via(unsigned char *data_inout,
+extern bool scanhash_via(int, unsigned char *data_inout,
 	const unsigned char *target,
 	uint32_t max_nonce, unsigned long *hashes_done);
 
-extern bool scanhash_c(const unsigned char *midstate, unsigned char *data,
+extern bool scanhash_c(int, const unsigned char *midstate, unsigned char *data,
 	      unsigned char *hash1, unsigned char *hash,
 	      const unsigned char *target,
 	      uint32_t max_nonce, unsigned long *hashes_done);
-extern bool scanhash_cryptopp(const unsigned char *midstate,unsigned char *data,
+extern bool scanhash_cryptopp(int, const unsigned char *midstate,unsigned char *data,
 	      unsigned char *hash1, unsigned char *hash,
 	      const unsigned char *target,
 	      uint32_t max_nonce, unsigned long *hashes_done);
-extern bool scanhash_asm32(const unsigned char *midstate,unsigned char *data,
+extern bool scanhash_asm32(int, const unsigned char *midstate,unsigned char *data,
 	      unsigned char *hash1, unsigned char *hash,
 	      const unsigned char *target,
 	      uint32_t max_nonce, unsigned long *hashes_done);
-extern int scanhash_sse2_64(const unsigned char *pmidstate, unsigned char *pdata,
+extern int scanhash_sse2_64(int, const unsigned char *pmidstate, unsigned char *pdata,
 	unsigned char *phash1, unsigned char *phash,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *nHashesDone);
@@ -112,6 +112,13 @@ extern bool fulltest(const unsigned char *hash, const unsigned char *target);
 
 struct thread_q;
 
+struct work_restart {
+	volatile unsigned long	restart;
+};
+
+extern struct work_restart *work_restart;
+extern void restart_threads(void);
+
 extern struct thread_q *tq_new(void);
 extern void tq_free(struct thread_q *tq);
 extern bool tq_push(struct thread_q *tq, void *data);
diff --git a/sha256_4way.c b/sha256_4way.c
index 742682f..6d42451 100644
--- a/sha256_4way.c
+++ b/sha256_4way.c
@@ -100,7 +100,8 @@ static const unsigned int pSHA256InitState[8] =
 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
 
 
-unsigned int ScanHash_4WaySSE2(const unsigned char *pmidstate, unsigned char *pdata,
+unsigned int ScanHash_4WaySSE2(int thr_id, const unsigned char *pmidstate,
+	unsigned char *pdata,
 	unsigned char *phash1, unsigned char *phash,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *nHashesDone)
@@ -108,6 +109,8 @@ unsigned int ScanHash_4WaySSE2(const unsigned char *pmidstate, unsigned char *pd
     unsigned int *nNonce_p = (unsigned int*)(pdata + 12);
     unsigned int nonce = 0;
 
+    work_restart[thr_id].restart = 0;
+
     for (;;)
     {
         unsigned int thash[9][NPAR] __attribute__((aligned(128)));
@@ -135,7 +138,7 @@ unsigned int ScanHash_4WaySSE2(const unsigned char *pmidstate, unsigned char *pd
             }
         }
 
-        if (nonce >= max_nonce)
+        if ((nonce >= max_nonce) || work_restart[thr_id].restart)
         {
             *nHashesDone = nonce;
             return -1;
diff --git a/sha256_cryptopp.c b/sha256_cryptopp.c
index f5f8900..76e178c 100644
--- a/sha256_cryptopp.c
+++ b/sha256_cryptopp.c
@@ -91,7 +91,8 @@ static void runhash(void *state, const void *input, const void *init)
 }
 
 /* suspiciously similar to ScanHash* from bitcoin */
-bool scanhash_cryptopp(const unsigned char *midstate, unsigned char *data,
+bool scanhash_cryptopp(int thr_id, const unsigned char *midstate,
+		unsigned char *data,
 	        unsigned char *hash1, unsigned char *hash,
 		const unsigned char *target,
 	        uint32_t max_nonce, unsigned long *hashes_done)
@@ -101,6 +102,8 @@ bool scanhash_cryptopp(const unsigned char *midstate, unsigned char *data,
 	uint32_t n = 0;
 	unsigned long stat_ctr = 0;
 
+	work_restart[thr_id].restart = 0;
+
 	while (1) {
 		n++;
 		*nonce = n;
@@ -115,7 +118,7 @@ bool scanhash_cryptopp(const unsigned char *midstate, unsigned char *data,
 			return true;
 		}
 
-		if (n >= max_nonce) {
+		if ((n >= max_nonce) || work_restart[thr_id].restart) {
 			*hashes_done = stat_ctr;
 			return false;
 		}
@@ -573,7 +576,8 @@ static void runhash32(void *state, const void *input, const void *init)
 }
 
 /* suspiciously similar to ScanHash* from bitcoin */
-bool scanhash_asm32(const unsigned char *midstate, unsigned char *data,
+bool scanhash_asm32(int thr_id, const unsigned char *midstate,
+		unsigned char *data,
 	        unsigned char *hash1, unsigned char *hash,
 		const unsigned char *target,
 	        uint32_t max_nonce, unsigned long *hashes_done)
@@ -583,6 +587,8 @@ bool scanhash_asm32(const unsigned char *midstate, unsigned char *data,
 	uint32_t n = 0;
 	unsigned long stat_ctr = 0;
 
+	work_restart[thr_id].restart = 0;
+
 	while (1) {
 		n++;
 		*nonce = n;
@@ -599,7 +605,7 @@ bool scanhash_asm32(const unsigned char *midstate, unsigned char *data,
 			return true;
 		}
 
-		if (n >= max_nonce) {
+		if ((n >= max_nonce) || work_restart[thr_id].restart) {
 			if (opt_debug)
 				fprintf(stderr, "DBG: end of nonce range\n");
 			*hashes_done = stat_ctr;
diff --git a/sha256_generic.c b/sha256_generic.c
index 596a6db..b30b326 100644
--- a/sha256_generic.c
+++ b/sha256_generic.c
@@ -237,7 +237,7 @@ const uint32_t sha256_init_state[8] = {
 };
 
 /* suspiciously similar to ScanHash* from bitcoin */
-bool scanhash_c(const unsigned char *midstate, unsigned char *data,
+bool scanhash_c(int thr_id, const unsigned char *midstate, unsigned char *data,
 	        unsigned char *hash1, unsigned char *hash,
 		const unsigned char *target,
 	        uint32_t max_nonce, unsigned long *hashes_done)
@@ -247,6 +247,8 @@ bool scanhash_c(const unsigned char *midstate, unsigned char *data,
 	uint32_t n = 0;
 	unsigned long stat_ctr = 0;
 
+	work_restart[thr_id].restart = 0;
+
 	while (1) {
 		n++;
 		*nonce = n;
@@ -261,7 +263,7 @@ bool scanhash_c(const unsigned char *midstate, unsigned char *data,
 			return true;
 		}
 
-		if (n >= max_nonce) {
+		if ((n >= max_nonce) || work_restart[thr_id].restart) {
 			*hashes_done = stat_ctr;
 			return false;
 		}
diff --git a/sha256_sse2_amd64.c b/sha256_sse2_amd64.c
index 03a8323..d97d888 100644
--- a/sha256_sse2_amd64.c
+++ b/sha256_sse2_amd64.c
@@ -47,7 +47,8 @@ uint32_t g_sha256_hinit[8] =
 
 __m128i g_4sha256_k[64];
 
-int scanhash_sse2_64(const unsigned char *pmidstate, unsigned char *pdata,
+int scanhash_sse2_64(int thr_id, const unsigned char *pmidstate,
+	unsigned char *pdata,
 	unsigned char *phash1, unsigned char *phash,
 	const unsigned char *ptarget,
 	uint32_t max_nonce, unsigned long *nHashesDone)
@@ -59,6 +60,8 @@ int scanhash_sse2_64(const unsigned char *pmidstate, unsigned char *pdata,
     __m128i offset;
     int i;
 
+    work_restart[thr_id].restart = 0;
+
     /* For debugging */
     union {
         __m128i m;
@@ -116,7 +119,7 @@ int scanhash_sse2_64(const unsigned char *pmidstate, unsigned char *pdata,
 
 	nonce += 4;
 
-        if (nonce >= max_nonce)
+        if ((nonce >= max_nonce) || work_restart[thr_id].restart)
         {
             *nHashesDone = nonce;
             return -1;
diff --git a/sha256_via.c b/sha256_via.c
index 186007e..158e757 100644
--- a/sha256_via.c
+++ b/sha256_via.c
@@ -17,7 +17,7 @@ static void via_sha256(void *hash, void *buf, unsigned len)
 		     :"memory");
 }
 
-bool scanhash_via(unsigned char *data_inout,
+bool scanhash_via(int thr_id, unsigned char *data_inout,
 		  const unsigned char *target,
 		  uint32_t max_nonce, unsigned long *hashes_done)
 {
@@ -31,6 +31,8 @@ bool scanhash_via(unsigned char *data_inout,
 	unsigned long stat_ctr = 0;
 	int i;
 
+	work_restart[thr_id].restart = 0;
+
 	/* bitcoin gives us big endian input, but via wants LE,
 	 * so we reverse the swapping bitcoin has already done (extra work)
 	 * in order to permit the hardware to swap everything
@@ -70,7 +72,7 @@ bool scanhash_via(unsigned char *data_inout,
 			return true;
 		}
 
-		if (n >= max_nonce) {
+		if ((n >= max_nonce) || work_restart[thr_id].restart) {
 			*hashes_done = stat_ctr;
 			return false;
 		}