Browse Source

Merge branch 'master' into hashfast

Con Kolivas 12 years ago
parent
commit
31e8ebaffa
8 changed files with 102 additions and 45 deletions
  1. 25 0
      NEWS
  2. 11 11
      cgminer.c
  3. 1 1
      configure.ac
  4. 9 3
      logging.c
  5. 16 6
      logging.h
  6. 32 18
      usbutils.c
  7. 7 4
      util.c
  8. 1 2
      util.h

+ 25 - 0
NEWS

@@ -1,3 +1,28 @@
+Version 3.6.4 - 18th October 2013
+
+- Fixing the memory leak for remaining semaphores means we can go back to using
+async transfers on other OSes with our own timeout management again.
+- Use the forcelog function on shutdown to cope with indeterminate console lock
+states due to killing of threads.
+- Add a forcelog variant of applog which invalidates any console lock to force
+output.
+- Send pthread_cancel to failed completion_timeout that has timed out.
+- Simplify queued hashtable by storing unqueued work separately in a single
+pointer.
+- bflsc use getinfo chip parallelization if it is present
+- bflsc - fix brackets so [Chips] isn't always null
+- Remove unused variables.
+- Use cgcompletion timeouts for the unreliable shutdown functions on kill_work.
+- Fix cgcompletion return code and free on successful completion.
+- Provide a cg_completion_timeout helper function for unreliable functions that
+takes arbitrary functions and parameters and reliably returns.
+- Perform sync transfers on shutdown to allow final transfers to complete.
+- Destroy cgsems used after transfers to not leave open files on osx.
+- klondike rewrite work control
+- allow __work_complete() access
+- miner.h allow devices to tv_stamp work
+
+
 Version 3.6.3 - 17th October 2013
 
 - API add 'MHS %ds' to 'summary'

+ 11 - 11
cgminer.c

@@ -427,7 +427,7 @@ static void applog_and_exit(const char *fmt, ...)
 	va_start(ap, fmt);
 	vsnprintf(exit_buf, sizeof(exit_buf), fmt, ap);
 	va_end(ap);
-	_applog(LOG_ERR, exit_buf);
+	_applog(LOG_ERR, exit_buf, true);
 	exit(1);
 }
 
@@ -3166,7 +3166,7 @@ static void kill_mining(void)
 	struct thr_info *thr;
 	int i;
 
-	applog(LOG_DEBUG, "Killing off mining threads");
+	forcelog(LOG_DEBUG, "Killing off mining threads");
 	/* Kill the mining threads*/
 	for (i = 0; i < mining_threads; i++) {
 		pthread_t *pth = NULL;
@@ -3193,29 +3193,29 @@ static void __kill_work(void)
 	if (!successful_connect)
 		return;
 
-	applog(LOG_INFO, "Received kill message");
+	forcelog(LOG_INFO, "Received kill message");
 
 #ifdef USE_USBUTILS
 	/* Best to get rid of it first so it doesn't
 	 * try to create any new devices */
 	if (!opt_scrypt) {
-		applog(LOG_DEBUG, "Killing off HotPlug thread");
+		forcelog(LOG_DEBUG, "Killing off HotPlug thread");
 		thr = &control_thr[hotplug_thr_id];
 		kill_timeout(thr);
 	}
 #endif
 
-	applog(LOG_DEBUG, "Killing off watchpool thread");
+	forcelog(LOG_DEBUG, "Killing off watchpool thread");
 	/* Kill the watchpool thread */
 	thr = &control_thr[watchpool_thr_id];
 	kill_timeout(thr);
 
-	applog(LOG_DEBUG, "Killing off watchdog thread");
+	forcelog(LOG_DEBUG, "Killing off watchdog thread");
 	/* Kill the watchdog thread */
 	thr = &control_thr[watchdog_thr_id];
 	kill_timeout(thr);
 
-	applog(LOG_DEBUG, "Shutting down mining threads");
+	forcelog(LOG_DEBUG, "Shutting down mining threads");
 	for (i = 0; i < mining_threads; i++) {
 		struct cgpu_info *cgpu;
 
@@ -3233,12 +3233,12 @@ static void __kill_work(void)
 
 	cg_completion_timeout(&kill_mining, NULL, 3000);
 
-	applog(LOG_DEBUG, "Killing off stage thread");
+	forcelog(LOG_DEBUG, "Killing off stage thread");
 	/* Stop the others */
 	thr = &control_thr[stage_thr_id];
 	kill_timeout(thr);
 
-	applog(LOG_DEBUG, "Killing off API thread");
+	forcelog(LOG_DEBUG, "Killing off API thread");
 	thr = &control_thr[api_thr_id];
 	kill_timeout(thr);
 
@@ -3246,10 +3246,10 @@ static void __kill_work(void)
 	/* Release USB resources in case it's a restart
 	 * and not a QUIT */
 	if (!opt_scrypt) {
-		applog(LOG_DEBUG, "Releasing all USB devices");
+		forcelog(LOG_DEBUG, "Releasing all USB devices");
 		cg_completion_timeout(&usb_cleanup, NULL, 1000);
 
-		applog(LOG_DEBUG, "Killing off usbres thread");
+		forcelog(LOG_DEBUG, "Killing off usbres thread");
 		thr = &control_thr[usbres_thr_id];
 		kill_timeout(thr);
 	}

+ 1 - 1
configure.ac

@@ -2,7 +2,7 @@
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_maj], [3])
 m4_define([v_min], [6])
