Browse Source

Merge commit '1e94214' into bfgminer

Luke Dashjr 13 years ago
parent
commit
d2a7357d0e
9 changed files with 166 additions and 104 deletions
  1. 81 0
      NEWS
  2. 18 8
      adl.c
  3. 28 32
      api.c
  4. 1 1
      configure.ac
  5. 1 1
      driver-icarus.c
  6. 1 1
      driver-modminer.c
  7. 11 8
      miner.c
  8. 1 3
      miner.h
  9. 24 50
      util.c

+ 81 - 0
NEWS

@@ -1,3 +1,84 @@
+Version 2.4.4 - July 1, 2012
+
+- Fix builds on non gnu platforms.
+- api.c ensure old mode is always available when not using --api-groups + quit()
+on param errors
+- Implement rudimentary X-Mining-Hashrate support.
+- Detect large swings in temperature when below the target temperature range and
+change fan by amounts dependant on the value of tdiff.
+- Adjust the fanspeed by the magnitude of the temperature difference when in the
+optimal range.
+- Revert "Restarting cgminer from within after ADL has been corrupted only leads
+to a crash. Display a warning only and disable fanspeed monitoring."
+- api.c fix json already closed
+- implement and document API option --api-groups
+- Put upper bounds to under 2 hours that work can be rolled into the future for
+bitcoind will deem it invalid beyond that.
+- define API option --api-groups
+- api.c allow unwell devices to be enabled so they can be cured
+- miner.php - fix/enable autorefresh for custom pages
+- miner.php allow custom summary pages - new 'Mobile' summary
+- Work around pools that advertise very low expire= time inappropriately as this
+leads to many false positives for stale shares detected.
+- Only show ztex board count if any exist.
+- There is no need for work to be a union in struct workio_cmd
+- fpgautils.c include a debug message for all unknown open errors
+- Don't keep rolling work right up to the expire= cut off. Use 2/3 of the time
+between the scantime and the expiry as cutoff for reusing work.
+- Log a specific error when serial opens fail due to lack of user permissions
+- Increase GPU timing resolution to microsecond and add sanity check to ensure
+times are positive.
+- Opencl code may start executing before the clfinish order is given to it so
+get the start timing used for dynamic intensity from before the kernel is
+queued.
+- fpgautils.c - set BAUD rate according to termio spec
+- fpgautils.c - linux ordering back to the correct way
+- miner.php remove unneeded '.'s
+- miner.php add auto refresh options
+- miner.php add 'restart' next to 'quit'
+- miner.php make fontname/size configurable with myminer.php
+- Make the pools array a dynamically allocated array to allow unlimited pools to
+be added.
+- Make the devices array a dynamically allocated array of pointers to allow
+unlimited devices.
+- Dynamic intensity for GPUs should be calculated on a per device basis. Clean
+up the code to only calculate it if required as well.
+- Use a queueing bool set under control_lock to prevent multiple calls to
+queue_request racing.
+- Use the work clone flag to determine if we should subtract it from the total
+queued variable and provide a subtract queued function to prevent looping over
+locked code.
+- Don't decrement staged extras count from longpoll work.
+- Count longpoll's contribution to the queue.
+- Increase queued count before pushing message.
+- Test we have enough work queued for pools with and without rolltime
+capability.
+- As work is sorted by age, we can discard the oldest work at regular intervals
+to keep only 1 of the newest work items per mining thread.
+- Roll work again after duplicating it to prevent duplicates on return to the
+clone function.
+- Abstract out work cloning and clone $mining_threads copies whenever a rollable
+work item is found and return a clone instead.
+- api.c display Pool Av in json
+- Take into account average getwork delay as a marker of pool communications
+when considering work stale.
+- Work out a rolling average getwork delay stored in pool_stats.
+- Getwork delay in stats should include retries for each getwork call.
+- Walk through the thread list instead of searching for them when disabling
+threads for dynamic mode.
+- Extend nrolltime to support the expiry= parameter. Do this by turning the
+rolltime bool into an integer set to the expiry time. If the pool supports
+rolltime but not expiry= then set the expiry time to the standard scantime.
+- When disabling fanspeed monitoring on adl failure, remove any twin GPU
+association. This could have been leading to hangs on machines with dual GPU
+cards when ADL failed.
+- modminer: Don't delay 2nd+ FPGAs during work restart
+- Disable OpenCL code when not available.
+- Fix openwrt crashing on regeneratehash() by making check_solve a noop.
+- FPGA - allow device detect override without an open failure
+- Fix sign warning.
+
+
 Version 2.4.3 - June 14, 2012
 Version 2.4.3 - June 14, 2012
 
 
 - Change device API "name" to reflect driver name abbreviation instead of device type name
 - Change device API "name" to reflect driver name abbreviation instead of device type name

