Browse Source

Merge branch 'cg_merges_20130822a' into bfgminer

Luke Dashjr 12 years ago
parent
commit
304658e193
22 changed files with 781 additions and 484 deletions
  1. 1 0
      AUTHORS
  2. 1 1
      Makefile.am
  3. 4 0
      README
  4. 2 0
      README.RPC
  5. 1 1
      adl.c
  6. 202 25
      api.c
  7. 3 0
      configure.ac
  8. 2 2
      deviceapi.c
  9. 6 4
      driver-avalon.c
  10. 4 4
      driver-bitforce.c
  11. 1 1
      driver-cairnsmore.c
  12. 1 1
      driver-icarus.c
  13. 1 1
      driver-modminer.c
  14. 1 1
      driver-x6500.c
  15. 4 4
      driver-ztex.c
  16. 2 2
      libztex.c
  17. 73 29
      miner.c
  18. 8 0
      miner.h
  19. 178 267
      sha2.c
  20. 51 80
      sha2.h
  21. 219 59
      util.c
  22. 16 2
      util.h

+ 1 - 0
AUTHORS

@@ -24,6 +24,7 @@ Philip Kaufmann <phil.kaufmann@t-online.de>
 Rusty Russell <rusty@rustcorp.com.au>
 Rusty Russell <rusty@rustcorp.com.au>
 Znort 987 <znort987@yahoo.com>
 Znort 987 <znort987@yahoo.com>
 Phateus <Jesse.Moll@gmail.com>
 Phateus <Jesse.Moll@gmail.com>
+Olivier Gay <olivier.gay@a3.epfl.ch>
 Glenn Francis Murray <glenn@gfm.cc>
 Glenn Francis Murray <glenn@gfm.cc>
 fleger <florian6.leger@laposte.net>
 fleger <florian6.leger@laposte.net>
 pooler <pooler@litecoinpool.org>
 pooler <pooler@litecoinpool.org>

+ 1 - 1
Makefile.am

@@ -43,7 +43,7 @@ bin_PROGRAMS	= bfgminer
 bfgminer_LDFLAGS	= $(PTHREAD_FLAGS)
 bfgminer_LDFLAGS	= $(PTHREAD_FLAGS)
 bfgminer_LDADD	= $(DLOPEN_FLAGS) @LIBCURL_LIBS@ @JANSSON_LIBS@ @PTHREAD_LIBS@ \
 bfgminer_LDADD	= $(DLOPEN_FLAGS) @LIBCURL_LIBS@ @JANSSON_LIBS@ @PTHREAD_LIBS@ \
 		  @NCURSES_LIBS@ @PDCURSES_LIBS@ @WS2_LIBS@ \
 		  @NCURSES_LIBS@ @PDCURSES_LIBS@ @WS2_LIBS@ \
-		  @UDEV_LIBS@ @LIBUSB_LIBS@ @MM_LIBS@ \
+		  @UDEV_LIBS@ @LIBUSB_LIBS@ @MM_LIBS@ @RT_LIBS@ \
 		  @MATH_LIBS@ lib/libgnu.a ccan/libccan.a
 		  @MATH_LIBS@ lib/libgnu.a ccan/libccan.a
 bfgminer_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib @LIBUSB_CFLAGS@ @LIBCURL_CFLAGS@
 bfgminer_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib @LIBUSB_CFLAGS@ @LIBCURL_CFLAGS@
 
 

+ 4 - 0
README

@@ -173,6 +173,10 @@ Options for both config file and command line:
 --api-listen        Listen for API requests (default: disabled)
 --api-listen        Listen for API requests (default: disabled)
                     By default any command that does not just display data returns access denied
                     By default any command that does not just display data returns access denied
                     See --api-allow to overcome this
                     See --api-allow to overcome this
+--api-mcast         Enable API Multicast listener, default: disabled
+--api-mcast-addr <arg> API Multicast listen address (default: "224.0.0.75")
+--api-mcast-code <arg> Code expected in the API Multicast (default: "FTW")
+--api-mcast-port <arg> Port number of miner API Multicast listener (default: 4028)
 --api-network       Allow API (if enabled) to listen on/for any address (default: only 127.0.0.1)
 --api-network       Allow API (if enabled) to listen on/for any address (default: only 127.0.0.1)
 --api-port          Port number of miner API (default: 4028)
 --api-port          Port number of miner API (default: 4028)
 --balance           Change multipool strategy from failover to even share balance
 --balance           Change multipool strategy from failover to even share balance

+ 2 - 0
README.RPC

@@ -440,6 +440,8 @@ Removed output limitation:
  All replies can now be longer than the previous limitation of 64k, and will
  All replies can now be longer than the previous limitation of 64k, and will
   only be truncated on a 50ms timeout sending.
   only be truncated on a 50ms timeout sending.
 
 
+Basic support for cgminer-compatible multicast RPC detection added.
+
 ----------
 ----------
 
 
 API V1.25.2
 API V1.25.2

+ 1 - 1
adl.c

@@ -1380,7 +1380,7 @@ updated:
 		clear_logwin();
 		clear_logwin();
 		return;
 		return;
 	}
 	}
-	nmsleep(1000);
+	cgsleep_ms(1000);
 	goto updated;
 	goto updated;
 }
 }
 #endif
 #endif

+ 202 - 25
api.c

@@ -52,6 +52,7 @@
 #define QUEUE	100
 #define QUEUE	100
 
 
 static const char *UNAVAILABLE = " - API will not be available";
 static const char *UNAVAILABLE = " - API will not be available";
+static const char *MUNAVAILABLE = " - API multicast listener will not be available";
 
 
 static const char *BLANK = "";
 static const char *BLANK = "";
 static const char *COMMA = ",";
 static const char *COMMA = ",";
@@ -516,6 +517,8 @@ struct CODES {
  { SEVERITY_FAIL, 0, 0, NULL }
  { SEVERITY_FAIL, 0, 0, NULL }
 };
 };
 
 
+static const char *localaddr = "127.0.0.1";
+
 static int my_thr_id = 0;
 static int my_thr_id = 0;
 static bool bye;
 static bool bye;
 
 
@@ -3648,13 +3651,203 @@ static void *restart_thread(__maybe_unused void *userdata)
 	return NULL;
 	return NULL;
 }
 }
 
 
