Browse Source

Merge commit '8c0c7ea' into bfgminer

Conflicts:
	README
	driver-icarus.c
Luke Dashjr 14 years ago
parent
commit
346452db9c
3 changed files with 120 additions and 43 deletions
  1. 5 2
      README
  2. 83 14
      api.c
  3. 32 27
      driver-icarus.c

+ 5 - 2
README

@@ -648,7 +648,7 @@ The STATUS section is:
    This defaults to the BFGMiner version but is the value of --api-description
    if it was specified at runtime.
 
-For API version 1.8:
+For API version 1.9:
 
 The list of requests - a (*) means it requires privileged access - and replies are:
 
@@ -772,7 +772,7 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               stating success or failure saving the BFGMiner config
                               to filename
 
- quit (*)      none           There is no status section but just a single "BYE|"
+ quit (*)      none           There is no status section but just a single "BYE"
                               reply before BFGMiner quits
 
  notify        NOTIFY         The last status and history count of each devices problem
@@ -800,6 +800,9 @@ The list of requests - a (*) means it requires privileged access - and replies a
                               by the 'devs' command
                               e.g. DEVDETAILS=0,Name=GPU,ID=0,Driver=opencl,...|
 
+ restart (*)   none           There is no status section but just a single "RESTART"
+                              reply before cgminer restarts
+
 When you enable, disable or restart a GPU or PGA, you will also get Thread messages
 in the BFGMiner status window
 

+ 83 - 14
api.c

@@ -158,7 +158,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 
-static const char *APIVERSION = "1.8";
+static const char *APIVERSION = "1.9";
 static const char *DEAD = "Dead";
 static const char *SICK = "Sick";
 static const char *NOSTART = "NoStart";
@@ -230,6 +230,7 @@ static const char *OSINFO =
 #define _NOTIFY		"NOTIFY"
 #define _DEVDETAILS	"DEVDETAILS"
 #define _BYE		"BYE"
+#define _RESTART	"RESTART"
 
 static const char ISJSON = '{';
 #define JSON0		"{"
@@ -261,6 +262,7 @@ static const char ISJSON = '{';
 #define JSON_NOTIFY	JSON1 _NOTIFY JSON2
 #define JSON_DEVDETAILS	JSON1 _DEVDETAILS JSON2
 #define JSON_BYE	JSON1 _BYE JSON1
+#define JSON_RESTART	JSON1 _RESTART JSON1
 #define JSON_CLOSE	JSON3
 #define JSON_END	JSON4
 
@@ -477,9 +479,15 @@ struct CODES {
 };
 
 static int my_thr_id = 0;
-static int bye = 0;
+static bool bye;
 static bool ping = true;
 
+// Used to control quit restart access to shutdown variables
+static pthread_mutex_t quit_restart_lock;
+
+static bool do_a_quit;
+static bool do_a_restart;
+
 static time_t when = 0;	// when the request occurred
 
 struct IP4ACCESS {
@@ -613,7 +621,7 @@ static int pgadevice(int pgaid)
 }
 #endif
 
-// All replies (except BYE) start with a message
+// All replies (except BYE and RESTART) start with a message
 //  thus for JSON, message() inserts JSON_START at the front
 //  and send_result() adds JSON_END at the end
 static char *message(int messageid, int paramid, char *param2, bool isjson)
@@ -1785,22 +1793,26 @@ static void gpuvddc(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
 #endif
 }
 