-m4_define([v_mic], [3])
+m4_define([v_mic], [4])
 ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 m4_define([v_ver], [v_maj.v_min.v_mic])
 m4_define([lt_rev], m4_eval(v_maj + v_min))

+ 9 - 3
logging.c

@@ -21,11 +21,17 @@ bool opt_log_output = false;
 /* per default priorities higher than LOG_NOTICE are logged */
 int opt_log_level = LOG_NOTICE;
 
-static void my_log_curses(int prio, const char *datetime, const char *str)
+static void my_log_curses(int prio, const char *datetime, const char *str, bool force)
 {
 	if (opt_quiet && prio != LOG_ERR)
 		return;
 
+	/* Mutex could be locked by dead thread on shutdown so forcelog will
+	 * invalidate any console lock status. */
+	if (force) {
+		mutex_trylock(&console_lock);
+		mutex_unlock(&console_lock);
+	}
 #ifdef HAVE_CURSES
 	extern bool use_curses;
 	if (use_curses && log_curses_only(prio, datetime, str))
@@ -44,7 +50,7 @@ static void my_log_curses(int prio, const char *datetime, const char *str)
 /*
  * log function
  */
-void _applog(int prio, const char *str)
+void _applog(int prio, const char *str, bool force)
 {
 #ifdef HAVE_SYSLOG_H
 	if (use_syslog) {
@@ -77,6 +83,6 @@ void _applog(int prio, const char *str)
 			fflush(stderr);
 		}
 
-		my_log_curses(prio, datetime, str);
+		my_log_curses(prio, datetime, str, force);
 	}
 }

+ 16 - 6
logging.h

@@ -28,7 +28,7 @@ extern int opt_log_level;
 
 #define LOGBUFSIZ 256
 
-extern void _applog(int prio, const char *str);
+extern void _applog(int prio, const char *str, bool force);
 
 #define IN_FMT_FFL " in %s %s():%d"
 
@@ -37,7 +37,7 @@ extern void _applog(int prio, const char *str);
 		if (use_syslog || opt_log_output || prio <= opt_log_level) { \
 			char tmp42[LOGBUFSIZ]; \
 			snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
-			_applog(prio, tmp42); \
+			_applog(prio, tmp42, false); \
 		} \
 	} \
 } while (0)
@@ -47,7 +47,17 @@ extern void _applog(int prio, const char *str);
 		if (use_syslog || opt_log_output || prio <= opt_log_level) { \
 			char tmp42[_SIZ]; \
 			snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
-			_applog(prio, tmp42); \
+			_applog(prio, tmp42, false); \
+		} \
+	} \
+} while (0)
+
+#define forcelog(prio, fmt, ...) do { \
+	if (opt_debug || prio != LOG_DEBUG) { \
+		if (use_syslog || opt_log_output || prio <= opt_log_level) { \
+			char tmp42[LOGBUFSIZ]; \
+			snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
+			_applog(prio, tmp42, true); \
 		} \
 	} \
 } while (0)
@@ -56,7 +66,7 @@ extern void _applog(int prio, const char *str);
 	if (fmt) { \
 		char tmp42[LOGBUFSIZ]; \
 		snprintf(tmp42, sizeof(tmp42), fmt, ##__VA_ARGS__); \
-		_applog(LOG_ERR, tmp42); \
+		_applog(LOG_ERR, tmp42, true); \
 	} \
 	_quit(status); \
 } while (0)