+static bool check_connect(struct sockaddr_in *cli, char **connectaddr, char *group)
+{
+	bool addrok = false;
+	int i;
+
+	*connectaddr = inet_ntoa(cli->sin_addr);
+
+	*group = NOPRIVGROUP;
+	if (opt_api_allow) {
+		int client_ip = htonl(cli->sin_addr.s_addr);
+		for (i = 0; i < ips; i++) {
+			if ((client_ip & ipaccess[i].mask) == ipaccess[i].ip) {
+				addrok = true;
+				*group = ipaccess[i].group;
+				break;
+			}
+		}
+	} else {
+		if (opt_api_network)
+			addrok = true;
+		else
+			addrok = (strcmp(*connectaddr, localaddr) == 0);
+	}
+
+	return addrok;
+}
+
+static void mcast()
+{
+	struct sockaddr_in listen;
+	struct ip_mreq grp;
+	struct sockaddr_in came_from;
+	time_t bindstart;
+	const char *binderror;
+	SOCKETTYPE mcast_sock;
+	SOCKETTYPE reply_sock;
+	socklen_t came_from_siz;
+	char *connectaddr;
+	ssize_t rep;
+	int bound;
+	int count;
+	int reply_port;
+	bool addrok;
+	char group;
+
+	char expect[] = "cgminer-"; // first 8 bytes constant
+	char *expect_code;
+	size_t expect_code_len;
+	char buf[1024];
+	char replybuf[1024];
+
+	memset(&grp, 0, sizeof(grp));
+	grp.imr_multiaddr.s_addr = inet_addr(opt_api_mcast_addr);
+	if (grp.imr_multiaddr.s_addr == INADDR_NONE)
+		quit(1, "Invalid Multicast Address");
+	grp.imr_interface.s_addr = INADDR_ANY;
+
+	mcast_sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+	int optval = 1;
+	if (SOCKETFAIL(setsockopt(mcast_sock, SOL_SOCKET, SO_REUSEADDR, (void *)(&optval), sizeof(optval)))) {
+		applog(LOG_ERR, "API mcast setsockopt SO_REUSEADDR failed (%s)%s", SOCKERRMSG, MUNAVAILABLE);
+		goto die;
+	}
+
+	memset(&listen, 0, sizeof(listen));
+	listen.sin_family = AF_INET;
+	listen.sin_addr.s_addr = INADDR_ANY;
+	listen.sin_port = htons(opt_api_mcast_port);
+
+	// try for more than 1 minute ... in case the old one hasn't completely gone yet
+	bound = 0;
+	bindstart = time(NULL);
+	while (bound == 0) {
+		if (SOCKETFAIL(bind(mcast_sock, (struct sockaddr *)(&listen), sizeof(listen)))) {
+			binderror = SOCKERRMSG;
+			if ((time(NULL) - bindstart) > 61)
+				break;
+			else
+				cgsleep_ms(30000);
+		} else
+			bound = 1;
+	}
+
+	if (bound == 0) {
+		applog(LOG_ERR, "API mcast bind to port %d failed (%s)%s", opt_api_port, binderror, MUNAVAILABLE);
+		goto die;
+	}
+
+	if (SOCKETFAIL(setsockopt(mcast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)(&grp), sizeof(grp)))) {
+		applog(LOG_ERR, "API mcast join failed (%s)%s", SOCKERRMSG, MUNAVAILABLE);
+		goto die;
+	}
+
+	expect_code_len = sizeof(expect) + strlen(opt_api_mcast_code);
+	expect_code = malloc(expect_code_len+1);
+	if (!expect_code)
+		quit(1, "Failed to malloc mcast expect_code");
+	snprintf(expect_code, expect_code_len+1, "%s%s-", expect, opt_api_mcast_code);
+
+	count = 0;
+	while (80085) {
+		cgsleep_ms(1000);
+
+		count++;
+		came_from_siz = sizeof(came_from);
+		if (SOCKETFAIL(rep = recvfrom(mcast_sock, buf, sizeof(buf),
+						0, (struct sockaddr *)(&came_from), &came_from_siz))) {
+			applog(LOG_DEBUG, "API mcast failed count=%d (%s) (%d)",
+					count, SOCKERRMSG, (int)mcast_sock);
+			continue;
+		}
+
+		addrok = check_connect(&came_from, &connectaddr, &group);
+		applog(LOG_DEBUG, "API mcast from %s - %s",
+					connectaddr, addrok ? "Accepted" : "Ignored");
+		if (!addrok)
+			continue;
+
+		buf[rep] = '\0';
+		if (rep > 0 && buf[rep-1] == '\n')
+			buf[--rep] = '\0';
+
+		applog(LOG_DEBUG, "API mcast request rep=%d (%s) from %s:%d",
+					(int)rep, buf,
+					inet_ntoa(came_from.sin_addr),
+					ntohs(came_from.sin_port));
+
+		if ((size_t)rep > expect_code_len && memcmp(buf, expect_code, expect_code_len) == 0) {
+			reply_port = atoi(&buf[expect_code_len]);
+			if (reply_port < 1 || reply_port > 65535) {
+				applog(LOG_DEBUG, "API mcast request ignored - invalid port (%s)",
+							&buf[expect_code_len]);
+			} else {
+				applog(LOG_DEBUG, "API mcast request OK port %s=%d",
+							&buf[expect_code_len], reply_port);
+
+				came_from.sin_port = htons(reply_port);
+				reply_sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+				snprintf(replybuf, sizeof(replybuf),
+							"cgm-%s-%d",
+							opt_api_mcast_code,
+							opt_api_port);
+
+				rep = sendto(reply_sock, replybuf, strlen(replybuf)+1,
+						0, (struct sockaddr *)(&came_from),
+						sizeof(came_from));
+				if (SOCKETFAIL(rep)) {
+					applog(LOG_DEBUG, "API mcast reply failed (%s) (%d)",
+								SOCKERRMSG, (int)reply_sock);
+				} else {
+					applog(LOG_DEBUG, "API mcast reply (%s) succeeded (%d) (%d)",
+								replybuf, (int)rep, (int)reply_sock);
+				}
+
+				CLOSESOCKET(reply_sock);
+			}
+		} else
+			applog(LOG_DEBUG, "API mcast request was no good");
+	}
+
+die:
+
+	CLOSESOCKET(mcast_sock);
+}
+
+static void *mcast_thread(void *userdata)
+{
+	pthread_detach(pthread_self());
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+	RenameThread("api_mcast");
+
+	mcast();
+
+	return NULL;
+}
+
+void mcast_init()
+{
+	struct thr_info *thr;
+
+	thr = calloc(1, sizeof(*thr));
+	if (!thr)
+		quit(1, "Failed to calloc mcast thr");
+
+	if (thr_info_create(thr, NULL, mcast_thread, thr))
+		quit(1, "API mcast thread create failed");
+}
+
 void api(int api_thr_id)
 void api(int api_thr_id)
 {
 {
 	struct io_data *io_data;
 	struct io_data *io_data;
 	struct thr_info bye_thr;
 	struct thr_info bye_thr;
 	char buf[TMPBUFSIZ];
 	char buf[TMPBUFSIZ];
 	char param_buf[TMPBUFSIZ];
 	char param_buf[TMPBUFSIZ];
-	const char *localaddr = "127.0.0.1";
 	SOCKETTYPE c;
 	SOCKETTYPE c;
 	int n, bound;
 	int n, bound;
 	char *connectaddr;
 	char *connectaddr;
@@ -3707,7 +3900,7 @@ void api(int api_thr_id)
 
 
 	/* This should be done before curl in needed
 	/* This should be done before curl in needed
 	 * to ensure curl has already called WSAStartup() in windows */
 	 * to ensure curl has already called WSAStartup() in windows */
-	nmsleep(opt_log_interval*1000);
+	cgsleep_ms(opt_log_interval*1000);
 
 
 	*apisock = socket(AF_INET, SOCK_STREAM, 0);
 	*apisock = socket(AF_INET, SOCK_STREAM, 0);
 	if (*apisock == INVSOCK) {
 	if (*apisock == INVSOCK) {
@@ -3753,7 +3946,7 @@ void api(int api_thr_id)
 				break;
 				break;
 			else {
 			else {
 				applog(LOG_WARNING, "API bind to port %d failed - trying again in 30sec", port);
 				applog(LOG_WARNING, "API bind to port %d failed - trying again in 30sec", port);
-				nmsleep(30000);
+				cgsleep_ms(30000);
 			}
 			}
 		} else
 		} else
 			bound = 1;
 			bound = 1;
@@ -3779,6 +3972,9 @@ void api(int api_thr_id)
 			applog(LOG_WARNING, "API running in local read access mode on port %d", port);
 			applog(LOG_WARNING, "API running in local read access mode on port %d", port);
 	}
 	}
 
 
+	if (opt_api_mcast)
+		mcast_init();
+
 	while (!bye) {
 	while (!bye) {
 		clisiz = sizeof(cli);
 		clisiz = sizeof(cli);
 		if (SOCKETFAIL(c = accept(*apisock, (struct sockaddr *)(&cli), &clisiz))) {
 		if (SOCKETFAIL(c = accept(*apisock, (struct sockaddr *)(&cli), &clisiz))) {
@@ -3786,28 +3982,9 @@ void api(int api_thr_id)
 			goto die;
 			goto die;
 		}
 		}
 
 
-		connectaddr = inet_ntoa(cli.sin_addr);
-
-		addrok = false;
-		group = NOPRIVGROUP;
-		if (opt_api_allow) {
-			int client_ip = htonl(cli.sin_addr.s_addr);
-			for (i = 0; i < ips; i++) {
-				if ((client_ip & ipaccess[i].mask) == ipaccess[i].ip) {
-					addrok = true;
-					group = ipaccess[i].group;
-					break;
-				}
-			}
-		} else {
-			if (opt_api_network)
-				addrok = true;
-			else
-				addrok = (strcmp(connectaddr, localaddr) == 0);
-		}
-
-		if (opt_debug)
-			applog(LOG_DEBUG, "API: connection from %s - %s", connectaddr, addrok ? "Accepted" : "Ignored");
+		addrok = check_connect(&cli, &connectaddr, &group);
+		applog(LOG_DEBUG, "API: connection from %s - %s",
+					connectaddr, addrok ? "Accepted" : "Ignored");
 
 
 		if (addrok) {
 		if (addrok) {
 			n = recv(c, &buf[0], TMPBUFSIZ-1, 0);
 			n = recv(c, &buf[0], TMPBUFSIZ-1, 0);

+ 3 - 0
configure.ac

@@ -83,6 +83,7 @@ DLOPEN_FLAGS="-ldl"
 WS2_LIBS=""
 WS2_LIBS=""
 MM_LIBS=""
 MM_LIBS=""
 MATH_LIBS="-lm"
 MATH_LIBS="-lm"
+RT_LIBS="-lrt"
 
 
 case $target in
 case $target in
   amd64-* | x86_64-*)
   amd64-* | x86_64-*)
@@ -107,6 +108,7 @@ case $target in
     DLOPEN_FLAGS=""
     DLOPEN_FLAGS=""
     WS2_LIBS="-lws2_32"
     WS2_LIBS="-lws2_32"
     MM_LIBS="-lwinmm"
     MM_LIBS="-lwinmm"
+    RT_LIBS=""
     AC_DEFINE([_WIN32_WINNT], [0x0501], "WinNT version for XP+ support")
     AC_DEFINE([_WIN32_WINNT], [0x0501], "WinNT version for XP+ support")
     AC_DEFINE([FD_SETSIZE], [4096], [Maximum sockets before fd_set overflows])
     AC_DEFINE([FD_SETSIZE], [4096], [Maximum sockets before fd_set overflows])
     ;;
     ;;
@@ -953,6 +955,7 @@ AC_SUBST(PDCURSES_LIBS)
 AC_SUBST(WS2_LIBS)
 AC_SUBST(WS2_LIBS)
 AC_SUBST(MM_LIBS)
 AC_SUBST(MM_LIBS)
 AC_SUBST(MATH_LIBS)
 AC_SUBST(MATH_LIBS)
+AC_SUBST(RT_LIBS)
 AC_SUBST(UDEV_LIBS)
 AC_SUBST(UDEV_LIBS)
 AC_SUBST(SSE2_CFLAGS)
 AC_SUBST(SSE2_CFLAGS)
 AC_SUBST(YASM_FMT)
 AC_SUBST(YASM_FMT)

+ 2 - 2
deviceapi.c

@@ -99,7 +99,7 @@ int restart_wait(struct thr_info *thr, unsigned int mstime)
 	{
 	{
 		// This is a bug!
 		// This is a bug!
 		applog(LOG_ERR, "%"PRIpreprv": restart_wait called without a work_restart_notifier", thr->cgpu->proc_repr);
 		applog(LOG_ERR, "%"PRIpreprv": restart_wait called without a work_restart_notifier", thr->cgpu->proc_repr);
-		nmsleep(mstime);
+		cgsleep_ms(mstime);
 		return (thr->work_restart ? 0 : ETIMEDOUT);
 		return (thr->work_restart ? 0 : ETIMEDOUT);
 	}
 	}
 	
 	
@@ -595,7 +595,7 @@ out: ;
 	while ( (proc = proc->next_proc) && !proc->threads);
 	while ( (proc = proc->next_proc) && !proc->threads);
 	mythr->getwork = 0;
 	mythr->getwork = 0;
 	mythr->has_pth = false;
 	mythr->has_pth = false;
-	nmsleep(1000);
+	cgsleep_ms(1000);
 	
 	
 	if (drv->thread_shutdown)
 	if (drv->thread_shutdown)
 		drv->thread_shutdown(mythr);
 		drv->thread_shutdown(mythr);

+ 6 - 4
driver-avalon.c

@@ -308,7 +308,7 @@ static bool avalon_decode_nonce(struct thr_info *thr, struct avalon_result *ar,
 	if (unlikely(!avalon->works))
 	if (unlikely(!avalon->works))
 		return false;
 		return false;
 
 
-	work = find_queued_work_bymidstate(avalon, (char *)ar->midstate, 32,
+	work = clone_queued_work_bymidstate(avalon, (char *)ar->midstate, 32,
 					   (char *)ar->data, 64, 12);
 					   (char *)ar->data, 64, 12);
 	if (!work)
 	if (!work)
 		return false;
 		return false;
@@ -317,6 +317,8 @@ static bool avalon_decode_nonce(struct thr_info *thr, struct avalon_result *ar,
 	info->matching_work[work->subid]++;
 	info->matching_work[work->subid]++;
 	*nonce = htole32(ar->nonce);
 	*nonce = htole32(ar->nonce);
 	submit_nonce(thr, work, *nonce);
 	submit_nonce(thr, work, *nonce);
+	
+	free_work(work);
 
 
 	return true;
 	return true;
 }
 }
@@ -706,7 +708,7 @@ static void do_avalon_close(struct thr_info *thr)
 	struct avalon_info *info = avalon->device_data;
 	struct avalon_info *info = avalon->device_data;
 
 
 	avalon_free_work(thr);
 	avalon_free_work(thr);
-	nmsleep(1000);
+	cgsleep_ms(1000);
 	avalon_reset(avalon->device_fd, &ar);
 	avalon_reset(avalon->device_fd, &ar);
 	avalon_idle(avalon);
 	avalon_idle(avalon);
 	avalon_close(avalon->device_fd);
 	avalon_close(avalon->device_fd);
@@ -853,7 +855,7 @@ static int64_t avalon_scanhash(struct thr_info *thr)
 			       avalon->device_id);
 			       avalon->device_id);
 			dev_error(avalon, REASON_DEV_COMMS_ERROR);
 			dev_error(avalon, REASON_DEV_COMMS_ERROR);
 			first_try = 0;
 			first_try = 0;