-static void send_result(SOCKETTYPE c, bool isjson);
-
-void doquit(SOCKETTYPE c, __maybe_unused char *param, bool isjson)
+void doquit(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
 {
 	if (isjson)
 		strcpy(io_buffer, JSON_START JSON_BYE);
 	else
 		strcpy(io_buffer, _BYE);
 
-	send_result(c, isjson);
-	*io_buffer = '\0';
-	bye = 1;
+	bye = true;
+	do_a_quit = true;
+}
 
-        PTH(&thr_info[my_thr_id]) = 0L;
+void dorestart(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
+{
+	if (isjson)
+		strcpy(io_buffer, JSON_START JSON_RESTART);
+	else
+		strcpy(io_buffer, _RESTART);
 
-	kill_work();
+	bye = true;
+	do_a_restart = true;
 }
 
 void privileged(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
@@ -1992,6 +2004,7 @@ struct CMDS {
 	{ "privileged",		privileged,	true },
 	{ "notify",		notify,		false },
 	{ "devdetails",		devdetails,	false },
+	{ "restart",		dorestart,	true },
 	{ NULL,			NULL,		false }
 };
 
@@ -2016,12 +2029,13 @@ static void send_result(SOCKETTYPE c, bool isjson)
 		else
 			applog(LOG_DEBUG, "API: sent %d", n);
 	}
-
 }
 
 static void tidyup(__maybe_unused void *arg)
 {
-	bye = 1;
+	mutex_lock(&quit_restart_lock);
+
+	bye = true;
 
 	if (sock != INVSOCK) {
 		shutdown(sock, SHUT_RDWR);
@@ -2043,6 +2057,8 @@ static void tidyup(__maybe_unused void *arg)
 		free(io_buffer);
 		io_buffer = NULL;
 	}
+
+	mutex_unlock(&quit_restart_lock);
 }
 
 /*
@@ -2147,8 +2163,37 @@ popipo:
 	free(buf);
 }
 
+static void *quit_thread(__maybe_unused void *userdata)
+{
+	// allow thread creator to finish whatever it's doing
+	mutex_lock(&quit_restart_lock);
+	mutex_unlock(&quit_restart_lock);
+
+	if (opt_debug)
+		applog(LOG_DEBUG, "API: killing cgminer");
+
+	kill_work();
+
+	return NULL;
+}
+
+static void *restart_thread(__maybe_unused void *userdata)
+{
+	// allow thread creator to finish whatever it's doing
+	mutex_lock(&quit_restart_lock);
+	mutex_unlock(&quit_restart_lock);
+
+	if (opt_debug)
+		applog(LOG_DEBUG, "API: restarting cgminer");
+
+	app_restart();
+
+	return NULL;
+}
+
 void api(int api_thr_id)
 {
+	struct thr_info bye_thr;
 	char buf[BUFSIZ];
 	char param_buf[BUFSIZ];
 	const char *localaddr = "127.0.0.1";
@@ -2172,6 +2217,8 @@ void api(int api_thr_id)
 	bool did;
 	int i;
 
+	mutex_init(&quit_restart_lock);
+
 	pthread_cleanup_push(tidyup, NULL);
 	my_thr_id = api_thr_id;
 
@@ -2251,7 +2298,7 @@ void api(int api_thr_id)
 	io_buffer = malloc(MYBUFSIZ+1);
 	msg_buffer = malloc(MYBUFSIZ+1);
 
-	while (bye == 0) {
+	while (!bye) {
 		clisiz = sizeof(cli);
 		if (SOCKETFAIL(c = accept(sock, (struct sockaddr *)(&cli), &clisiz))) {
 			applog(LOG_ERR, "API failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
@@ -2383,4 +2430,26 @@ void api(int api_thr_id)
 	}
 die:
 	pthread_cleanup_pop(true);
+
+	if (opt_debug)
+		applog(LOG_DEBUG, "API: terminating due to: %s",
+				do_a_quit ? "QUIT" : (do_a_restart ? "RESTART" : (bye ? "BYE" : "UNKNOWN!")));
+
+	mutex_lock(&quit_restart_lock);
+
+	if (do_a_restart) {
+		if (thr_info_create(&bye_thr, NULL, restart_thread, &bye_thr)) {
+			mutex_unlock(&quit_restart_lock);
+			quit(1, "API failed to initiate a restart - aborting");
+		}
+		pthread_detach(bye_thr.pth);
+	} else if (do_a_quit) {
+		if (thr_info_create(&bye_thr, NULL, quit_thread, &bye_thr)) {
+			mutex_unlock(&quit_restart_lock);
+			quit(1, "API failed to initiate a clean quit - aborting");
+		}
+		pthread_detach(bye_thr.pth);
+	}
+
+	mutex_unlock(&quit_restart_lock);
 }

+ 32 - 27
driver-icarus.c

@@ -339,7 +339,9 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	char *ob_hex, *nonce_hex;
 	uint32_t nonce;
 	uint32_t hash_count;
-	struct timeval tv_end, elapsed;
+	struct timeval tv_finish, elapsed;
+
+	elapsed.tv_sec = elapsed.tv_usec = 0;
 
 	icarus = thr->cgpu;
 	struct icarus_state *state = thr->cgpu_data;
@@ -358,7 +360,7 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 			state->changework = false;
 		else
 		{
-			/* Icarus will return 8 bytes nonces or nothing */
+			/* Icarus will return 4 bytes nonces or nothing */
 			lret = icarus_gets(nonce_bin, sizeof(nonce_bin), fd, wr,
 			                   ICARUS_READ_FAULT_COUNT);
 			if (lret && *wr) {
@@ -370,8 +372,8 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 			}
 		}
 