+ 18 - 8
adl.c

@@ -13,6 +13,7 @@
 
 
 #include <stdio.h>
 #include <stdio.h>
 #include <string.h>
 #include <string.h>
+#include <math.h>
 
 
 #ifdef HAVE_CURSES
 #ifdef HAVE_CURSES
 #include <curses.h>
 #include <curses.h>
@@ -1024,6 +1025,7 @@ static int set_powertune(int gpu, int iPercentage)
 static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *fan_window)
 static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *fan_window)
 {
 {
 	struct cgpu_info *cgpu = &gpus[gpu];
 	struct cgpu_info *cgpu = &gpus[gpu];
+	int tdiff = round(temp - lasttemp);
 	struct gpu_adl *ga = &cgpu->adl;
 	struct gpu_adl *ga = &cgpu->adl;
 	int top = gpus[gpu].gpu_fan;
 	int top = gpus[gpu].gpu_fan;
 	int bot = gpus[gpu].min_fan;
 	int bot = gpus[gpu].min_fan;
@@ -1038,7 +1040,7 @@ static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *
 		cgpu->device_last_not_well = time(NULL);
 		cgpu->device_last_not_well = time(NULL);
 		cgpu->device_not_well_reason = REASON_DEV_OVER_HEAT;
 		cgpu->device_not_well_reason = REASON_DEV_OVER_HEAT;
 		cgpu->dev_over_heat_count++;
 		cgpu->dev_over_heat_count++;
-	} else if (temp > ga->targettemp && fanpercent < top && temp >= lasttemp) {
+	} else if (temp > ga->targettemp && fanpercent < top && tdiff >= 0) {
 		applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
 		applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
 		if (temp > ga->targettemp + opt_hysteresis)
 		if (temp > ga->targettemp + opt_hysteresis)
 			newpercent = ga->targetfan + 10;
 			newpercent = ga->targetfan + 10;
@@ -1046,18 +1048,26 @@ static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *
 			newpercent = ga->targetfan + 5;
 			newpercent = ga->targetfan + 5;
 		if (newpercent > top)
 		if (newpercent > top)
 			newpercent = top;
 			newpercent = top;
-	} else if (fanpercent > bot && temp < ga->targettemp - opt_hysteresis && temp <= lasttemp) {
-		applog(LOG_DEBUG, "Temperature %d degrees below target, decreasing fanspeed", opt_hysteresis);
-		newpercent = ga->targetfan - 1;
+	} else if (fanpercent > bot && temp < ga->targettemp - opt_hysteresis) {
+		/* Detect large swings of 5 degrees or more and change fan by
+		 * a proportion more */
+		if (tdiff <= 0) {
+			applog(LOG_DEBUG, "Temperature %d degrees below target, decreasing fanspeed", opt_hysteresis);
+			newpercent = ga->targetfan - 1 + tdiff / 5;
+		} else if (tdiff >= 5) {
+			applog(LOG_DEBUG, "Temperature climbed %d while below target, increasing fanspeed", tdiff);
+			newpercent = ga->targetfan + tdiff / 5;
+		}
 	} else {
 	} else {
+
 		/* We're in the optimal range, make minor adjustments if the
 		/* We're in the optimal range, make minor adjustments if the
 		 * temp is still drifting */
 		 * temp is still drifting */
-		if (fanpercent > bot && temp < lasttemp && lasttemp < ga->targettemp) {
+		if (fanpercent > bot && tdiff < 0 && lasttemp < ga->targettemp) {
 			applog(LOG_DEBUG, "Temperature dropping while in target range, decreasing fanspeed");
 			applog(LOG_DEBUG, "Temperature dropping while in target range, decreasing fanspeed");
-			newpercent = ga->targetfan - 1;
-		} else if (fanpercent < top && temp > lasttemp && temp > ga->targettemp - opt_hysteresis) {
+			newpercent = ga->targetfan + tdiff;
+		} else if (fanpercent < top && tdiff > 0 && temp > ga->targettemp - opt_hysteresis) {
 			applog(LOG_DEBUG, "Temperature rising while in target range, increasing fanspeed");
 			applog(LOG_DEBUG, "Temperature rising while in target range, increasing fanspeed");
-			newpercent = ga->targetfan + 1;
+			newpercent = ga->targetfan + tdiff;
 		}
 		}
 	}
 	}
 
 