-			nmsleep(1000);
+			cgsleep_ms(1000);
 			avalon_init(avalon);
 			avalon_init(avalon);
 			return 0;	/* This should never happen */
 			return 0;	/* This should never happen */
 		}
 		}
@@ -939,7 +941,7 @@ static int64_t avalon_scanhash(struct thr_info *thr)
 			"AVA%i: FPGA controller messed up, %d wrong results",
 			"AVA%i: FPGA controller messed up, %d wrong results",
 			avalon->device_id, result_wrong);
 			avalon->device_id, result_wrong);
 		dev_error(avalon, REASON_DEV_COMMS_ERROR);
 		dev_error(avalon, REASON_DEV_COMMS_ERROR);
-		nmsleep(1000);
+		cgsleep_ms(1000);
 		avalon_init(avalon);
 		avalon_init(avalon);
 		return 0;
 		return 0;
 	}
 	}

+ 4 - 4
driver-bitforce.c

@@ -426,7 +426,7 @@ void bitforce_reinit(struct cgpu_info *bitforce)
 
 
 	if (fdDev) {
 	if (fdDev) {
 		BFclose(fdDev);
 		BFclose(fdDev);
-		nmsleep(5000);
+		cgsleep_ms(5000);
 		*p_fdDev = 0;
 		*p_fdDev = 0;
 	}
 	}
 
 
@@ -449,7 +449,7 @@ void bitforce_reinit(struct cgpu_info *bitforce)
 		}
 		}
 
 
 		if (retries++)
 		if (retries++)