@@ -66,7 +76,7 @@ extern void _applog(int prio, const char *str);
 		char tmp42[LOGBUFSIZ]; \
 		snprintf(tmp42, sizeof(tmp42), fmt IN_FMT_FFL, \
 				##__VA_ARGS__, __FILE__, __func__, __LINE__); \
-		_applog(LOG_ERR, tmp42); \
+		_applog(LOG_ERR, tmp42, true); \
 	} \
 	_quit(status); \
 } while (0)
@@ -76,7 +86,7 @@ extern void _applog(int prio, const char *str);
 		char tmp42[LOGBUFSIZ]; \
 		snprintf(tmp42, sizeof(tmp42), fmt IN_FMT_FFL, \
 				##__VA_ARGS__, _file, _func, _line); \
-		_applog(LOG_ERR, tmp42); \
+		_applog(LOG_ERR, tmp42, true); \
 	} \
 	_quit(status); \
 } while (0)

+ 32 - 18
usbutils.c

@@ -968,7 +968,7 @@ void usb_all(int level)
 		for (i = 0; i < count; i++)
 			usb_full(&j, list[i], &buf, &off, &len, level);
 
-		_applog(LOG_WARNING, buf);
+		_applog(LOG_WARNING, buf, false);
 
 		free(buf);
 
@@ -2267,6 +2267,33 @@ static void LIBUSB_CALL transfer_callback(struct libusb_transfer *transfer)
 	cgsem_post(&ut->cgsem);
 }
 
+static int usb_transfer_toerr(int ret)
+{
+	switch (ret) {
+		default:
+		case LIBUSB_TRANSFER_COMPLETED:
+			ret = LIBUSB_SUCCESS;
+			break;
+		case LIBUSB_TRANSFER_ERROR:
+			ret = LIBUSB_ERROR_IO;
+			break;
+		case LIBUSB_TRANSFER_TIMED_OUT:
+		case LIBUSB_TRANSFER_CANCELLED:
+			ret = LIBUSB_ERROR_TIMEOUT;
+			break;
+		case LIBUSB_TRANSFER_STALL:
+			ret = LIBUSB_ERROR_PIPE;
+			break;
+		case LIBUSB_TRANSFER_NO_DEVICE:
+			ret = LIBUSB_ERROR_NO_DEVICE;
+			break;
+		case LIBUSB_TRANSFER_OVERFLOW:
+			ret = LIBUSB_ERROR_OVERFLOW;
+			break;
+	}
+	return ret;
+}
+
 /* Wait for callback function to tell us it has finished the USB transfer, but
  * use our own timer to cancel the request if we go beyond the timeout. */
 static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int timeout)
@@ -2283,8 +2310,7 @@ static int callback_wait(struct usb_transfer *ut, int *transferred, unsigned int
 		cgsem_wait(&ut->cgsem);
 	}
 	ret = transfer->status;
-	if (ret == LIBUSB_TRANSFER_CANCELLED || ret == LIBUSB_TRANSFER_TIMED_OUT)
-		ret = LIBUSB_ERROR_TIMEOUT;
+	ret = usb_transfer_toerr(ret);
 
 	/* No need to sort out mutexes here since they won't be reused */
 	*transferred = transfer->actual_length;
@@ -2331,15 +2357,9 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 	USBDEBUG("USB debug: @usb_bulk_transfer(%s (nodev=%s),intinfo=%d,epinfo=%d,data=%p,length=%d,timeout=%u,mode=%d,cmd=%s,seq=%d) endpoint=%d", cgpu->drv->name, bool_str(cgpu->usbinfo.nodev), intinfo, epinfo, data, length, timeout, mode, usb_cmdname(cmd), seq, (int)endpoint);
 
 	init_usb_transfer(&ut);
-#ifdef LINUX
 	/* We give the transfer no timeout since we manage timeouts ourself */
 	libusb_fill_bulk_transfer(ut.transfer, dev_handle, endpoint, buf, length,
 				  transfer_callback, &ut, 0);
-#else
-	/* All other OSes not so lucky */
-	libusb_fill_bulk_transfer(ut.transfer, dev_handle, endpoint, buf, length,
-				  transfer_callback, &ut, timeout);
-#endif
 	STATS_TIMEVAL(&tv_start);
 	cg_rlock(&cgusb_fd_lock);
 	err = libusb_submit_transfer(ut.transfer);