+ 28 - 32
api.c

@@ -159,7 +159,7 @@ static char *msg_buffer = NULL;
 static SOCKETTYPE sock = INVSOCK;
 static SOCKETTYPE sock = INVSOCK;
 
 
 static const char *UNAVAILABLE = " - API will not be available";
 static const char *UNAVAILABLE = " - API will not be available";
-static const char *GROUPDIS = " - groups will be disabled";
+static const char *INVAPIGROUPS = "Invalid --api-groups parameter";
 
 
 static const char *BLANK = "";
 static const char *BLANK = "";
 static const char *COMMA = ",";
 static const char *COMMA = ",";
@@ -550,8 +550,6 @@ struct APIGROUPS {
 	char *commands;
 	char *commands;
 } apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs)
 } apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs)
 
 
-static bool groups_enabled = false;
-
 static struct IP4ACCESS *ipaccess = NULL;
 static struct IP4ACCESS *ipaccess = NULL;
 static int ips = 0;
 static int ips = 0;
 
 
@@ -1997,7 +1995,7 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson, __maybe_unuse
 	strcat(io_buffer, buf);
 	strcat(io_buffer, buf);
 }
 }
 
 
-static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
+static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group)
 {
 {
 	int i;
 	int i;
 
 
@@ -2320,6 +2318,7 @@ static void tidyup(__maybe_unused void *arg)
  */
  */
 static void setup_groups()
 static void setup_groups()
 {
 {
+	char *api_groups = opt_api_groups ? opt_api_groups : (char *)BLANK;
 	char *buf, *ptr, *next, *colon;
 	char *buf, *ptr, *next, *colon;
 	char group;
 	char group;
 	char commands[TMPBUFSIZ];
 	char commands[TMPBUFSIZ];
@@ -2328,11 +2327,11 @@ static void setup_groups()
 	bool addstar, did;
 	bool addstar, did;
 	int i;
 	int i;
 
 
-	buf = malloc(strlen(opt_api_groups) + 1);
+	buf = malloc(strlen(api_groups) + 1);
 	if (unlikely(!buf))
 	if (unlikely(!buf))
 		quit(1, "Failed to malloc ipgroups buf");
 		quit(1, "Failed to malloc ipgroups buf");
 
 
-	strcpy(buf, opt_api_groups);
+	strcpy(buf, api_groups);
 
 
 	next = buf;
 	next = buf;
 	// for each group defined
 	// for each group defined
@@ -2347,29 +2346,29 @@ static void setup_groups()
 			colon = strchr(ptr, ':');
 			colon = strchr(ptr, ':');
 			if (colon)
 			if (colon)
 				*colon = '\0';
 				*colon = '\0';
-			applog(LOG_WARNING, "API invalid group name '%s'%s", ptr, GROUPDIS);
-			goto shin;
+			applog(LOG_WARNING, "API invalid group name '%s'", ptr);
+			quit(1, INVAPIGROUPS);
 		}
 		}
 
 
 		group = GROUP(*ptr);
 		group = GROUP(*ptr);
 		if (!VALIDGROUP(group)) {
 		if (!VALIDGROUP(group)) {
-			applog(LOG_WARNING, "API invalid group name '%c'%s", *ptr, GROUPDIS);
-			goto shin;
+			applog(LOG_WARNING, "API invalid group name '%c'", *ptr);
+			quit(1, INVAPIGROUPS);
 		}
 		}
 
 
 		if (group == PRIVGROUP) {
 		if (group == PRIVGROUP) {
-			applog(LOG_WARNING, "API group name can't be '%c'%s", PRIVGROUP, GROUPDIS);
-			goto shin;
+			applog(LOG_WARNING, "API group name can't be '%c'", PRIVGROUP);
+			quit(1, INVAPIGROUPS);
 		}
 		}
 
 
 		if (group == NOPRIVGROUP) {
 		if (group == NOPRIVGROUP) {
-			applog(LOG_WARNING, "API group name can't be '%c'%s", NOPRIVGROUP, GROUPDIS);
-			goto shin;
+			applog(LOG_WARNING, "API group name can't be '%c'", NOPRIVGROUP);
+			quit(1, INVAPIGROUPS);
 		}
 		}
 
 
 		if (apigroups[GROUPOFFSET(group)].commands != NULL) {
 		if (apigroups[GROUPOFFSET(group)].commands != NULL) {
-			applog(LOG_WARNING, "API duplicate group name '%c'%s", *ptr, GROUPDIS);
-			goto shin;
+			applog(LOG_WARNING, "API duplicate group name '%c'", *ptr);
+			quit(1, INVAPIGROUPS);
 		}
 		}
 
 
 		ptr += 2;
 		ptr += 2;
@@ -2404,8 +2403,8 @@ static void setup_groups()
 						*cmd = '\0';
 						*cmd = '\0';
 					}
 					}
 				} else {
 				} else {
-					applog(LOG_WARNING, "API unknown command '%s' in group '%c'%s", ptr, group, GROUPDIS);
-					goto shin;
+					applog(LOG_WARNING, "API unknown command '%s' in group '%c'", ptr, group);
+					quit(1, INVAPIGROUPS);
 				}
 				}
 			}
 			}
 
 