-			nmsleep(10);
+			cgsleep_ms(10);
 	} while (strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS));
 	} while (strstr(pdevbuf, "BUSY") && (retries * 10 < BITFORCE_TIMEOUT_MS));
 
 
 	if (unlikely(!strstr(pdevbuf, "SHA256"))) {
 	if (unlikely(!strstr(pdevbuf, "SHA256"))) {
@@ -517,7 +517,7 @@ static void bitforce_flash_led(struct cgpu_info *bitforce)
 
 
 	/* However, this stops anything else getting a reply
 	/* However, this stops anything else getting a reply
 	 * So best to delay any other access to the BFL */
 	 * So best to delay any other access to the BFL */
-	nmsleep(4000);
+	cgsleep_ms(4000);
 
 
 	mutex_unlock(mutexp);
 	mutex_unlock(mutexp);
 
 
@@ -1365,7 +1365,7 @@ static bool bitforce_thread_init(struct thr_info *thr)
 	 * so the devices aren't making calls all at the same time. */
 	 * so the devices aren't making calls all at the same time. */
 	wait = thr->id * MAX_START_DELAY_MS;
 	wait = thr->id * MAX_START_DELAY_MS;
 	applog(LOG_DEBUG, "%s: Delaying start by %dms", bitforce->dev_repr, wait / 1000);
 	applog(LOG_DEBUG, "%s: Delaying start by %dms", bitforce->dev_repr, wait / 1000);
-	nmsleep(wait);
+	cgsleep_ms(wait);
 
 
 	if (sc)
 	if (sc)
 	{
 	{

+ 1 - 1
driver-cairnsmore.c

@@ -190,7 +190,7 @@ static bool cairnsmore_identify(struct cgpu_info *cm1)
 		return false;
 		return false;
 	
 	
 	cairnsmore_send_cmd(cm1->device_fd, 1, 1);
 	cairnsmore_send_cmd(cm1->device_fd, 1, 1);
-	nmsleep(5000);
+	cgsleep_ms(5000);
 	cairnsmore_send_cmd(cm1->device_fd, 1, 0);
 	cairnsmore_send_cmd(cm1->device_fd, 1, 0);
 	cm1->flash_led = true;
 	cm1->flash_led = true;
 	return true;
 	return true;

+ 1 - 1
driver-icarus.c

@@ -844,7 +844,7 @@ void handle_identify(struct thr_info * const thr, int ret, const bool was_first_
 	
 	
 	// 3. Delay 3 more seconds
 	// 3. Delay 3 more seconds
 	applog(LOG_DEBUG, "%"PRIpreprv": Identify: Leaving idle for 3 seconds", icarus->proc_repr);
 	applog(LOG_DEBUG, "%"PRIpreprv": Identify: Leaving idle for 3 seconds", icarus->proc_repr);
-	nmsleep(3000);
+	cgsleep_ms(3000);
 	
 	
 	// Check for work restart in the meantime
 	// Check for work restart in the meantime
 	if (thr->work_restart)
 	if (thr->work_restart)

+ 1 - 1
driver-modminer.c

@@ -664,7 +664,7 @@ modminer_process_results(struct thr_info*thr)
 		}
 		}
 		if (work_restart(thr) || !--iter)
 		if (work_restart(thr) || !--iter)
 			break;
 			break;
-		nmsleep(1);
+		cgsleep_ms(1);
 		if (work_restart(thr))
 		if (work_restart(thr))
 			break;
 			break;
 		mutex_lock(mutexp);
 		mutex_lock(mutexp);

+ 1 - 1
driver-x6500.c

@@ -255,7 +255,7 @@ x6500_fpga_upload_bitstream(struct cgpu_info *x6500, struct jtag_port *jp1)
 	x6500_jtag_set(jp, 0x11);
 	x6500_jtag_set(jp, 0x11);
 	jtag_write(jp, JTAG_REG_IR, "\xa0", 6);  // CFG_IN
 	jtag_write(jp, JTAG_REG_IR, "\xa0", 6);  // CFG_IN
 	
 	
-	nmsleep(1000);
+	cgsleep_ms(1000);
 	
 	
 	if (fread(buf, 32, 1, f) != 1)
 	if (fread(buf, 32, 1, f) != 1)
 		bailout2(LOG_ERR, "%s: File underrun programming %s (%lu bytes left)", x6500->dev_repr, x6500->device_path, len);
 		bailout2(LOG_ERR, "%s: File underrun programming %s (%lu bytes left)", x6500->dev_repr, x6500->device_path, len);

+ 4 - 4
driver-ztex.c

@@ -153,8 +153,8 @@ static bool ztex_checkNonce(struct cgpu_info *cgpu,
 
 
 	swap32yes(swap32, data32, 76 / 4);
 	swap32yes(swap32, data32, 76 / 4);
 
 
-	sha2(swap, 80, hash1);
-	sha2(hash1, 32, hash2);
+	sha256(swap, 80, hash1);
+	sha256(hash1, 32, hash2);
 
 
 	if (be32toh(hash2_32[7]) != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) {
 	if (be32toh(hash2_32[7]) != ((hdata->hash7 + 0x5be0cd19) & 0xFFFFFFFF)) {
 		applog(LOG_DEBUG, "%"PRIpreprv": checkNonce failed for %08x", cgpu->proc_repr, hdata->nonce);
 		applog(LOG_DEBUG, "%"PRIpreprv": checkNonce failed for %08x", cgpu->proc_repr, hdata->nonce);
@@ -190,7 +190,7 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work,
 	if (i < 0) {
 	if (i < 0) {
 		// Something wrong happened in send
 		// Something wrong happened in send
 		applog(LOG_ERR, "%"PRIpreprv": Failed to send hash data with err %d, retrying", cgpu->proc_repr, i);
 		applog(LOG_ERR, "%"PRIpreprv": Failed to send hash data with err %d, retrying", cgpu->proc_repr, i);
-		nmsleep(500);
+		cgsleep_ms(500);
 		i = libztex_sendHashData(ztex, sendbuf);
 		i = libztex_sendHashData(ztex, sendbuf);
 		if (i < 0) {
 		if (i < 0) {
 			// And there's nothing we can do about it
 			// And there's nothing we can do about it
@@ -235,7 +235,7 @@ static int64_t ztex_scanhash(struct thr_info *thr, struct work *work,
 		if (i < 0) {
 		if (i < 0) {
 			// Something wrong happened in read
 			// Something wrong happened in read
 			applog(LOG_ERR, "%"PRIpreprv": Failed to read hash data with err %d, retrying", cgpu->proc_repr, i);
 			applog(LOG_ERR, "%"PRIpreprv": Failed to read hash data with err %d, retrying", cgpu->proc_repr, i);
-			nmsleep(500);
+			cgsleep_ms(500);
 			i = libztex_readHashData(ztex, &hdata[0]);
 			i = libztex_readHashData(ztex, &hdata[0]);
 			if (i < 0) {
 			if (i < 0) {
 				// And there's nothing we can do about it
 				// And there's nothing we can do about it

+ 2 - 2
libztex.c

@@ -404,7 +404,7 @@ static int libztex_configureFpgaHS(struct libztex_device *ztex, const char* firm
 
 
 	libusb_release_interface(ztex->hndl, settings[1]);
 	libusb_release_interface(ztex->hndl, settings[1]);
 
 
-	nmsleep(200);
+	cgsleep_ms(200);
 	applog(LOG_INFO, "%"PRIpreprv": HS FPGA configuration done", repr);
 	applog(LOG_INFO, "%"PRIpreprv": HS FPGA configuration done", repr);
 	return 0;
 	return 0;
 }
 }
@@ -469,7 +469,7 @@ static int libztex_configureFpgaLS(struct libztex_device *ztex, const char* firm
 		return -3;
 		return -3;
 	}
 	}
 
 
-	nmsleep(200);
+	cgsleep_ms(200);
 	applog(LOG_INFO, "%"PRIpreprv": FPGA configuration done", repr);
 	applog(LOG_INFO, "%"PRIpreprv": FPGA configuration done", repr);
 	return 0;
 	return 0;
 }
 }

+ 73 - 29
miner.c

@@ -45,6 +45,7 @@
 #include <sys/socket.h>
 #include <sys/socket.h>
 #else
 #else
 #include <winsock2.h>
 #include <winsock2.h>
+#include <windows.h>
 #endif
 #endif
 #include <ccan/opt/opt.h>
 #include <ccan/opt/opt.h>
 #include <jansson.h>
 #include <jansson.h>
@@ -199,9 +200,14 @@ char *opt_api_groups;
 char *opt_api_description = PACKAGE_STRING;
 char *opt_api_description = PACKAGE_STRING;
 int opt_api_port = 4028;
 int opt_api_port = 4028;
 bool opt_api_listen;
 bool opt_api_listen;
+bool opt_api_mcast;
+char *opt_api_mcast_addr = API_MCAST_ADDR;
+char *opt_api_mcast_code = API_MCAST_CODE;
+int opt_api_mcast_port = 4028;
 bool opt_api_network;
 bool opt_api_network;
 bool opt_delaynet;
 bool opt_delaynet;
 bool opt_disable_pool;
 bool opt_disable_pool;
+static bool no_work;
 char *opt_icarus_options = NULL;
 char *opt_icarus_options = NULL;
 char *opt_icarus_timing = NULL;
 char *opt_icarus_timing = NULL;
 bool opt_worktime;
 bool opt_worktime;
@@ -1360,6 +1366,18 @@ static struct opt_table opt_config_table[] = {
 	OPT_WITHOUT_ARG("--api-listen",
 	OPT_WITHOUT_ARG("--api-listen",
 			opt_set_bool, &opt_api_listen,
 			opt_set_bool, &opt_api_listen,
 			"Enable API, default: disabled"),
 			"Enable API, default: disabled"),
+	OPT_WITHOUT_ARG("--api-mcast",
+			opt_set_bool, &opt_api_mcast,
+			"Enable API Multicast listener, default: disabled"),
+	OPT_WITH_ARG("--api-mcast-addr",
+		     opt_set_charp, opt_show_charp, &opt_api_mcast_addr,
+		     "API Multicast listen address"),
+	OPT_WITH_ARG("--api-mcast-code",
+		     opt_set_charp, opt_show_charp, &opt_api_mcast_code,
+		     "Code expected in the API Multicast"),
+	OPT_WITH_ARG("--api-mcast-port",
+		     set_int_1_to_65535, opt_show_intval, &opt_api_mcast_port,
+		     "Port number of miner API Multicast listener"),
 	OPT_WITHOUT_ARG("--api-network",
 	OPT_WITHOUT_ARG("--api-network",
 			opt_set_bool, &opt_api_network,
 			opt_set_bool, &opt_api_network,
 			"Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"),
 			"Allow API (if enabled) to listen on/for any address, default: only 127.0.0.1"),
@@ -1946,32 +1964,32 @@ extern const char *opt_argv0;
 static char *opt_verusage_and_exit(const char *extra)
 static char *opt_verusage_and_exit(const char *extra)
 {
 {
 	printf("%s\nBuilt with "
 	printf("%s\nBuilt with "
-#ifdef HAVE_OPENCL
-		"GPU "
+#ifdef USE_AVALON
+		"avalon "
+#endif
+#ifdef USE_BITFORCE
+		"bitforce "
 #endif
 #endif
 #ifdef WANT_CPUMINE
 #ifdef WANT_CPUMINE
 		"CPU "
 		"CPU "
 #endif
 #endif
-#ifdef USE_BITFORCE
-		"bitforce "
+#ifdef HAVE_OPENCL
+		"GPU "
 #endif
 #endif
 #ifdef USE_ICARUS
 #ifdef USE_ICARUS
 		"icarus "
 		"icarus "
 #endif
 #endif
-#ifdef USE_AVALON
-		"avalon "
-#endif
 #ifdef USE_MODMINER
 #ifdef USE_MODMINER
 		"modminer "
 		"modminer "
 #endif
 #endif
+#ifdef USE_SCRYPT
+		"scrypt "
+#endif
 #ifdef USE_X6500
 #ifdef USE_X6500
 		"x6500 "
 		"x6500 "
 #endif
 #endif
 #ifdef USE_ZTEX
 #ifdef USE_ZTEX
 		"ztex "
 		"ztex "
-#endif
-#ifdef USE_SCRYPT
-		"scrypt "
 #endif
 #endif
 		"mining support.\n"
 		"mining support.\n"
 		, packagename);
 		, packagename);
@@ -2031,10 +2049,10 @@ static void calc_midstate(struct work *work)
 	} data;
 	} data;
 
 
 	swap32yes(&data.i[0], work->data, 16);
 	swap32yes(&data.i[0], work->data, 16);
-	sha2_context ctx;
-	sha2_starts(&ctx);
-	sha2_update(&ctx, data.c, 64);
-	memcpy(work->midstate, ctx.state, sizeof(work->midstate));
+	sha256_ctx ctx;
+	sha256_init(&ctx);
+	sha256_update(&ctx, data.c, 64);
+	memcpy(work->midstate, ctx.h, sizeof(work->midstate));
 	swap32tole(work->midstate, work->midstate, 8);
 	swap32tole(work->midstate, work->midstate, 8);
 }
 }
 
 
@@ -5820,6 +5838,10 @@ void write_config(FILE *fcfg)
 	
 	
 	if (opt_api_allow)
 	if (opt_api_allow)
 		fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow));
 		fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow));
+	if (strcmp(opt_api_mcast_addr, API_MCAST_ADDR) != 0)
+		fprintf(fcfg, ",\n\"api-mcast-addr\" : \"%s\"", json_escape(opt_api_mcast_addr));
+	if (strcmp(opt_api_mcast_code, API_MCAST_CODE) != 0)
+		fprintf(fcfg, ",\n\"api-mcast-code\" : \"%s\"", json_escape(opt_api_mcast_code));
 	if (strcmp(opt_api_description, PACKAGE_STRING) != 0)
 	if (strcmp(opt_api_description, PACKAGE_STRING) != 0)
 		fprintf(fcfg, ",\n\"api-description\" : \"%s\"", json_escape(opt_api_description));
 		fprintf(fcfg, ",\n\"api-description\" : \"%s\"", json_escape(opt_api_description));
 	if (opt_api_groups)
 	if (opt_api_groups)
@@ -7213,6 +7235,10 @@ static bool cnx_needed(struct pool *pool)
 
 
 	if (pool_unworkable(cp))
 	if (pool_unworkable(cp))
 		return true;
 		return true;
+	
+	/* We've run out of work, bring anything back to life. */
+	if (no_work)
+		return true;
 
 
 	return false;
 	return false;
 }
 }
@@ -7281,7 +7307,7 @@ static void *stratum_thread(void *userdata)
 				while (!restart_stratum(pool)) {
 				while (!restart_stratum(pool)) {
 					if (pool->removed)
 					if (pool->removed)
 						goto out;
 						goto out;
-					nmsleep(30000);
+					cgsleep_ms(30000);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -7609,7 +7635,7 @@ static struct work *hash_pop(void)
 
 
 retry:
 retry:
 	mutex_lock(stgd_lock);
 	mutex_lock(stgd_lock);
-	while (!getq->frozen && !HASH_COUNT(staged_work))
+	while (!HASH_COUNT(staged_work))
 	{
 	{
 		if (unlikely(staged_full))
 		if (unlikely(staged_full))
 		{
 		{
@@ -7621,6 +7647,7 @@ retry:
 			else
 			else
 				applog(LOG_WARNING, "Staged work underrun; not automatically increasing above %d", opt_queue);
 				applog(LOG_WARNING, "Staged work underrun; not automatically increasing above %d", opt_queue);
 			staged_full = false;  // Let it fill up before triggering an underrun again
 			staged_full = false;  // Let it fill up before triggering an underrun again
+			no_work = true;
 		}
 		}
 		ts = (struct timespec){ .tv_sec = opt_log_interval, };
 		ts = (struct timespec){ .tv_sec = opt_log_interval, };
 		if (ETIMEDOUT == pthread_cond_timedwait(&getq->cond, stgd_lock, &ts))
 		if (ETIMEDOUT == pthread_cond_timedwait(&getq->cond, stgd_lock, &ts))
@@ -7629,6 +7656,8 @@ retry:
 			pthread_cond_wait(&getq->cond, stgd_lock);
 			pthread_cond_wait(&getq->cond, stgd_lock);
 		}
 		}
 	}
 	}
+	
+	no_work = false;
 
 
 	hc = HASH_COUNT(staged_work);
 	hc = HASH_COUNT(staged_work);
 	/* Find clone work if possible, to allow masters to be reused */
 	/* Find clone work if possible, to allow masters to be reused */
@@ -7703,8 +7732,8 @@ void gen_hash(unsigned char *data, unsigned char *hash, int len)
 {
 {
 	unsigned char hash1[32];
 	unsigned char hash1[32];
 
 
-	sha2(data, len, hash1);
-	sha2(hash1, 32, hash);
+	sha256(data, len, hash1);
+	sha256(hash1, 32, hash);
 }
 }
 
 
 /* Diff 1 is a 256 bit unsigned integer of
 /* Diff 1 is a 256 bit unsigned integer of
@@ -8184,6 +8213,19 @@ struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate,
 	return ret;
 	return ret;
 }
 }
 
 
+struct work *clone_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen)
+{
+	struct work *work, *ret = NULL;
+
+	rd_lock(&cgpu->qlock);
+	work = __find_work_bymidstate(cgpu->queued_work, midstate, midstatelen, data, offset, datalen);
+	if (work)
+		ret = copy_work(work);
+	rd_unlock(&cgpu->qlock);
+
+	return ret;
+}
+
 /* This function should be used by queued device drivers when they're sure
 /* This function should be used by queued device drivers when they're sure
  * the work struct is no longer in use. */
  * the work struct is no longer in use. */
 void work_completed(struct cgpu_info *cgpu, struct work *work)
 void work_completed(struct cgpu_info *cgpu, struct work *work)
@@ -8369,12 +8411,9 @@ static struct pool *select_longpoll_pool(struct pool *cp)
  */
  */
 static void wait_lpcurrent(struct pool *pool)
 static void wait_lpcurrent(struct pool *pool)
 {
 {
-	if (cnx_needed(pool))
-		return;
-
-	while (pool->enabled == POOL_DISABLED ||
+	while (!cnx_needed(pool) && (pool->enabled == POOL_DISABLED ||
 	       (pool != current_pool() && pool_strategy != POOL_LOADBALANCE &&
 	       (pool != current_pool() && pool_strategy != POOL_LOADBALANCE &&
-	       pool_strategy != POOL_BALANCE)) {
+	       pool_strategy != POOL_BALANCE))) {
 		mutex_lock(&lp_lock);
 		mutex_lock(&lp_lock);
 		pthread_cond_wait(&lp_cond, &lp_lock);
 		pthread_cond_wait(&lp_cond, &lp_lock);
 		mutex_unlock(&lp_lock);
 		mutex_unlock(&lp_lock);
@@ -8419,7 +8458,7 @@ retry_pool:
 	if (!pool) {
 	if (!pool) {
 		applog(LOG_WARNING, "No suitable long-poll found for %s", cp->rpc_url);
 		applog(LOG_WARNING, "No suitable long-poll found for %s", cp->rpc_url);
 		while (!pool) {
 		while (!pool) {
-			nmsleep(60000);
+			cgsleep_ms(60000);
 			pool = select_longpoll_pool(cp);
 			pool = select_longpoll_pool(cp);
 		}
 		}
 	}
 	}
@@ -8496,7 +8535,7 @@ retry_pool:
 			if (failures == 1)
 			if (failures == 1)
 				applog(LOG_WARNING, "longpoll failed for %s, retrying every 30s", lp_url);
 				applog(LOG_WARNING, "longpoll failed for %s, retrying every 30s", lp_url);
 lpfail:
 lpfail:
-			nmsleep(30000);
+			cgsleep_ms(30000);
 		}
 		}
 
 
 		if (pool != cp) {
 		if (pool != cp) {
@@ -8647,7 +8686,7 @@ static void *watchpool_thread(void __maybe_unused *userdata)
 			switch_pools(NULL);
 			switch_pools(NULL);
 		}
 		}
 
 
-		nmsleep(30000);
+		cgsleep_ms(30000);
 			
 			
 	}
 	}
 	return NULL;
 	return NULL;
@@ -9021,6 +9060,9 @@ void _bfg_clean_up(void)
 #endif
 #endif
 
 
 	cgtime(&total_tv_end);
 	cgtime(&total_tv_end);
+#ifdef WIN32
+	timeEndPeriod(1);
+#endif
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
 	disable_curses();
 	disable_curses();
 #endif
 #endif
@@ -9391,7 +9433,7 @@ void renumber_cgpu(struct cgpu_info *cgpu)
 
 
 static bool my_blkmaker_sha256_callback(void *digest, const void *buffer, size_t length)
 static bool my_blkmaker_sha256_callback(void *digest, const void *buffer, size_t length)
 {
 {
-	sha2(buffer, length, digest);
+	sha256(buffer, length, digest);
 	return true;
 	return true;
 }
 }
 
 
@@ -9767,6 +9809,8 @@ int main(int argc, char *argv[])
 	sigaction(SIGINT, &handler, &inthandler);
 	sigaction(SIGINT, &handler, &inthandler);
 #ifndef WIN32
 #ifndef WIN32
 	signal(SIGPIPE, SIG_IGN);
 	signal(SIGPIPE, SIG_IGN);
+#else
+	timeBeginPeriod(1);
 #endif
 #endif
 	opt_kernel_path = alloca(PATH_MAX);
 	opt_kernel_path = alloca(PATH_MAX);
 	strcpy(opt_kernel_path, CGMINER_PREFIX);
 	strcpy(opt_kernel_path, CGMINER_PREFIX);
@@ -10266,7 +10310,7 @@ retry:
 				struct pool *altpool = select_pool(true);
 				struct pool *altpool = select_pool(true);
 
 
 				if (altpool == pool && pool->has_stratum)
 				if (altpool == pool && pool->has_stratum)
-					nmsleep(5000);
+					cgsleep_ms(5000);
 				pool = altpool;
 				pool = altpool;
 				goto retry;
 				goto retry;
 			}
 			}
@@ -10328,7 +10372,7 @@ retry:
 			next_pool = select_pool(!opt_fail_only);
 			next_pool = select_pool(!opt_fail_only);
 			if (pool == next_pool) {
 			if (pool == next_pool) {
 				applog(LOG_DEBUG, "Pool %d json_rpc_call failed on get work, retrying in 5s", pool->pool_no);
 				applog(LOG_DEBUG, "Pool %d json_rpc_call failed on get work, retrying in 5s", pool->pool_no);
-				nmsleep(5000);
+				cgsleep_ms(5000);
 			} else {
 			} else {
 				applog(LOG_DEBUG, "Pool %d json_rpc_call failed on get work, failover activated", pool->pool_no);
 				applog(LOG_DEBUG, "Pool %d json_rpc_call failed on get work, failover activated", pool->pool_no);
 				pool = next_pool;
 				pool = next_pool;

+ 8 - 0
miner.h

@@ -873,6 +873,9 @@ static inline void cg_wunlock(cglock_t *lock)
 
 
 struct pool;
 struct pool;
 
 
+#define API_MCAST_CODE "FTW"
+#define API_MCAST_ADDR "224.0.0.75"
+
 extern bool opt_protocol;
 extern bool opt_protocol;
 extern bool opt_dev_protocol;
 extern bool opt_dev_protocol;
 extern char *opt_coinbase_sig;
 extern char *opt_coinbase_sig;
@@ -889,6 +892,10 @@ extern bool opt_autoengine;
 extern bool use_curses;
 extern bool use_curses;
 extern int httpsrv_port;
 extern int httpsrv_port;
 extern char *opt_api_allow;
 extern char *opt_api_allow;
+extern bool opt_api_mcast;
+extern char *opt_api_mcast_addr;
+extern char *opt_api_mcast_code;
+extern int opt_api_mcast_port;
 extern char *opt_api_groups;
 extern char *opt_api_groups;
 extern char *opt_api_description;
 extern char *opt_api_description;
 extern int opt_api_port;
 extern int opt_api_port;
@@ -1336,6 +1343,7 @@ extern bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce
 extern struct work *get_queued(struct cgpu_info *cgpu);
 extern struct work *get_queued(struct cgpu_info *cgpu);
 extern struct work *__find_work_bymidstate(struct work *que, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
 extern struct work *__find_work_bymidstate(struct work *que, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
 extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
 extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
+extern struct work *clone_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
 extern void work_completed(struct cgpu_info *cgpu, struct work *work);
 extern void work_completed(struct cgpu_info *cgpu, struct work *work);
 extern bool abandon_work(struct work *, struct timeval *work_runtime, uint64_t hashes);
 extern bool abandon_work(struct work *, struct timeval *work_runtime, uint64_t hashes);
 extern void hash_queued_work(struct thr_info *mythr);
 extern void hash_queued_work(struct thr_info *mythr);

+ 178 - 267
sha2.c

@@ -1,307 +1,218 @@
 /*
 /*
- *  FIPS-180-2 compliant SHA-256 implementation
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
  *
  *
- *  Copyright (C) 2011, Con Kolivas
- *  Copyright (C) 2006-2010, Brainspark B.V.
+ * Copyright 2013 Con Kolivas
+ * Copyright 2005 2007 Olivier Gay
+ * All rights reserved.
  *
  *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-/*
- *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
- *
- *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
  */
 
 
+#include <string.h>
+
 #include "sha2.h"
 #include "sha2.h"
 
 
-#include <string.h>
-#include <stdio.h>
+#define SHFR(x, n)    (x >> n)
+#define ROTR(x, n)   ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define CH(x, y, z)  ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define UNPACK32(x, str)                      \
+{                                             \
+    *((str) + 3) = (uint8_t) ((x)      );       \
+    *((str) + 2) = (uint8_t) ((x) >>  8);       \
+    *((str) + 1) = (uint8_t) ((x) >> 16);       \
+    *((str) + 0) = (uint8_t) ((x) >> 24);       \
+}
 
 
-/*
- * 32-bit integer manipulation macros (big endian)
- */
-#ifndef GET_ULONG_BE
-#define GET_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (n) = ( (uint32_t) (b)[(i)    ] << 24 )        \
-        | ( (uint32_t) (b)[(i) + 1] << 16 )        \
-        | ( (uint32_t) (b)[(i) + 2] <<  8 )        \
-        | ( (uint32_t) (b)[(i) + 3]       );       \
+#define PACK32(str, x)                        \
+{                                             \
+    *(x) =   ((uint32_t) *((str) + 3)      )    \
+           | ((uint32_t) *((str) + 2) <<  8)    \
+           | ((uint32_t) *((str) + 1) << 16)    \
+           | ((uint32_t) *((str) + 0) << 24);   \
 }
 }
-#endif
-
-#ifndef PUT_ULONG_BE
-#define PUT_ULONG_BE(n,b,i)                             \
-{                                                       \
-    (b)[(i)    ] = (unsigned char) ( (n) >> 24 );       \
-    (b)[(i) + 1] = (unsigned char) ( (n) >> 16 );       \
-    (b)[(i) + 2] = (unsigned char) ( (n) >>  8 );       \
-    (b)[(i) + 3] = (unsigned char) ( (n)       );       \
+
+#define SHA256_SCR(i)                         \
+{                                             \
+    w[i] =  SHA256_F4(w[i -  2]) + w[i -  7]  \
+          + SHA256_F3(w[i - 15]) + w[i - 16]; \
 }
 }
-#endif
 
 
-/*
- * SHA-256 context setup
- */
-void sha2_starts( sha2_context *ctx )
+uint32_t sha256_h0[8] =
+            {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+             0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+
+uint32_t sha256_k[64] =
+            {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+             0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+             0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+             0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+             0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+             0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+             0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+             0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+             0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+             0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+             0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+             0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+             0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+             0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+             0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+             0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+/* SHA-256 functions */
+
+void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
+                   unsigned int block_nb)
 {
 {
-    ctx->total[0] = 0;
-    ctx->total[1] = 0;
-
-    ctx->state[0] = 0x6A09E667;
-    ctx->state[1] = 0xBB67AE85;
-    ctx->state[2] = 0x3C6EF372;
-    ctx->state[3] = 0xA54FF53A;
-    ctx->state[4] = 0x510E527F;
-    ctx->state[5] = 0x9B05688C;
-    ctx->state[6] = 0x1F83D9AB;
-    ctx->state[7] = 0x5BE0CD19;
+    uint32_t w[64];
+    uint32_t wv[8];
+    uint32_t t1, t2;
+    const unsigned char *sub_block;
+    int i;
+
+    int j;
+
+    for (i = 0; i < (int) block_nb; i++) {
+        sub_block = message + (i << 6);
+
+        for (j = 0; j < 16; j++) {
+            PACK32(&sub_block[j << 2], &w[j]);
+        }
+
+        for (j = 16; j < 64; j++) {
+            SHA256_SCR(j);
+        }
+
+        for (j = 0; j < 8; j++) {
+            wv[j] = ctx->h[j];
+        }
+
+        for (j = 0; j < 64; j++) {
+            t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+                + sha256_k[j] + w[j];
+            t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+            wv[7] = wv[6];
+            wv[6] = wv[5];
+            wv[5] = wv[4];
+            wv[4] = wv[3] + t1;
+            wv[3] = wv[2];
+            wv[2] = wv[1];
+            wv[1] = wv[0];
+            wv[0] = t1 + t2;
+        }
+
+        for (j = 0; j < 8; j++) {
+            ctx->h[j] += wv[j];
+        }
+    }
 }
 }
 
 
-static void sha2_process( sha2_context *ctx, const unsigned char data[64] )
+void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
 {
 {
-    uint32_t temp1, temp2, W[64];
-    uint32_t A, B, C, D, E, F, G, H;
-
-    GET_ULONG_BE( W[ 0], data,  0 );
-    GET_ULONG_BE( W[ 1], data,  4 );
-    GET_ULONG_BE( W[ 2], data,  8 );
-    GET_ULONG_BE( W[ 3], data, 12 );
-    GET_ULONG_BE( W[ 4], data, 16 );
-    GET_ULONG_BE( W[ 5], data, 20 );
-    GET_ULONG_BE( W[ 6], data, 24 );
-    GET_ULONG_BE( W[ 7], data, 28 );
-    GET_ULONG_BE( W[ 8], data, 32 );
-    GET_ULONG_BE( W[ 9], data, 36 );
-    GET_ULONG_BE( W[10], data, 40 );
-    GET_ULONG_BE( W[11], data, 44 );
-    GET_ULONG_BE( W[12], data, 48 );
-    GET_ULONG_BE( W[13], data, 52 );
-    GET_ULONG_BE( W[14], data, 56 );
-    GET_ULONG_BE( W[15], data, 60 );
-
-#define  SHR(x,n) ((x & 0xFFFFFFFF) >> n)
-#define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
-
-#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^  SHR(x, 3))
-#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^  SHR(x,10))
-
-#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
-#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
-
-#define F0(x,y,z) ((x & y) | (z & (x | y)))
-#define F1(x,y,z) (z ^ (x & (y ^ z)))
-
-#define R(t)                                    \
-(                                               \
-    W[t] = S1(W[t -  2]) + W[t -  7] +          \
-           S0(W[t - 15]) + W[t - 16]            \
-)
-
-#define P(a,b,c,d,e,f,g,h,x,K)                  \
-{                                               \
-    temp1 = h + S3(e) + F1(e,f,g) + K + x;      \
-    temp2 = S2(a) + F0(a,b,c);                  \
-    d += temp1; h = temp1 + temp2;              \
-}
+    sha256_ctx ctx;
 
 
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-    F = ctx->state[5];
-    G = ctx->state[6];
-    H = ctx->state[7];
-
-    P( A, B, C, D, E, F, G, H, W[ 0], 0x428A2F98 );
-    P( H, A, B, C, D, E, F, G, W[ 1], 0x71374491 );
-    P( G, H, A, B, C, D, E, F, W[ 2], 0xB5C0FBCF );
-    P( F, G, H, A, B, C, D, E, W[ 3], 0xE9B5DBA5 );
-    P( E, F, G, H, A, B, C, D, W[ 4], 0x3956C25B );
-    P( D, E, F, G, H, A, B, C, W[ 5], 0x59F111F1 );
-    P( C, D, E, F, G, H, A, B, W[ 6], 0x923F82A4 );
-    P( B, C, D, E, F, G, H, A, W[ 7], 0xAB1C5ED5 );
-    P( A, B, C, D, E, F, G, H, W[ 8], 0xD807AA98 );
-    P( H, A, B, C, D, E, F, G, W[ 9], 0x12835B01 );
-    P( G, H, A, B, C, D, E, F, W[10], 0x243185BE );
-    P( F, G, H, A, B, C, D, E, W[11], 0x550C7DC3 );
-    P( E, F, G, H, A, B, C, D, W[12], 0x72BE5D74 );
-    P( D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE );
-    P( C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7 );
-    P( B, C, D, E, F, G, H, A, W[15], 0xC19BF174 );
-    P( A, B, C, D, E, F, G, H, R(16), 0xE49B69C1 );
-    P( H, A, B, C, D, E, F, G, R(17), 0xEFBE4786 );
-    P( G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6 );
-    P( F, G, H, A, B, C, D, E, R(19), 0x240CA1CC );
-    P( E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F );
-    P( D, E, F, G, H, A, B, C, R(21), 0x4A7484AA );
-    P( C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC );
-    P( B, C, D, E, F, G, H, A, R(23), 0x76F988DA );
-    P( A, B, C, D, E, F, G, H, R(24), 0x983E5152 );
-    P( H, A, B, C, D, E, F, G, R(25), 0xA831C66D );
-    P( G, H, A, B, C, D, E, F, R(26), 0xB00327C8 );
-    P( F, G, H, A, B, C, D, E, R(27), 0xBF597FC7 );
-    P( E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3 );
-    P( D, E, F, G, H, A, B, C, R(29), 0xD5A79147 );
-    P( C, D, E, F, G, H, A, B, R(30), 0x06CA6351 );
-    P( B, C, D, E, F, G, H, A, R(31), 0x14292967 );
-    P( A, B, C, D, E, F, G, H, R(32), 0x27B70A85 );
-    P( H, A, B, C, D, E, F, G, R(33), 0x2E1B2138 );
-    P( G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC );
-    P( F, G, H, A, B, C, D, E, R(35), 0x53380D13 );
-    P( E, F, G, H, A, B, C, D, R(36), 0x650A7354 );
-    P( D, E, F, G, H, A, B, C, R(37), 0x766A0ABB );
-    P( C, D, E, F, G, H, A, B, R(38), 0x81C2C92E );
-    P( B, C, D, E, F, G, H, A, R(39), 0x92722C85 );
-    P( A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1 );
-    P( H, A, B, C, D, E, F, G, R(41), 0xA81A664B );
-    P( G, H, A, B, C, D, E, F, R(42), 0xC24B8B70 );
-    P( F, G, H, A, B, C, D, E, R(43), 0xC76C51A3 );
-    P( E, F, G, H, A, B, C, D, R(44), 0xD192E819 );
-    P( D, E, F, G, H, A, B, C, R(45), 0xD6990624 );
-    P( C, D, E, F, G, H, A, B, R(46), 0xF40E3585 );
-    P( B, C, D, E, F, G, H, A, R(47), 0x106AA070 );
-    P( A, B, C, D, E, F, G, H, R(48), 0x19A4C116 );
-    P( H, A, B, C, D, E, F, G, R(49), 0x1E376C08 );
-    P( G, H, A, B, C, D, E, F, R(50), 0x2748774C );
-    P( F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5 );
-    P( E, F, G, H, A, B, C, D, R(52), 0x391C0CB3 );
-    P( D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A );
-    P( C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F );
-    P( B, C, D, E, F, G, H, A, R(55), 0x682E6FF3 );
-    P( A, B, C, D, E, F, G, H, R(56), 0x748F82EE );
-    P( H, A, B, C, D, E, F, G, R(57), 0x78A5636F );
-    P( G, H, A, B, C, D, E, F, R(58), 0x84C87814 );
-    P( F, G, H, A, B, C, D, E, R(59), 0x8CC70208 );
-    P( E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA );
-    P( D, E, F, G, H, A, B, C, R(61), 0xA4506CEB );
-    P( C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7 );
-    P( B, C, D, E, F, G, H, A, R(63), 0xC67178F2 );
-
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-    ctx->state[5] += F;
-    ctx->state[6] += G;
-    ctx->state[7] += H;
+    sha256_init(&ctx);
+    sha256_update(&ctx, message, len);
+    sha256_final(&ctx, digest);
 }
 }
 
 
-/*
- * SHA-256 process buffer
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen )
+void sha256_init(sha256_ctx *ctx)
 {
 {
-    int fill;
-    uint32_t left;
+    int i;
+    for (i = 0; i < 8; i++) {
+        ctx->h[i] = sha256_h0[i];
+    }
 
 
-    if( ilen <= 0 )
-        return;
+    ctx->len = 0;
+    ctx->tot_len = 0;
+}
 
 
-    left = ctx->total[0] & 0x3F;
-    fill = 64 - left;
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+                   unsigned int len)
+{
+    unsigned int block_nb;
+    unsigned int new_len, rem_len, tmp_len;
+    const unsigned char *shifted_message;
 
 
-    ctx->total[0] += ilen;
-    ctx->total[0] &= 0xFFFFFFFF;
+    tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+    rem_len = len < tmp_len ? len : tmp_len;
 
 
-    if( ctx->total[0] < (uint32_t) ilen )
-        ctx->total[1]++;
+    memcpy(&ctx->block[ctx->len], message, rem_len);
 
 
-    if( left && ilen >= fill )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, fill );
-        sha2_process( ctx, ctx->buffer );
-        input += fill;
-        ilen  -= fill;
-        left = 0;
+    if (ctx->len + len < SHA256_BLOCK_SIZE) {
+        ctx->len += len;
+        return;
     }
     }
 
 
-    while( ilen >= 64 )
-    {
-        sha2_process( ctx, input );
-        input += 64;
-        ilen  -= 64;
-    }
+    new_len = len - rem_len;
+    block_nb = new_len / SHA256_BLOCK_SIZE;
 
 
-    if( ilen > 0 )
-    {
-        memcpy( (void *) (ctx->buffer + left),
-                (void *) input, ilen );
-    }
-}
+    shifted_message = message + rem_len;
 
 
-static const unsigned char sha2_padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+    sha256_transf(ctx, ctx->block, 1);
+    sha256_transf(ctx, shifted_message, block_nb);
 
 
-/*
- * SHA-256 final digest
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] )
-{
-    uint32_t last, padn;
-    uint32_t high, low;
-    unsigned char msglen[8];
+    rem_len = new_len % SHA256_BLOCK_SIZE;
 
 
-    high = ( ctx->total[0] >> 29 )
-         | ( ctx->total[1] <<  3 );
-    low  = ( ctx->total[0] <<  3 );
+    memcpy(ctx->block, &shifted_message[block_nb << 6],
+           rem_len);
 
 
-    PUT_ULONG_BE( high, msglen, 0 );
-    PUT_ULONG_BE( low,  msglen, 4 );
+    ctx->len = rem_len;
+    ctx->tot_len += (block_nb + 1) << 6;
+}
 
 
-    last = ctx->total[0] & 0x3F;
-    padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
+void sha256_final(sha256_ctx *ctx, unsigned char *digest)
+{
+    unsigned int block_nb;
+    unsigned int pm_len;
+    unsigned int len_b;
 
 
-    sha2_update( ctx, (unsigned char *) sha2_padding, padn );
-    sha2_update( ctx, msglen, 8 );
+    int i;
 
 
-    PUT_ULONG_BE( ctx->state[0], output,  0 );
-    PUT_ULONG_BE( ctx->state[1], output,  4 );
-    PUT_ULONG_BE( ctx->state[2], output,  8 );
-    PUT_ULONG_BE( ctx->state[3], output, 12 );
-    PUT_ULONG_BE( ctx->state[4], output, 16 );
-    PUT_ULONG_BE( ctx->state[5], output, 20 );
-    PUT_ULONG_BE( ctx->state[6], output, 24 );
+    block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
+                     < (ctx->len % SHA256_BLOCK_SIZE)));
 
 
-    PUT_ULONG_BE( ctx->state[7], output, 28 );
-}
+    len_b = (ctx->tot_len + ctx->len) << 3;
+    pm_len = block_nb << 6;
 
 
-/*
- * output = SHA-256( input buffer )
- */
-void sha2( const unsigned char *input, int ilen,
-           unsigned char output[32] )
-{
-    sha2_context ctx;
+    memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+    ctx->block[ctx->len] = 0x80;
+    UNPACK32(len_b, ctx->block + pm_len - 4);
 
 
-    sha2_starts( &ctx );
-    sha2_update( &ctx, input, ilen );
-    sha2_finish( &ctx, output );
+    sha256_transf(ctx, ctx->block, block_nb);
 
 
-    memset( &ctx, 0, sizeof( sha2_context ) );
+    for (i = 0 ; i < 8; i++) {
+        UNPACK32(ctx->h[i], &digest[i << 2]);
+    }
 }
 }

+ 51 - 80
sha2.h

@@ -1,87 +1,58 @@
-/**
- * \file sha2.h
- *
- *  Copyright (C) 2011, Con Kolivas
- *  Copyright (C) 2006-2010, Brainspark B.V.
- *
- *  This file is part of PolarSSL (http://www.polarssl.org)
- *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
- *
- *  All rights reserved.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date:  04/30/2005
+ *
+ * Copyright 2013 Con Kolivas
+ * Copyright 2005, 2007 Olivier Gay
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
  */
-#ifndef POLARSSL_SHA2_H
-#define POLARSSL_SHA2_H
-
-#include <stdint.h>
 
 
-/**
- * \brief          SHA-256 context structure
- */
-typedef struct
-{
-    uint32_t total[2];     /*!< number of bytes processed  */
-    uint32_t state[8];     /*!< intermediate digest state  */
-    unsigned char buffer[64];   /*!< data block being processed */
+#include "config.h"
+#include "miner.h"
 
 
-    unsigned char ipad[64];     /*!< HMAC: inner padding        */
-    unsigned char opad[64];     /*!< HMAC: outer padding        */
-}
-sha2_context;
+#ifndef SHA2_H
+#define SHA2_H
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define SHA256_DIGEST_SIZE ( 256 / 8)
+#define SHA256_BLOCK_SIZE  ( 512 / 8)
 
 
-/**
- * \brief          SHA-256 context setup
- *
- * \param ctx      context to be initialized
- */
-void sha2_starts( sha2_context *ctx);
-
-/**
- * \brief          SHA-256 process buffer
- *
- * \param ctx      SHA-256 context
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- */
-void sha2_update( sha2_context *ctx, const unsigned char *input, int ilen );
-
-/**
- * \brief          SHA-256 final digest
- *
- * \param ctx      SHA-256 context
- * \param output   SHA-256 checksum result
- */
-void sha2_finish( sha2_context *ctx, unsigned char output[32] );
-
-/**
- * \brief          Output = SHA-256( input buffer )
- *
- * \param input    buffer holding the  data
- * \param ilen     length of the input data
- * \param output   SHA-256 checksum result
- */
-void sha2( const unsigned char *input, int ilen,
-           unsigned char output[32]);
+typedef struct {
+    unsigned int tot_len;
+    unsigned int len;
+    unsigned char block[2 * SHA256_BLOCK_SIZE];
+    uint32_t h[8];
+} sha256_ctx;
 
 
-#ifdef __cplusplus
-}
-#endif
+void sha256_init(sha256_ctx * ctx);
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+                   unsigned int len);
+void sha256_final(sha256_ctx *ctx, unsigned char *digest);
+void sha256(const unsigned char *message, unsigned int len,
+            unsigned char *digest);
 
 
-#endif /* sha2.h */
+#endif /* !SHA2_H */

+ 219 - 59
util.c

@@ -1053,65 +1053,7 @@ void setup_pthread_cancel_workaround()
 
 
 #endif
 #endif
 
 
-/* Provide a ms based sleep that uses nanosleep to avoid poor usleep accuracy
- * on SMP machines */
-void nmsleep(unsigned int msecs)
-{
-	struct timespec twait, tleft;
-	int ret;
-	ldiv_t d;
-
-#ifdef WIN32
-	timeBeginPeriod(1);
-#endif
-	d = ldiv(msecs, 1000);
-	tleft.tv_sec = d.quot;
-	tleft.tv_nsec = d.rem * 1000000;
-	do {
-		twait.tv_sec = tleft.tv_sec;
-		twait.tv_nsec = tleft.tv_nsec;
-		ret = nanosleep(&twait, &tleft);
-	} while (ret == -1 && errno == EINTR);
-#ifdef WIN32
-	timeEndPeriod(1);
-#endif
-}
-
-/* Same for usecs */
-void nusleep(unsigned int usecs)
-{
-	struct timespec twait, tleft;
-	int ret;
-	ldiv_t d;
-
-#ifdef WIN32
-	timeBeginPeriod(1);
-#endif
-	d = ldiv(usecs, 1000000);
-	tleft.tv_sec = d.quot;
-	tleft.tv_nsec = d.rem * 1000;
-	do {
-		twait.tv_sec = tleft.tv_sec;
-		twait.tv_nsec = tleft.tv_nsec;
-		ret = nanosleep(&twait, &tleft);
-	} while (ret == -1 && errno == EINTR);
-#ifdef WIN32
-	timeEndPeriod(1);
-#endif
-}
-
-static
-void _now_gettimeofday(struct timeval *tv)
-{
-#ifdef WIN32
-	// Windows' default resolution is only 15ms. This requests 1ms.
-	timeBeginPeriod(1);
-#endif
-	gettimeofday(tv, NULL);
-#ifdef WIN32
-	timeEndPeriod(1);
-#endif
-}
+static void _now_gettimeofday(struct timeval *);
 
 
 #ifdef HAVE_POOR_GETTIMEOFDAY
 #ifdef HAVE_POOR_GETTIMEOFDAY
 static struct timeval tv_timeofday_offset;
 static struct timeval tv_timeofday_offset;
@@ -1266,6 +1208,224 @@ void copy_time(struct timeval *dest, const struct timeval *src)
 	memcpy(dest, src, sizeof(struct timeval));
 	memcpy(dest, src, sizeof(struct timeval));
 }
 }
 
 
+void timespec_to_val(struct timeval *val, const struct timespec *spec)
+{
+	val->tv_sec = spec->tv_sec;
+	val->tv_usec = spec->tv_nsec / 1000;
+}
+
+void timeval_to_spec(struct timespec *spec, const struct timeval *val)
+{
+	spec->tv_sec = val->tv_sec;
+	spec->tv_nsec = val->tv_usec * 1000;
+}
+
+void us_to_timeval(struct timeval *val, int64_t us)
+{
+	lldiv_t tvdiv = lldiv(us, 1000000);
+
+	val->tv_sec = tvdiv.quot;
+	val->tv_usec = tvdiv.rem;
+}
+
+void us_to_timespec(struct timespec *spec, int64_t us)
+{
+	lldiv_t tvdiv = lldiv(us, 1000000);
+
+	spec->tv_sec = tvdiv.quot;
+	spec->tv_nsec = tvdiv.rem * 1000;
+}
+
+void ms_to_timespec(struct timespec *spec, int64_t ms)
+{
+	lldiv_t tvdiv = lldiv(ms, 1000);
+
+	spec->tv_sec = tvdiv.quot;
+	spec->tv_nsec = tvdiv.rem * 1000000;
+}
+
+void timeraddspec(struct timespec *a, const struct timespec *b)
+{
+	a->tv_sec += b->tv_sec;
+	a->tv_nsec += b->tv_nsec;
+	if (a->tv_nsec >= 1000000000) {
+		a->tv_nsec -= 1000000000;
+		a->tv_sec++;
+	}
+}
+
+static int timespec_to_ms(struct timespec *ts)
+{
+	return ts->tv_sec * 1000 + ts->tv_nsec / 1000000;
+}
+
+/* These are cgminer specific sleep functions that use an absolute nanosecond
+ * resolution timer to avoid poor usleep accuracy and overruns. */
+#ifndef WIN32
+void cgtimer_time(cgtimer_t *ts_start)
+{
+	clock_gettime(CLOCK_MONOTONIC, ts_start);
+}
+
+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 *ts_start, int ms)
+{
+	struct timespec ts_end;
+
+	ms_to_timespec(&ts_end, ms);
+	timeraddspec(&ts_end, ts_start);
+	nanosleep_abstime(&ts_end);
+}
+
+void cgsleep_us_r(cgtimer_t *ts_start, int64_t us)
+{
+	struct timespec ts_end;
+
+	us_to_timespec(&ts_end, us);
+	timeraddspec(&ts_end, ts_start);
+	nanosleep_abstime(&ts_end);
+}
+
+int cgtimer_to_ms(cgtimer_t *cgt)
+{
+	return timespec_to_ms(cgt);
+}
+
+/* Subtracts b from a and stores it in res. */
+void cgtimer_sub(cgtimer_t *a, cgtimer_t *b, cgtimer_t *res)
+{
+	res->tv_sec = a->tv_sec - b->tv_sec;
+	res->tv_nsec = a->tv_nsec - b->tv_nsec;
+	if (res->tv_nsec < 0) {
+		res->tv_nsec += 1000000000;
+		res->tv_sec--;
+	}
+}
+
+static
+void _now_gettimeofday(struct timeval *tv)
+{
+	gettimeofday(tv, NULL);
+}
+#else
+/* Windows start time is since 1601 lol so convert it to unix epoch 1970. */
+#define EPOCHFILETIME (116444736000000000LL)
+
+/* Return the system time as an lldiv_t in decimicroseconds. */
+static void decius_time(lldiv_t *lidiv)
+{
+	FILETIME ft;
+	LARGE_INTEGER li;
+
+	GetSystemTimeAsFileTime(&ft);
+	li.LowPart  = ft.dwLowDateTime;
+	li.HighPart = ft.dwHighDateTime;
+	li.QuadPart -= EPOCHFILETIME;
+
+	/* SystemTime is in decimicroseconds so divide by an unusual number */
+	*lidiv = lldiv(li.QuadPart, 10000000);
+}
+
+void _now_gettimeofday(struct timeval *tv)
+{
+	lldiv_t lidiv;
+
+	decius_time(&lidiv);
+	tv->tv_sec = lidiv.quot;
+	tv->tv_usec = lidiv.rem / 10;
+}
+
+void cgtimer_time(cgtimer_t *ts_start)
+{
+	lldiv_t lidiv;;
+
+	decius_time(&lidiv);
+	ts_start->tv_sec = lidiv.quot;
+	ts_start->tv_nsec = lidiv.quot * 100;
+}
+
+/* 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);
+}
+
+void cgsleep_ms_r(cgtimer_t *ts_start, int ms)
+{
+	struct timespec ts_diff;
+
+	ms_to_timespec(&ts_diff, ms);
+	cgsleep_spec(&ts_diff, ts_start);
+}
+
+void cgsleep_us_r(cgtimer_t *ts_start, int64_t us)
+{
+	struct timespec ts_diff;
+
+	us_to_timespec(&ts_diff, us);
+	cgsleep_spec(&ts_diff, ts_start);
+}
+
+int cgtimer_to_ms(cgtimer_t *cgt)
+{
+	return timespec_to_ms(cgt);
+}
+
+void cgtimer_sub(cgtimer_t *a, cgtimer_t *b, cgtimer_t *res)
+{
+	res->tv_sec = a->tv_sec - b->tv_sec;
+	res->tv_nsec = a->tv_nsec - b->tv_nsec;
+	if (res->tv_nsec < 0) {
+		res->tv_nsec += 1000000000;;
+		res->tv_sec--;
+	}
+}
+#endif
+
+void cgsleep_ms(int ms)
+{
+	cgtimer_t ts_start;
+
+	cgsleep_prepare_r(&ts_start);
+	cgsleep_ms_r(&ts_start, ms);
+}
+
+void cgsleep_us(int64_t us)
+{
+	cgtimer_t ts_start;
+
+	cgsleep_prepare_r(&ts_start);
+	cgsleep_us_r(&ts_start, us);
+}
+
 /* Returns the microseconds difference between end and start times as a double */
 /* Returns the microseconds difference between end and start times as a double */
 double us_tdiff(struct timeval *end, struct timeval *start)
 double us_tdiff(struct timeval *end, struct timeval *start)
 {
 {

+ 16 - 2
util.h

@@ -98,6 +98,8 @@ bool isCspace(int c)
 	}
 	}
 }
 }
 
 
