Merge branch 'master' into hashfast
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
diff --git a/NEWS b/NEWS
index d430852..f4d8f5b 100644
--- a/NEWS
+++ b/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'
diff --git a/cgminer.c b/cgminer.c
index 6679448..a4007f6 100644
--- a/cgminer.c
+++ b/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);
}
diff --git a/configure.ac b/configure.ac
index 39b74cc..27c68ba 100644
--- a/configure.ac
+++ b/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))
diff --git a/logging.c b/logging.c
index d00600f..52eb9ef 100644
--- a/logging.c
+++ b/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);
}
}
diff --git a/logging.h b/logging.h
index 2956452..4d8a250 100644
--- a/logging.h
+++ b/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)
diff --git a/usbutils.c b/usbutils.c
index d66d722..6ad2245 100644
--- a/usbutils.c
+++ b/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;
diff --git a/util.c b/util.c
index 48c9225..36bced2 100644
--- a/util.c
+++ b/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;
}
diff --git a/util.h b/util.h
index fa4e7ed..ae4a345 100644
--- a/util.h
+++ b/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)