-		gettimeofday(&tv_end, NULL);
-		timeval_subtract(&elapsed, &tv_end, &state->tv_workstart);
+		gettimeofday(&tv_finish, NULL);
+		timeval_subtract(&elapsed, &tv_finish, &state->tv_workstart);
 	}
 
 #ifndef WIN32
@@ -386,11 +388,13 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 		return 0;	/* This should never happen */
 	}
 
-	ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
-	if (ob_hex) {
-		applog(LOG_DEBUG, "Icarus %d sent: %s",
-		       icarus->device_id, ob_hex);
-		free(ob_hex);
+	if (opt_debug) {
+		ob_hex = bin2hex(ob_bin, sizeof(ob_bin));
+		if (ob_hex) {
+			applog(LOG_DEBUG, "Icarus %d sent: %s",
+			       icarus->device_id, ob_hex);
+			free(ob_hex);
+		}
 	}
 
 	// Reopen the serial port to workaround a USB-host-chipset-specific issue with the Icarus's buggy USB-UART
@@ -425,8 +429,10 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 			// 0x16a7a561 would be if it was exactly 380 MH/s
 			// 0x167a09b3 was the average over a 7500-sample period based on time to find actual shares
 			ESTIMATE_HASHES = (0x167a09b3 * elapsed.tv_sec) + (0x179 * elapsed.tv_usec);
-		applog(LOG_DEBUG, "Icarus %d no nonce = 0x%08x hashes (%ld.%06lds)",
-			icarus->device_id, ESTIMATE_HASHES, elapsed.tv_sec, elapsed.tv_usec);
+		if (opt_debug) {
+			applog(LOG_DEBUG, "Icarus %d no nonce = 0x%08x hashes (%ld.%06lds)",
+				icarus->device_id, ESTIMATE_HASHES, elapsed.tv_sec, elapsed.tv_usec);
+		}
 		return ESTIMATE_HASHES;
 	}
 
@@ -436,25 +442,24 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 	submit_nonce(thr, &state->last_work, nonce);
 	memcpy(&state->last_work, work, sizeof(state->last_work));
 
-	nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
-	if (nonce_hex) {
-		applog(LOG_DEBUG, "Icarus %d returned (elapsed %ld.%06ld seconds): %s",
-		       icarus->device_id, elapsed.tv_sec, elapsed.tv_usec, nonce_hex);
-		free(nonce_hex);
+	if (opt_debug) {
+		nonce_hex = bin2hex(nonce_bin, sizeof(nonce_bin));
+		if (nonce_hex) {
+			applog(LOG_DEBUG, "Icarus %d returned (elapsed %ld.%06ld seconds): %s",
+			       icarus->device_id, elapsed.tv_sec, elapsed.tv_usec, nonce_hex);
+			free(nonce_hex);
+		}
 	}
 
 	hash_count = (nonce & 0x7fffffff);
-        if (hash_count == 0)
-		hash_count = 2;
-        else {
-                if (hash_count++ == 0x7fffffff)
-                        hash_count = 0xffffffff;
-                else
-                        hash_count <<= 1;
-        }
-
-	applog(LOG_DEBUG, "Icarus %d nonce = 0x%08x = 0x%08x hashes (%ld.%06lds)",
-			icarus->device_id, nonce, hash_count, elapsed.tv_sec, elapsed.tv_usec);
+	if (hash_count++ == 0x7fffffff)
+		hash_count = 0xffffffff;
+	else
+		hash_count <<= 1;
+
+	if (opt_debug)
+		applog(LOG_DEBUG, "Icarus %d nonce = 0x%08x = 0x%08x hashes (%ld.%06lds)",
+				icarus->device_id, nonce, hash_count, elapsed.tv_sec, elapsed.tv_usec);
 
         return hash_count;
 }