@@ -2357,7 +2377,7 @@ usb_bulk_transfer(struct libusb_device_handle *dev_handle, int intinfo,
 				cgpu->drv->name, cgpu->device_id,
 				usb_cmdname(cmd), *transferred, err, errn);
 
-	if (err == LIBUSB_ERROR_PIPE || err == LIBUSB_TRANSFER_STALL) {
+	if (err == LIBUSB_ERROR_PIPE) {
 		int retries = 0;
 
 		do {
@@ -2775,25 +2795,19 @@ static int usb_control_transfer(struct cgpu_info *cgpu, libusb_device_handle *de
 				  wIndex, wLength);
 	if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
 		memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, buffer, wLength);
-#ifdef LINUX
 	libusb_fill_control_transfer(ut.transfer, dev_handle, buf, transfer_callback,
 				     &ut, 0);
-#else
-	libusb_fill_control_transfer(ut.transfer, dev_handle, buf, transfer_callback,
-				     &ut, timeout);
-#endif
 	err = libusb_submit_transfer(ut.transfer);
 	if (!err)
 		err = callback_wait(&ut, &transferred, timeout);
-	if (err == LIBUSB_TRANSFER_COMPLETED && transferred) {
+	if (err == LIBUSB_SUCCESS && transferred) {
 		if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
 			memcpy(buffer, libusb_control_transfer_get_data(ut.transfer),
 			       transferred);
 		err = transferred;
 		goto out;
 	}
-	if ((err) == LIBUSB_TRANSFER_CANCELLED)
-		err = LIBUSB_ERROR_TIMEOUT;
+	err = usb_transfer_toerr(err);
 out:
 	complete_usb_transfer(&ut);
 	return err;

+ 7 - 4
util.c

@@ -2410,7 +2410,7 @@ void _cgsem_wait(cgsem_t *cgsem, const char *file, const char *func, const int l
 		applog(LOG_WARNING, "Failed to read errno=%d" IN_FMT_FFL, errno, file, func, line);
 }
 
-void _cgsem_destroy(cgsem_t *cgsem)
+void cgsem_destroy(cgsem_t *cgsem)
 {
 	close(cgsem->pipefd[1]);
 	close(cgsem->pipefd[0]);
@@ -2480,7 +2480,7 @@ int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, co
 	return 0;
 }
 
-void _cgsem_destroy(cgsem_t *cgsem)
+void cgsem_destroy(cgsem_t *cgsem)
 {
 	sem_destroy(cgsem);
 }
@@ -2499,7 +2499,7 @@ void *completion_thread(void *arg)
 {
 	struct cg_completion *cgc = (struct cg_completion *)arg;
 
-	pthread_detach(pthread_self());
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 	cgc->fn(cgc->fnarg);
 	cgsem_post(&cgc->cgsem);
 
@@ -2522,7 +2522,10 @@ bool cg_completion_timeout(void *fn, void *fnarg, int timeout)
 	pthread_create(&pthread, NULL, completion_thread, (void *)cgc);
 
 	ret = cgsem_mswait(&cgc->cgsem, timeout);
-	if (!ret)
+	if (!ret) {
+		pthread_join(pthread, NULL);
 		free(cgc);
+	} else
+		pthread_cancel(pthread);
 	return !ret;
 }

+ 1 - 2
util.h

@@ -134,14 +134,13 @@ void _cgsem_init(cgsem_t *cgsem, const char *file, const char *func, const int l
 void _cgsem_post(cgsem_t *cgsem, const char *file, const char *func, const int line);
 void _cgsem_wait(cgsem_t *cgsem, const char *file, const char *func, const int line);
 int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, const int line);
-void _cgsem_destroy(cgsem_t *cgsem);
+void cgsem_destroy(cgsem_t *cgsem);
 bool cg_completion_timeout(void *fn, void *fnarg, int timeout);
 
 #define cgsem_init(_sem) _cgsem_init(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_post(_sem) _cgsem_post(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_wait(_sem) _cgsem_wait(_sem, __FILE__, __func__, __LINE__)
 #define cgsem_mswait(_sem, _timeout) _cgsem_mswait(_sem, _timeout, __FILE__, __func__, __LINE__)
-#define cgsem_destroy(_sem) _cgsem_destroy(_sem)
 
 /* Align a size_t to 4 byte boundaries for fussy arches */
 static inline void align_len(size_t *len)