@@ -2456,8 +2455,6 @@ static void setup_groups()
 
 
 	// W (PRIVGROUP) is handled as a special case since it simply means all commands
 	// W (PRIVGROUP) is handled as a special case since it simply means all commands
 
 
-	groups_enabled = true;
-shin:
 	free(buf);
 	free(buf);
 	return;
 	return;
 }
 }
@@ -2624,16 +2621,12 @@ void api(int api_thr_id)
 	pthread_cleanup_push(tidyup, NULL);
 	pthread_cleanup_push(tidyup, NULL);
 	my_thr_id = api_thr_id;
 	my_thr_id = api_thr_id;
 
 
-	/* This should be done first to ensure curl has already called WSAStartup() in windows */
-	sleep(opt_log_interval);
-
 	if (!opt_api_listen) {
 	if (!opt_api_listen) {
 		applog(LOG_DEBUG, "API not running%s", UNAVAILABLE);
 		applog(LOG_DEBUG, "API not running%s", UNAVAILABLE);
 		return;
 		return;
 	}
 	}
 
 
-	if (opt_api_groups)
-		setup_groups();
+	setup_groups();
 
 
 	if (opt_api_allow) {
 	if (opt_api_allow) {
 		setup_ipaccess();
 		setup_ipaccess();
@@ -2644,6 +2637,10 @@ void api(int api_thr_id)
 		}
 		}
 	}
 	}
 
 
+	/* This should be done before curl in needed
+	 * to ensure curl has already called WSAStartup() in windows */
+	sleep(opt_log_interval);
+
 	sock = socket(AF_INET, SOCK_STREAM, 0);
 	sock = socket(AF_INET, SOCK_STREAM, 0);
 	if (sock == INVSOCK) {
 	if (sock == INVSOCK) {
 		applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
 		applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
@@ -2715,14 +2712,13 @@ void api(int api_thr_id)
 		addrok = false;
 		addrok = false;
 		group = NOPRIVGROUP;
 		group = NOPRIVGROUP;
 		if (opt_api_allow) {
 		if (opt_api_allow) {
-			if (groups_enabled)
-				for (i = 0; i < ips; i++) {
-					if ((cli.sin_addr.s_addr & ipaccess[i].mask) == ipaccess[i].ip) {
-						addrok = true;
-						group = ipaccess[i].group;
-						break;
-					}
+			for (i = 0; i < ips; i++) {
+				if ((cli.sin_addr.s_addr & ipaccess[i].mask) == ipaccess[i].ip) {
+					addrok = true;
+					group = ipaccess[i].group;
+					break;
 				}
 				}
+			}
 		} else {
 		} else {
 			if (opt_api_network)
 			if (opt_api_network)
 				addrok = true;
 				addrok = true;

+ 1 - 1
configure.ac

@@ -21,7 +21,7 @@ AC_CONFIG_HEADERS([config.h])
 
 
 AM_INIT_AUTOMAKE([foreign])
 AM_INIT_AUTOMAKE([foreign])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-AC_GNU_SOURCE
+AC_USE_SYSTEM_EXTENSIONS
 
 
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##

+ 1 - 1
driver-icarus.c

@@ -593,7 +593,7 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 		}
 		}
 
 
 		tv_start = state->tv_workstart;
 		tv_start = state->tv_workstart;
-		timeval_subtract(&elapsed, &state->tv_workfinish, &tv_start);
+		timersub(&state->tv_workfinish, &tv_start, &elapsed);
 	}
 	}
 
 
 #ifndef WIN32
 #ifndef WIN32

