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
    This defaults to the BFGMiner version but is the value of --api-description
    if it was specified at runtime.
    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:
 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
                               stating success or failure saving the BFGMiner config
                               to filename
                               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
                               reply before BFGMiner quits
 
 
  notify        NOTIFY         The last status and history count of each devices problem
  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
                               by the 'devs' command
                               e.g. DEVDETAILS=0,Name=GPU,ID=0,Driver=opencl,...|
                               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
 When you enable, disable or restart a GPU or PGA, you will also get Thread messages
 in the BFGMiner status window
 in the BFGMiner status window
 
 

+ 83 - 14
api.c

@@ -158,7 +158,7 @@ static const char SEPARATOR = '|';
 #define SEPSTR "|"
 #define SEPSTR "|"
 static const char GPUSEP = ',';
 static const char GPUSEP = ',';
 
 
-static const char *APIVERSION = "1.8";
+static const char *APIVERSION = "1.9";
 static const char *DEAD = "Dead";
 static const char *DEAD = "Dead";
 static const char *SICK = "Sick";
 static const char *SICK = "Sick";
 static const char *NOSTART = "NoStart";
 static const char *NOSTART = "NoStart";
@@ -230,6 +230,7 @@ static const char *OSINFO =
 #define _NOTIFY		"NOTIFY"
 #define _NOTIFY		"NOTIFY"
 #define _DEVDETAILS	"DEVDETAILS"
 #define _DEVDETAILS	"DEVDETAILS"
 #define _BYE		"BYE"
 #define _BYE		"BYE"
+#define _RESTART	"RESTART"
 
 
 static const char ISJSON = '{';
 static const char ISJSON = '{';
 #define JSON0		"{"
 #define JSON0		"{"
@@ -261,6 +262,7 @@ static const char ISJSON = '{';
 #define JSON_NOTIFY	JSON1 _NOTIFY JSON2
 #define JSON_NOTIFY	JSON1 _NOTIFY JSON2
 #define JSON_DEVDETAILS	JSON1 _DEVDETAILS JSON2
 #define JSON_DEVDETAILS	JSON1 _DEVDETAILS JSON2
 #define JSON_BYE	JSON1 _BYE JSON1
 #define JSON_BYE	JSON1 _BYE JSON1
+#define JSON_RESTART	JSON1 _RESTART JSON1
 #define JSON_CLOSE	JSON3
 #define JSON_CLOSE	JSON3
 #define JSON_END	JSON4
 #define JSON_END	JSON4
 
 
@@ -477,9 +479,15 @@ struct CODES {
 };
 };
 
 
 static int my_thr_id = 0;
 static int my_thr_id = 0;
-static int bye = 0;
+static bool bye;
 static bool ping = true;
 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
 static time_t when = 0;	// when the request occurred
 
 
 struct IP4ACCESS {
 struct IP4ACCESS {
@@ -613,7 +621,7 @@ static int pgadevice(int pgaid)
 }
 }
 #endif
 #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
 //  thus for JSON, message() inserts JSON_START at the front
 //  and send_result() adds JSON_END at the end
 //  and send_result() adds JSON_END at the end
 static char *message(int messageid, int paramid, char *param2, bool isjson)
 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
 #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)
 	if (isjson)
 		strcpy(io_buffer, JSON_START JSON_BYE);
 		strcpy(io_buffer, JSON_START JSON_BYE);
 	else
 	else
 		strcpy(io_buffer, _BYE);
 		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)
 void privileged(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
@@ -1992,6 +2004,7 @@ struct CMDS {
 	{ "privileged",		privileged,	true },
 	{ "privileged",		privileged,	true },
 	{ "notify",		notify,		false },
 	{ "notify",		notify,		false },
 	{ "devdetails",		devdetails,	false },
 	{ "devdetails",		devdetails,	false },
+	{ "restart",		dorestart,	true },
 	{ NULL,			NULL,		false }
 	{ NULL,			NULL,		false }
 };
 };
 
 