+typedef struct timespec cgtimer_t;
+
 struct thr_info;
 struct thr_info;
 struct pool;
 struct pool;
 enum dev_reason;
 enum dev_reason;
@@ -117,13 +119,25 @@ extern bool hash_target_check_v(const unsigned char *hash, const unsigned char *
 int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
 int thr_info_create(struct thr_info *thr, pthread_attr_t *attr, void *(*start) (void *), void *arg);
 void thr_info_freeze(struct thr_info *thr);
 void thr_info_freeze(struct thr_info *thr);
 void thr_info_cancel(struct thr_info *thr);
 void thr_info_cancel(struct thr_info *thr);
-void nmsleep(unsigned int msecs);
-void nusleep(unsigned int usecs);
 void subtime(struct timeval *a, struct timeval *b);
 void subtime(struct timeval *a, struct timeval *b);
 void addtime(struct timeval *a, struct timeval *b);
 void addtime(struct timeval *a, struct timeval *b);
 bool time_more(struct timeval *a, struct timeval *b);
 bool time_more(struct timeval *a, struct timeval *b);
 bool time_less(struct timeval *a, struct timeval *b);
 bool time_less(struct timeval *a, struct timeval *b);
 void copy_time(struct timeval *dest, const struct timeval *src);
 void copy_time(struct timeval *dest, const struct timeval *src);
+void timespec_to_val(struct timeval *val, const struct timespec *spec);
+void timeval_to_spec(struct timespec *spec, const struct timeval *val);
+void us_to_timeval(struct timeval *val, int64_t us);
+void us_to_timespec(struct timespec *spec, int64_t us);
+void ms_to_timespec(struct timespec *spec, int64_t ms);
+void timeraddspec(struct timespec *a, const struct timespec *b);
+void cgsleep_ms(int ms);
+void cgsleep_us(int64_t us);
+void cgtimer_time(cgtimer_t *ts_start);
+#define cgsleep_prepare_r(ts_start) cgtimer_time(ts_start)
+void cgsleep_ms_r(cgtimer_t *ts_start, int ms);
+void cgsleep_us_r(cgtimer_t *ts_start, int64_t us);
+int cgtimer_to_ms(cgtimer_t *cgt);
+void cgtimer_sub(cgtimer_t *a, cgtimer_t *b, cgtimer_t *res);
 double us_tdiff(struct timeval *end, struct timeval *start);
 double us_tdiff(struct timeval *end, struct timeval *start);
 double tdiff(struct timeval *end, struct timeval *start);
 double tdiff(struct timeval *end, struct timeval *start);
 bool _stratum_send(struct pool *pool, char *s, ssize_t len, bool force);
 bool _stratum_send(struct pool *pool, char *s, ssize_t len, bool force);