+ 1 - 1
driver-modminer.c

@@ -504,7 +504,7 @@ modminer_process_results(struct thr_info*thr)
 
 
 	struct timeval tv_workend, elapsed;
 	struct timeval tv_workend, elapsed;
 	gettimeofday(&tv_workend, NULL);
 	gettimeofday(&tv_workend, NULL);
-	timeval_subtract(&elapsed, &tv_workend, &state->tv_workstart);
+	timersub(&tv_workend, &state->tv_workstart, &elapsed);
 
 
 	uint64_t hashes = (uint64_t)state->clock * (((uint64_t)elapsed.tv_sec * 1000000) + elapsed.tv_usec);
 	uint64_t hashes = (uint64_t)state->clock * (((uint64_t)elapsed.tv_sec * 1000000) + elapsed.tv_usec);
 	if (hashes > 0xffffffff)
 	if (hashes > 0xffffffff)

+ 11 - 8
miner.c

@@ -101,6 +101,7 @@ int opt_scantime = 60;
 int opt_expiry = 120;
 int opt_expiry = 120;
 int opt_bench_algo = -1;
 int opt_bench_algo = -1;
 static const bool opt_time = true;
 static const bool opt_time = true;
+unsigned long long global_hashrate;
 
 
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
 int opt_dynamic_interval = 7;
 int opt_dynamic_interval = 7;