@@ -2016,12 +2029,13 @@ static void send_result(SOCKETTYPE c, bool isjson)
 		else
 		else
 			applog(LOG_DEBUG, "API: sent %d", n);
 			applog(LOG_DEBUG, "API: sent %d", n);
 	}
 	}
-
 }
 }
 
 
 static void tidyup(__maybe_unused void *arg)
 static void tidyup(__maybe_unused void *arg)
 {
 {
-	bye = 1;
+	mutex_lock(&quit_restart_lock);
+
+	bye = true;
 
 
 	if (sock != INVSOCK) {
 	if (sock != INVSOCK) {
 		shutdown(sock, SHUT_RDWR);
 		shutdown(sock, SHUT_RDWR);
@@ -2043,6 +2057,8 @@ static void tidyup(__maybe_unused void *arg)
 		free(io_buffer);
 		free(io_buffer);
 		io_buffer = NULL;
 		io_buffer = NULL;
 	}
 	}
+
+	mutex_unlock(&quit_restart_lock);
 }
 }
 
 
 /*
 /*
@@ -2147,8 +2163,37 @@ popipo:
 	free(buf);
 	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)
 void api(int api_thr_id)
 {
 {
+	struct thr_info bye_thr;
 	char buf[BUFSIZ];
 	char buf[BUFSIZ];
 	char param_buf[BUFSIZ];
 	char param_buf[BUFSIZ];
 	const char *localaddr = "127.0.0.1";
 	const char *localaddr = "127.0.0.1";
@@ -2172,6 +2217,8 @@ void api(int api_thr_id)
 	bool did;
 	bool did;
 	int i;
 	int i;
 
 
+	mutex_init(&quit_restart_lock);
+
 	pthread_cleanup_push(tidyup, NULL);
 	pthread_cleanup_push(tidyup, NULL);
 	my_thr_id = api_thr_id;
 	my_thr_id = api_thr_id;
 
 
@@ -2251,7 +2298,7 @@ void api(int api_thr_id)
 	io_buffer = malloc(MYBUFSIZ+1);
 	io_buffer = malloc(MYBUFSIZ+1);
 	msg_buffer = malloc(MYBUFSIZ+1);
 	msg_buffer = malloc(MYBUFSIZ+1);
 
 
-	while (bye == 0) {
+	while (!bye) {
 		clisiz = sizeof(cli);
 		clisiz = sizeof(cli);
 		if (SOCKETFAIL(c = accept(sock, (struct sockaddr *)(&cli), &clisiz))) {
 		if (SOCKETFAIL(c = accept(sock, (struct sockaddr *)(&cli), &clisiz))) {
 			applog(LOG_ERR, "API failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
 			applog(LOG_ERR, "API failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
@@ -2383,4 +2430,26 @@ void api(int api_thr_id)
 	}
 	}
 die:
 die:
 	pthread_cleanup_pop(true);
 	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;
 	char *ob_hex, *nonce_hex;
 	uint32_t nonce;
 	uint32_t nonce;
 	uint32_t hash_count;
 	uint32_t hash_count;
-	struct timeval tv_end, elapsed;
+	struct timeval tv_finish, elapsed;
+
+	elapsed.tv_sec = elapsed.tv_usec = 0;
 
 
 	icarus = thr->cgpu;
 	icarus = thr->cgpu;
 	struct icarus_state *state = thr->cgpu_data;
 	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;
 			state->changework = false;
 		else
 		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,
 			lret = icarus_gets(nonce_bin, sizeof(nonce_bin), fd, wr,
 			                   ICARUS_READ_FAULT_COUNT);
 			                   ICARUS_READ_FAULT_COUNT);
 			if (lret && *wr) {
 			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
 #ifndef WIN32
@@ -386,11 +388,13 @@ static uint64_t icarus_scanhash(struct thr_info *thr, struct work *work,
 		return 0;	/* This should never happen */
 		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
 	// 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
 			// 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
 			// 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);
 			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;
 		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);
 	submit_nonce(thr, &state->last_work, nonce);
 	memcpy(&state->last_work, work, sizeof(state->last_work));
 	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);
 	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;
         return hash_count;
 }
 }