@@ -3403,8 +3404,9 @@ static void hashmeter(int thr_id, struct timeval *diff,
 		if (want_per_device_stats) {
 		if (want_per_device_stats) {
 			struct timeval now;
 			struct timeval now;
 			struct timeval elapsed;
 			struct timeval elapsed;
+
 			gettimeofday(&now, NULL);
 			gettimeofday(&now, NULL);
-			timeval_subtract(&elapsed, &now, &thr->cgpu->last_message_tv);
+			timersub(&now, &thr->cgpu->last_message_tv, &elapsed);
 			if (opt_log_interval <= elapsed.tv_sec) {
 			if (opt_log_interval <= elapsed.tv_sec) {
 				struct cgpu_info *cgpu = thr->cgpu;
 				struct cgpu_info *cgpu = thr->cgpu;
 				char logline[255];
 				char logline[255];
@@ -3424,7 +3426,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
 	/* Totals are updated by all threads so can race without locking */
 	/* Totals are updated by all threads so can race without locking */
 	mutex_lock(&hash_lock);
 	mutex_lock(&hash_lock);
 	gettimeofday(&temp_tv_end, NULL);
 	gettimeofday(&temp_tv_end, NULL);
-	timeval_subtract(&total_diff, &temp_tv_end, &total_tv_end);
+	timersub(&temp_tv_end, &total_tv_end, &total_diff);
 
 
 	total_mhashes_done += local_mhashes;
 	total_mhashes_done += local_mhashes;
 	local_mhashes_done += local_mhashes;
 	local_mhashes_done += local_mhashes;
@@ -3436,8 +3438,9 @@ static void hashmeter(int thr_id, struct timeval *diff,
 
 
 	local_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0);
 	local_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0);
 	decay_time(&rolling, local_mhashes_done / local_secs);
 	decay_time(&rolling, local_mhashes_done / local_secs);
+	global_hashrate = roundl(rolling) * 1000000;
 
 
-	timeval_subtract(&total_diff, &total_tv_end, &total_tv_start);
+	timersub(&total_tv_end, &total_tv_start, &total_diff);
 	total_secs = (double)total_diff.tv_sec +
 	total_secs = (double)total_diff.tv_sec +
 		((double)total_diff.tv_usec / 1000000.0);
 		((double)total_diff.tv_usec / 1000000.0);
 
 
@@ -3991,7 +3994,7 @@ void *miner_thread(void *userdata)
 	/* Try to cycle approximately 5 times before each log update */
 	/* Try to cycle approximately 5 times before each log update */
 	const long cycle = opt_log_interval / 5 ? : 1;
 	const long cycle = opt_log_interval / 5 ? : 1;
 	struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate;
 	struct timeval tv_start, tv_end, tv_workstart, tv_lastupdate;
-	struct timeval diff, sdiff, wdiff;
+	struct timeval diff, sdiff, wdiff = {0, 0};
 	uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff;
 	uint32_t max_nonce = api->can_limit_work ? api->can_limit_work(mythr) : 0xffffffff;
 	unsigned long long hashes_done = 0;
 	unsigned long long hashes_done = 0;
 	unsigned long long hashes;
 	unsigned long long hashes;
@@ -4108,7 +4111,7 @@ void *miner_thread(void *userdata)
 				cgpu->max_hashes = hashes;
 				cgpu->max_hashes = hashes;
 
 
 			gettimeofday(&tv_end, NULL);
 			gettimeofday(&tv_end, NULL);
-			timeval_subtract(&diff, &tv_end, &tv_start);
+			timersub(&tv_end, &tv_start, &diff);
 			sdiff.tv_sec += diff.tv_sec;
 			sdiff.tv_sec += diff.tv_sec;
 			sdiff.tv_usec += diff.tv_usec;
 			sdiff.tv_usec += diff.tv_usec;
 			if (sdiff.tv_usec > 1000000) {
 			if (sdiff.tv_usec > 1000000) {
@@ -4116,7 +4119,7 @@ void *miner_thread(void *userdata)
 				sdiff.tv_usec -= 1000000;
 				sdiff.tv_usec -= 1000000;
 			}
 			}
 
 
-			timeval_subtract(&wdiff, &tv_end, &tv_workstart);
+			timersub(&tv_end, &tv_workstart, &wdiff);
 			if (!requested) {
 			if (!requested) {
 				if (wdiff.tv_sec > request_interval || work->blk.nonce > request_nonce) {
 				if (wdiff.tv_sec > request_interval || work->blk.nonce > request_nonce) {
 					thread_reportout(mythr);
 					thread_reportout(mythr);
@@ -4152,7 +4155,7 @@ void *miner_thread(void *userdata)
 				max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400));
 				max_nonce = max_nonce * 0x400 / (((cycle * 1000000) + sdiff.tv_usec) / (cycle * 1000000 / 0x400));
 			}
 			}
 
 
-			timeval_subtract(&diff, &tv_end, &tv_lastupdate);
+			timersub(&tv_end, &tv_lastupdate, &diff);
 			if (diff.tv_sec >= opt_log_interval) {
 			if (diff.tv_sec >= opt_log_interval) {
 				hashmeter(thr_id, &diff, hashes_done);
 				hashmeter(thr_id, &diff, hashes_done);
 				hashes_done = 0;
 				hashes_done = 0;
@@ -4658,7 +4661,7 @@ static void print_summary(void)
 	int hours, mins, secs, i;
 	int hours, mins, secs, i;
 	double utility, efficiency = 0.0;
 	double utility, efficiency = 0.0;
 
 
-	timeval_subtract(&diff, &total_tv_end, &total_tv_start);
+	timersub(&total_tv_end, &total_tv_start, &diff);
 	hours = diff.tv_sec / 3600;
 	hours = diff.tv_sec / 3600;
 	mins = (diff.tv_sec % 3600) / 60;
 	mins = (diff.tv_sec % 3600) / 60;
 	secs = diff.tv_sec % 60;
 	secs = diff.tv_sec % 60;

+ 1 - 3
miner.h

@@ -552,9 +552,6 @@ typedef bool (*sha256_func)(struct thr_info*, const unsigned char *pmidstate,
 	uint32_t *last_nonce,
 	uint32_t *last_nonce,
 	uint32_t nonce);
 	uint32_t nonce);
 
 
-extern int
-timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y);
-
 extern bool fulltest(const unsigned char *hash, const unsigned char *target);
 extern bool fulltest(const unsigned char *hash, const unsigned char *target);
 
 
 extern int opt_scantime;
 extern int opt_scantime;
@@ -616,6 +613,7 @@ extern unsigned int local_work;
 extern unsigned int total_go, total_ro;
 extern unsigned int total_go, total_ro;
 extern const int opt_cutofftemp;
 extern const int opt_cutofftemp;
 extern int opt_log_interval;
 extern int opt_log_interval;
+extern unsigned long long global_hashrate;
 
 
 #ifdef HAVE_OPENCL
 #ifdef HAVE_OPENCL
 typedef struct {
 typedef struct {

+ 24 - 50
util.c

@@ -147,9 +147,9 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
 
 
 	memcpy(val, rem, remlen);	/* store value, trim trailing ws */
 	memcpy(val, rem, remlen);	/* store value, trim trailing ws */
 	val[remlen] = 0;
 	val[remlen] = 0;
-	while ((*val) && (isspace(val[strlen(val) - 1]))) {
+	while ((*val) && (isspace(val[strlen(val) - 1])))
 		val[strlen(val) - 1] = 0;
 		val[strlen(val) - 1] = 0;
-	}
+
 	if (!*val)			/* skip blank value */
 	if (!*val)			/* skip blank value */
 		goto out;
 		goto out;
 
 
@@ -157,9 +157,9 @@ static size_t resp_hdr_cb(void *ptr, size_t size, size_t nmemb, void *user_data)
 		applog(LOG_DEBUG, "HTTP hdr(%s): %s", key, val);
 		applog(LOG_DEBUG, "HTTP hdr(%s): %s", key, val);
 
 
 	if (!strcasecmp("X-Roll-Ntime", key)) {
 	if (!strcasecmp("X-Roll-Ntime", key)) {
-		if (!strncasecmp("N", val, 1)) {
+		if (!strncasecmp("N", val, 1))
 			applog(LOG_DEBUG, "X-Roll-Ntime: N found");
 			applog(LOG_DEBUG, "X-Roll-Ntime: N found");
-		} else {
+		else {
 			/* Check to see if expire= is supported and if not, set
 			/* Check to see if expire= is supported and if not, set
 			 * the rolltime to the default scantime */
 			 * the rolltime to the default scantime */
 			if (strlen(val) > 7 && !strncasecmp("expire=", val, 7))
 			if (strlen(val) > 7 && !strncasecmp("expire=", val, 7))
@@ -256,17 +256,17 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 		      bool probe, bool longpoll, int *rolltime,
 		      bool probe, bool longpoll, int *rolltime,
 		      struct pool *pool, bool share)
 		      struct pool *pool, bool share)
 {
 {
-	json_t *val, *err_val, *res_val;
-	int rc;
-	struct data_buffer all_data = {NULL, 0};
-	struct upload_buffer upload_data;
-	json_error_t err;
-	struct curl_slist *headers = NULL;
-	char len_hdr[64], user_agent_hdr[128];
-	char curl_err_str[CURL_ERROR_SIZE];
+	char len_hdr[64], user_agent_hdr[128], *ghashrate;
 	long timeout = longpoll ? (60 * 60) : 60;
 	long timeout = longpoll ? (60 * 60) : 60;
+	struct data_buffer all_data = {NULL, 0};
 	struct header_info hi = {NULL, 0, NULL};
 	struct header_info hi = {NULL, 0, NULL};
+	char curl_err_str[CURL_ERROR_SIZE];
+	struct curl_slist *headers = NULL;
+	struct upload_buffer upload_data;
+	json_t *val, *err_val, *res_val;
 	bool probing = false;
 	bool probing = false;
+	json_error_t err;
+	int rc;
 
 
 	memset(&err, 0, sizeof(err));
 	memset(&err, 0, sizeof(err));
 
 
@@ -325,6 +325,12 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 		"Content-type: application/json");
 		"Content-type: application/json");
 	headers = curl_slist_append(headers,
 	headers = curl_slist_append(headers,
 		"X-Mining-Extensions: longpoll midstate rollntime submitold");
 		"X-Mining-Extensions: longpoll midstate rollntime submitold");
+
+	if (likely(global_hashrate && asprintf(&ghashrate, "X-Mining-Hashrate: %llu", global_hashrate) != -1)) {
+		headers = curl_slist_append(headers, ghashrate);
+		free(ghashrate);
+	}
+
 	headers = curl_slist_append(headers, len_hdr);
 	headers = curl_slist_append(headers, len_hdr);
 	headers = curl_slist_append(headers, user_agent_hdr);
 	headers = curl_slist_append(headers, user_agent_hdr);
 	headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
 	headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
@@ -372,9 +378,8 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 			if (pool->hdr_path != NULL)
 			if (pool->hdr_path != NULL)
 				free(pool->hdr_path);
 				free(pool->hdr_path);
 			pool->hdr_path = hi.lp_path;
 			pool->hdr_path = hi.lp_path;
-		} else {
+		} else
 			pool->hdr_path = NULL;
 			pool->hdr_path = NULL;
-		}
 	} else if (hi.lp_path) {
 	} else if (hi.lp_path) {
 		free(hi.lp_path);
 		free(hi.lp_path);
 		hi.lp_path = NULL;
 		hi.lp_path = NULL;
@@ -394,6 +399,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 
 
 	if (opt_protocol) {
 	if (opt_protocol) {
 		char *s = json_dumps(val, JSON_INDENT(3));
 		char *s = json_dumps(val, JSON_INDENT(3));
+
 		applog(LOG_DEBUG, "JSON protocol response:\n%s", s);
 		applog(LOG_DEBUG, "JSON protocol response:\n%s", s);
 		free(s);
 		free(s);
 	}
 	}
@@ -443,8 +449,8 @@ err_out:
 
 
 char *bin2hex(const unsigned char *p, size_t len)
 char *bin2hex(const unsigned char *p, size_t len)
 {
 {
-	unsigned int i;
 	char *s = malloc((len * 2) + 1);
 	char *s = malloc((len * 2) + 1);
+	unsigned int i;
 
 
 	if (!s)
 	if (!s)
 		return NULL;
 		return NULL;
@@ -485,43 +491,14 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
 	return (len == 0 && *hexstr == 0) ? true : false;
 	return (len == 0 && *hexstr == 0) ? true : false;
 }
 }
 
 
-/* Subtract the `struct timeval' values X and Y,
-   storing the result in RESULT.
-   Return 1 if the difference is negative, otherwise 0.  */
-
-int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y)
-{
-	/* Perform the carry for the later subtraction by updating Y. */
-	if (x->tv_usec < y->tv_usec) {
-		int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
-
-		y->tv_usec -= 1000000 * nsec;
-		y->tv_sec += nsec;
-	}
-	if (x->tv_usec - y->tv_usec > 1000000) {
-		int nsec = (x->tv_usec - y->tv_usec) / 1000000;
-
-		y->tv_usec += 1000000 * nsec;
-		y->tv_sec -= nsec;
-	}
-
-	/* Compute the time remaining to wait.
-	 * `tv_usec' is certainly positive. */
-	result->tv_sec = x->tv_sec - y->tv_sec;
-	result->tv_usec = x->tv_usec - y->tv_usec;
-
-	/* Return 1 if result is negative. */
-	return x->tv_sec < y->tv_sec;
-}
-
 bool fulltest(const unsigned char *hash, const unsigned char *target)
 bool fulltest(const unsigned char *hash, const unsigned char *target)
 {
 {
 	unsigned char hash_swap[32], target_swap[32];
 	unsigned char hash_swap[32], target_swap[32];
 	uint32_t *hash32 = (uint32_t *) hash_swap;
 	uint32_t *hash32 = (uint32_t *) hash_swap;
 	uint32_t *target32 = (uint32_t *) target_swap;
 	uint32_t *target32 = (uint32_t *) target_swap;
-	int i;
-	bool rc = true;
 	char *hash_str, *target_str;
 	char *hash_str, *target_str;
+	bool rc = true;
+	int i;
 
 
 	swap256(hash_swap, hash);
 	swap256(hash_swap, hash);
 	swap256(target_swap, target);
 	swap256(target_swap, target);
@@ -674,10 +651,7 @@ out:
 
 
 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)
 {
 {
-	int ret;
-
-	ret = pthread_create(&thr->pth, attr, start, arg);
-	return ret;
+	return pthread_create(&thr->pth, attr, start, arg);
 }
 }
 
 
 void thr_info_freeze(struct thr_info *thr)
 void thr_info_freeze(struct thr_info *thr)