|
|
@ -146,7 +146,8 @@ bool opt_bfl_noncerange; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#define QUIET (opt_quiet || opt_realquiet) |
|
|
|
#define QUIET (opt_quiet || opt_realquiet) |
|
|
|
|
|
|
|
|
|
|
|
struct thr_info *thr_info; |
|
|
|
struct thr_info *control_thr; |
|
|
|
|
|
|
|
struct thr_info **mining_thr; |
|
|
|
static int gwsched_thr_id; |
|
|
|
static int gwsched_thr_id; |
|
|
|
static int stage_thr_id; |
|
|
|
static int stage_thr_id; |
|
|
|
static int watchpool_thr_id; |
|
|
|
static int watchpool_thr_id; |
|
|
@ -156,7 +157,7 @@ static int input_thr_id; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
int gpur_thr_id; |
|
|
|
int gpur_thr_id; |
|
|
|
static int api_thr_id; |
|
|
|
static int api_thr_id; |
|
|
|
static int total_threads; |
|
|
|
static int total_control_threads; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_LIBUSB |
|
|
|
#ifdef HAVE_LIBUSB |
|
|
|
pthread_mutex_t cgusb_lock; |
|
|
|
pthread_mutex_t cgusb_lock; |
|
|
@ -171,6 +172,7 @@ static pthread_rwlock_t blk_lock; |
|
|
|
static pthread_mutex_t sshare_lock; |
|
|
|
static pthread_mutex_t sshare_lock; |
|
|
|
|
|
|
|
|
|
|
|
pthread_rwlock_t netacc_lock; |
|
|
|
pthread_rwlock_t netacc_lock; |
|
|
|
|
|
|
|
pthread_mutex_t mining_thr_lock; |
|
|
|
|
|
|
|
|
|
|
|
static pthread_mutex_t lp_lock; |
|
|
|
static pthread_mutex_t lp_lock; |
|
|
|
static pthread_cond_t lp_cond; |
|
|
|
static pthread_cond_t lp_cond; |
|
|
@ -377,7 +379,9 @@ static void sharelog(const char*disposition, const struct work*work) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
thr_id = work->thr_id; |
|
|
|
thr_id = work->thr_id; |
|
|
|
cgpu = thr_info[thr_id].cgpu; |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
pool = work->pool; |
|
|
|
pool = work->pool; |
|
|
|
t = (unsigned long int)(work->tv_work_found.tv_sec); |
|
|
|
t = (unsigned long int)(work->tv_work_found.tv_sec); |
|
|
|
target = bin2hex(work->target, sizeof(work->target)); |
|
|
|
target = bin2hex(work->target, sizeof(work->target)); |
|
|
@ -385,7 +389,7 @@ static void sharelog(const char*disposition, const struct work*work) |
|
|
|
data = bin2hex(work->data, sizeof(work->data)); |
|
|
|
data = bin2hex(work->data, sizeof(work->data)); |
|
|
|
|
|
|
|
|
|
|
|
// timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
|
|
|
|
// timestamp,disposition,target,pool,dev,thr,sharehash,sharedata
|
|
|
|
rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->api->name, cgpu->device_id, thr_id, hash, data); |
|
|
|
rv = snprintf(s, sizeof(s), "%lu,%s,%s,%s,%s%u,%u,%s,%s\n", t, disposition, target, pool->rpc_url, cgpu->drv->name, cgpu->device_id, thr_id, hash, data); |
|
|
|
free(target); |
|
|
|
free(target); |
|
|
|
free(hash); |
|
|
|
free(hash); |
|
|
|
free(data); |
|
|
|
free(data); |
|
|
@ -1722,7 +1726,13 @@ out: |
|
|
|
|
|
|
|
|
|
|
|
int dev_from_id(int thr_id) |
|
|
|
int dev_from_id(int thr_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return thr_info[thr_id].cgpu->device_id; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return cgpu->device_id; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Make the change in the recent value adjust dynamically when the difference
|
|
|
|
/* Make the change in the recent value adjust dynamically when the difference
|
|
|
@ -1875,9 +1885,9 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) |
|
|
|
suffix_string(dh64, displayed_hashes, 4); |
|
|
|
suffix_string(dh64, displayed_hashes, 4); |
|
|
|
suffix_string(dr64, displayed_rolling, 4); |
|
|
|
suffix_string(dr64, displayed_rolling, 4); |
|
|
|
|
|
|
|
|
|
|
|
sprintf(buf, "%s%d ", cgpu->api->name, cgpu->device_id); |
|
|
|
sprintf(buf, "%s%d ", cgpu->drv->name, cgpu->device_id); |
|
|
|
if (cgpu->api->get_statline_before) |
|
|
|
if (cgpu->drv->get_statline_before) |
|
|
|
cgpu->api->get_statline_before(buf, cgpu); |
|
|
|
cgpu->drv->get_statline_before(buf, cgpu); |
|
|
|
else |
|
|
|
else |
|
|
|
tailsprintf(buf, " | "); |
|
|
|
tailsprintf(buf, " | "); |
|
|
|
tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m", |
|
|
|
tailsprintf(buf, "(%ds):%s (avg):%sh/s | A:%d R:%d HW:%d U:%.1f/m", |
|
|
@ -1888,15 +1898,19 @@ static void get_statline(char *buf, struct cgpu_info *cgpu) |
|
|
|
cgpu->rejected, |
|
|
|
cgpu->rejected, |
|
|
|
cgpu->hw_errors, |
|
|
|
cgpu->hw_errors, |
|
|
|
cgpu->utility); |
|
|
|
cgpu->utility); |
|
|
|
if (cgpu->api->get_statline) |
|
|
|
if (cgpu->drv->get_statline) |
|
|
|
cgpu->api->get_statline(buf, cgpu); |
|
|
|
cgpu->drv->get_statline(buf, cgpu); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void text_print_status(int thr_id) |
|
|
|
static void text_print_status(int thr_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
char logline[256]; |
|
|
|
char logline[256]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu) { |
|
|
|
if (cgpu) { |
|
|
|
get_statline(logline, cgpu); |
|
|
|
get_statline(logline, cgpu); |
|
|
|
printf("%s\n", logline); |
|
|
|
printf("%s\n", logline); |
|
|
@ -1960,21 +1974,25 @@ static int dev_width; |
|
|
|
static void curses_print_devstatus(int thr_id) |
|
|
|
static void curses_print_devstatus(int thr_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; |
|
|
|
static int awidth = 1, rwidth = 1, hwwidth = 1, uwidth = 1; |
|
|
|
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
char logline[256]; |
|
|
|
char logline[256]; |
|
|
|
char displayed_hashes[16], displayed_rolling[16]; |
|
|
|
char displayed_hashes[16], displayed_rolling[16]; |
|
|
|
uint64_t dh64, dr64; |
|
|
|
uint64_t dh64, dr64; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) |
|
|
|
if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact) |
|
|
|
return; |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
cgpu->utility = cgpu->accepted / total_secs * 60; |
|
|
|
cgpu->utility = cgpu->accepted / total_secs * 60; |
|
|
|
|
|
|
|
|
|
|
|
wmove(statuswin,devcursor + cgpu->cgminer_id, 0); |
|
|
|
wmove(statuswin,devcursor + cgpu->cgminer_id, 0); |
|
|
|
wprintw(statuswin, " %s %*d: ", cgpu->api->name, dev_width, cgpu->device_id); |
|
|
|
wprintw(statuswin, " %s %*d: ", cgpu->drv->name, dev_width, cgpu->device_id); |
|
|
|
if (cgpu->api->get_statline_before) { |
|
|
|
if (cgpu->drv->get_statline_before) { |
|
|
|
logline[0] = '\0'; |
|
|
|
logline[0] = '\0'; |
|
|
|
cgpu->api->get_statline_before(logline, cgpu); |
|
|
|
cgpu->drv->get_statline_before(logline, cgpu); |
|
|
|
wprintw(statuswin, "%s", logline); |
|
|
|
wprintw(statuswin, "%s", logline); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
@ -1986,11 +2004,11 @@ static void curses_print_devstatus(int thr_id) |
|
|
|
suffix_string(dr64, displayed_rolling, 4); |
|
|
|
suffix_string(dr64, displayed_rolling, 4); |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->status == LIFE_DEAD) |
|
|
|
if (cgpu->status == LIFE_DEAD) |
|
|
|
wprintw(statuswin, "DEAD "); |
|
|
|
wprintw(statuswin, "DEAD "); |
|
|
|
else if (cgpu->status == LIFE_SICK) |
|
|
|
else if (cgpu->status == LIFE_SICK) |
|
|
|
wprintw(statuswin, "SICK "); |
|
|
|
wprintw(statuswin, "SICK "); |
|
|
|
else if (cgpu->deven == DEV_DISABLED) |
|
|
|
else if (cgpu->deven == DEV_DISABLED) |
|
|
|
wprintw(statuswin, "OFF "); |
|
|
|
wprintw(statuswin, "OFF "); |
|
|
|
else if (cgpu->deven == DEV_RECOVER) |
|
|
|
else if (cgpu->deven == DEV_RECOVER) |
|
|
|
wprintw(statuswin, "REST "); |
|
|
|
wprintw(statuswin, "REST "); |
|
|
|
else |
|
|
|
else |
|
|
@ -2007,9 +2025,9 @@ static void curses_print_devstatus(int thr_id) |
|
|
|
hwwidth, cgpu->hw_errors, |
|
|
|
hwwidth, cgpu->hw_errors, |
|
|
|
uwidth + 3, cgpu->utility); |
|
|
|
uwidth + 3, cgpu->utility); |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->api->get_statline) { |
|
|
|
if (cgpu->drv->get_statline) { |
|
|
|
logline[0] = '\0'; |
|
|
|
logline[0] = '\0'; |
|
|
|
cgpu->api->get_statline(logline, cgpu); |
|
|
|
cgpu->drv->get_statline(logline, cgpu); |
|
|
|
wprintw(statuswin, "%s", logline); |
|
|
|
wprintw(statuswin, "%s", logline); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2212,7 +2230,11 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, |
|
|
|
char *hashshow, bool resubmit, char *worktime) |
|
|
|
char *hashshow, bool resubmit, char *worktime) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct pool *pool = work->pool; |
|
|
|
struct pool *pool = work->pool; |
|
|
|
struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[work->thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
if (json_is_true(res) || (work->gbt && json_is_null(res))) { |
|
|
|
if (json_is_true(res) || (work->gbt && json_is_null(res))) { |
|
|
|
mutex_lock(&stats_lock); |
|
|
|
mutex_lock(&stats_lock); |
|
|
@ -2234,10 +2256,10 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, |
|
|
|
if (!QUIET) { |
|
|
|
if (!QUIET) { |
|
|
|
if (total_pools > 1) |
|
|
|
if (total_pools > 1) |
|
|
|
applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s", |
|
|
|
applog(LOG_NOTICE, "Accepted %s %s %d pool %d %s%s", |
|
|
|
hashshow, cgpu->api->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
hashshow, cgpu->drv->name, cgpu->device_id, work->pool->pool_no, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
else |
|
|
|
else |
|
|
|
applog(LOG_NOTICE, "Accepted %s %s %d %s%s", |
|
|
|
applog(LOG_NOTICE, "Accepted %s %s %d %s%s", |
|
|
|
hashshow, cgpu->api->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
hashshow, cgpu->drv->name, cgpu->device_id, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
} |
|
|
|
} |
|
|
|
sharelog("accept", work); |
|
|
|
sharelog("accept", work); |
|
|
|
if (opt_shares && total_accepted >= opt_shares) { |
|
|
|
if (opt_shares && total_accepted >= opt_shares) { |
|
|
@ -2302,7 +2324,7 @@ share_result(json_t *val, json_t *res, json_t *err, const struct work *work, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s", |
|
|
|
applog(LOG_NOTICE, "Rejected %s %s %d %s%s %s%s", |
|
|
|
hashshow, cgpu->api->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
hashshow, cgpu->drv->name, cgpu->device_id, where, reason, resubmit ? "(resubmit)" : "", worktime); |
|
|
|
sharelog(disposition, work); |
|
|
|
sharelog(disposition, work); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -2349,6 +2371,8 @@ static uint64_t share_diff(const struct work *work) |
|
|
|
best_diff = ret; |
|
|
|
best_diff = ret; |
|
|
|
suffix_string(best_diff, best_share, 0); |
|
|
|
suffix_string(best_diff, best_share, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (ret > work->pool->best_diff) |
|
|
|
|
|
|
|
work->pool->best_diff = ret; |
|
|
|
mutex_unlock(&control_lock); |
|
|
|
mutex_unlock(&control_lock); |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
@ -2360,13 +2384,17 @@ static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) |
|
|
|
char *s; |
|
|
|
char *s; |
|
|
|
bool rc = false; |
|
|
|
bool rc = false; |
|
|
|
int thr_id = work->thr_id; |
|
|
|
int thr_id = work->thr_id; |
|
|
|
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; |
|
|
|
struct cgpu_info *cgpu; |
|
|
|
struct pool *pool = work->pool; |
|
|
|
struct pool *pool = work->pool; |
|
|
|
int rolltime; |
|
|
|
int rolltime; |
|
|
|
struct timeval tv_submit, tv_submit_reply; |
|
|
|
struct timeval tv_submit, tv_submit_reply; |
|
|
|
char hashshow[64 + 4] = ""; |
|
|
|
char hashshow[64 + 4] = ""; |
|
|
|
char worktime[200] = ""; |
|
|
|
char worktime[200] = ""; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef __BIG_ENDIAN__ |
|
|
|
#ifdef __BIG_ENDIAN__ |
|
|
|
int swapcounter = 0; |
|
|
|
int swapcounter = 0; |
|
|
|
for (swapcounter = 0; swapcounter < 32; swapcounter++) |
|
|
|
for (swapcounter = 0; swapcounter < 32; swapcounter++) |
|
|
@ -2574,7 +2602,7 @@ static inline struct pool *select_pool(bool lagging) |
|
|
|
return pool; |
|
|
|
return pool; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249216.0; |
|
|
|
static double DIFFEXACTONE = 26959946667150639794667015087019630673637144422540572481103610249215.0; |
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Calculate the work share difficulty |
|
|
|
* Calculate the work share difficulty |
|
|
@ -2730,8 +2758,6 @@ static void disable_curses(void) |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
static void print_summary(void); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void __kill_work(void) |
|
|
|
static void __kill_work(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct thr_info *thr; |
|
|
|
struct thr_info *thr; |
|
|
@ -2744,18 +2770,20 @@ static void __kill_work(void) |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Killing off watchpool thread"); |
|
|
|
applog(LOG_DEBUG, "Killing off watchpool thread"); |
|
|
|
/* Kill the watchpool thread */ |
|
|
|
/* Kill the watchpool thread */ |
|
|
|
thr = &thr_info[watchpool_thr_id]; |
|
|
|
thr = &control_thr[watchpool_thr_id]; |
|
|
|
thr_info_cancel(thr); |
|
|
|
thr_info_cancel(thr); |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Killing off watchdog thread"); |
|
|
|
applog(LOG_DEBUG, "Killing off watchdog thread"); |
|
|
|
/* Kill the watchdog thread */ |
|
|
|
/* Kill the watchdog thread */ |
|
|
|
thr = &thr_info[watchdog_thr_id]; |
|
|
|
thr = &control_thr[watchdog_thr_id]; |
|
|
|
thr_info_cancel(thr); |
|
|
|
thr_info_cancel(thr); |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Stopping mining threads"); |
|
|
|
applog(LOG_DEBUG, "Stopping mining threads"); |
|
|
|
/* Stop the mining threads*/ |
|
|
|
/* Stop the mining threads*/ |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
thr = &thr_info[i]; |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
thr = mining_thr[i]; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
thr_info_freeze(thr); |
|
|
|
thr_info_freeze(thr); |
|
|
|
thr->pause = true; |
|
|
|
thr->pause = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -2765,17 +2793,19 @@ static void __kill_work(void) |
|
|
|
applog(LOG_DEBUG, "Killing off mining threads"); |
|
|
|
applog(LOG_DEBUG, "Killing off mining threads"); |
|
|
|
/* Kill the mining threads*/ |
|
|
|
/* Kill the mining threads*/ |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
thr = &thr_info[i]; |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
thr = mining_thr[i]; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
thr_info_cancel(thr); |
|
|
|
thr_info_cancel(thr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Killing off stage thread"); |
|
|
|
applog(LOG_DEBUG, "Killing off stage thread"); |
|
|
|
/* Stop the others */ |
|
|
|
/* Stop the others */ |
|
|
|
thr = &thr_info[stage_thr_id]; |
|
|
|
thr = &control_thr[stage_thr_id]; |
|
|
|
thr_info_cancel(thr); |
|
|
|
thr_info_cancel(thr); |
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Killing off API thread"); |
|
|
|
applog(LOG_DEBUG, "Killing off API thread"); |
|
|
|
thr = &thr_info[api_thr_id]; |
|
|
|
thr = &control_thr[api_thr_id]; |
|
|
|
thr_info_cancel(thr); |
|
|
|
thr_info_cancel(thr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3369,8 +3399,10 @@ static void restart_threads(void) |
|
|
|
/* Discard staged work that is now stale */ |
|
|
|
/* Discard staged work that is now stale */ |
|
|
|
discard_stale(); |
|
|
|
discard_stale(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
for (i = 0; i < mining_threads; i++) |
|
|
|
for (i = 0; i < mining_threads; i++) |
|
|
|
thr_info[i].work_restart = true; |
|
|
|
mining_thr[i]->work_restart = true; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&restart_lock); |
|
|
|
mutex_lock(&restart_lock); |
|
|
|
pthread_cond_broadcast(&restart_cond); |
|
|
|
pthread_cond_broadcast(&restart_cond); |
|
|
@ -3914,6 +3946,20 @@ void write_config(FILE *fcfg) |
|
|
|
json_escape_free(); |
|
|
|
json_escape_free(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void zero_bestshare(void) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
best_diff = 0; |
|
|
|
|
|
|
|
memset(best_share, 0, 8); |
|
|
|
|
|
|
|
suffix_string(best_diff, best_share, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < total_pools; i++) { |
|
|
|
|
|
|
|
struct pool *pool = pools[i]; |
|
|
|
|
|
|
|
pool->best_diff = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void zero_stats(void) |
|
|
|
void zero_stats(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int i; |
|
|
@ -3930,10 +3976,11 @@ void zero_stats(void) |
|
|
|
total_go = 0; |
|
|
|
total_go = 0; |
|
|
|
total_ro = 0; |
|
|
|
total_ro = 0; |
|
|
|
total_secs = 1.0; |
|
|
|
total_secs = 1.0; |
|
|
|
best_diff = 0; |
|
|
|
|
|
|
|
total_diff1 = 0; |
|
|
|
total_diff1 = 0; |
|
|
|
memset(best_share, 0, 8); |
|
|
|
found_blocks = 0; |
|
|
|
suffix_string(best_diff, best_share, 0); |
|
|
|
total_diff_accepted = 0; |
|
|
|
|
|
|
|
total_diff_rejected = 0; |
|
|
|
|
|
|
|
total_diff_stale = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < total_pools; i++) { |
|
|
|
for (i = 0; i < total_pools; i++) { |
|
|
|
struct pool *pool = pools[i]; |
|
|
|
struct pool *pool = pools[i]; |
|
|
@ -3945,8 +3992,16 @@ void zero_stats(void) |
|
|
|
pool->discarded_work = 0; |
|
|
|
pool->discarded_work = 0; |
|
|
|
pool->getfail_occasions = 0; |
|
|
|
pool->getfail_occasions = 0; |
|
|
|
pool->remotefail_occasions = 0; |
|
|
|
pool->remotefail_occasions = 0; |
|
|
|
|
|
|
|
pool->last_share_time = 0; |
|
|
|
|
|
|
|
pool->diff1 = 0; |
|
|
|
|
|
|
|
pool->diff_accepted = 0; |
|
|
|
|
|
|
|
pool->diff_rejected = 0; |
|
|
|
|
|
|
|
pool->diff_stale = 0; |
|
|
|
|
|
|
|
pool->last_share_diff = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zero_bestshare(); |
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&hash_lock); |
|
|
|
mutex_lock(&hash_lock); |
|
|
|
for (i = 0; i < total_devices; ++i) { |
|
|
|
for (i = 0; i < total_devices; ++i) { |
|
|
|
struct cgpu_info *cgpu = devices[i]; |
|
|
|
struct cgpu_info *cgpu = devices[i]; |
|
|
@ -3956,6 +4011,11 @@ void zero_stats(void) |
|
|
|
cgpu->rejected = 0; |
|
|
|
cgpu->rejected = 0; |
|
|
|
cgpu->hw_errors = 0; |
|
|
|
cgpu->hw_errors = 0; |
|
|
|
cgpu->utility = 0.0; |
|
|
|
cgpu->utility = 0.0; |
|
|
|
|
|
|
|
cgpu->last_share_pool_time = 0; |
|
|
|
|
|
|
|
cgpu->diff1 = 0; |
|
|
|
|
|
|
|
cgpu->diff_accepted = 0; |
|
|
|
|
|
|
|
cgpu->diff_rejected = 0; |
|
|
|
|
|
|
|
cgpu->last_share_diff = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
mutex_unlock(&hash_lock); |
|
|
|
mutex_unlock(&hash_lock); |
|
|
|
} |
|
|
|
} |
|
|
@ -4378,20 +4438,23 @@ static void hashmeter(int thr_id, struct timeval *diff, |
|
|
|
bool showlog = false; |
|
|
|
bool showlog = false; |
|
|
|
char displayed_hashes[16], displayed_rolling[16]; |
|
|
|
char displayed_hashes[16], displayed_rolling[16]; |
|
|
|
uint64_t dh64, dr64; |
|
|
|
uint64_t dh64, dr64; |
|
|
|
|
|
|
|
struct thr_info *thr; |
|
|
|
|
|
|
|
|
|
|
|
local_mhashes = (double)hashes_done / 1000000.0; |
|
|
|
local_mhashes = (double)hashes_done / 1000000.0; |
|
|
|
/* Update the last time this thread reported in */ |
|
|
|
/* Update the last time this thread reported in */ |
|
|
|
if (thr_id >= 0) { |
|
|
|
if (thr_id >= 0) { |
|
|
|
gettimeofday(&thr_info[thr_id].last, NULL); |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
thr_info[thr_id].cgpu->device_last_well = time(NULL); |
|
|
|
thr = mining_thr[thr_id]; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
gettimeofday(&(thr->last), NULL); |
|
|
|
|
|
|
|
thr->cgpu->device_last_well = time(NULL); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); |
|
|
|
secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0); |
|
|
|
|
|
|
|
|
|
|
|
/* So we can call hashmeter from a non worker thread */ |
|
|
|
/* So we can call hashmeter from a non worker thread */ |
|
|
|
if (thr_id >= 0) { |
|
|
|
if (thr_id >= 0) { |
|
|
|
struct thr_info *thr = &thr_info[thr_id]; |
|
|
|
struct cgpu_info *cgpu = thr->cgpu; |
|
|
|
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; |
|
|
|
|
|
|
|
double thread_rolling = 0.0; |
|
|
|
double thread_rolling = 0.0; |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
@ -4574,8 +4637,8 @@ static void clear_stratum_shares(struct pool *pool) |
|
|
|
|
|
|
|
|
|
|
|
if (cleared) { |
|
|
|
if (cleared) { |
|
|
|
applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no); |
|
|
|
applog(LOG_WARNING, "Lost %d shares due to stratum disconnect on pool %d", cleared, pool->pool_no); |
|
|
|
pool->stale_shares++; |
|
|
|
pool->stale_shares += cleared; |
|
|
|
total_stale++; |
|
|
|
total_stale += cleared; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -4881,7 +4944,7 @@ retry_stratum: |
|
|
|
calc_diff(work, 0); |
|
|
|
calc_diff(work, 0); |
|
|
|
applog(LOG_DEBUG, "Pushing pooltest work to base pool"); |
|
|
|
applog(LOG_DEBUG, "Pushing pooltest work to base pool"); |
|
|
|
|
|
|
|
|
|
|
|
tq_push(thr_info[stage_thr_id].q, work); |
|
|
|
tq_push(control_thr[stage_thr_id].q, work); |
|
|
|
total_getworks++; |
|
|
|
total_getworks++; |
|
|
|
pool->getwork_requested++; |
|
|
|
pool->getwork_requested++; |
|
|
|
ret = true; |
|
|
|
ret = true; |
|
|
@ -5221,15 +5284,15 @@ static bool hashtest(struct thr_info *thr, struct work *work) |
|
|
|
|
|
|
|
|
|
|
|
if (hash2_32[7] != 0) { |
|
|
|
if (hash2_32[7] != 0) { |
|
|
|
applog(LOG_WARNING, "%s%d: invalid nonce - HW error", |
|
|
|
applog(LOG_WARNING, "%s%d: invalid nonce - HW error", |
|
|
|
thr->cgpu->api->name, thr->cgpu->device_id); |
|
|
|
thr->cgpu->drv->name, thr->cgpu->device_id); |
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&stats_lock); |
|
|
|
mutex_lock(&stats_lock); |
|
|
|
hw_errors++; |
|
|
|
hw_errors++; |
|
|
|
thr->cgpu->hw_errors++; |
|
|
|
thr->cgpu->hw_errors++; |
|
|
|
mutex_unlock(&stats_lock); |
|
|
|
mutex_unlock(&stats_lock); |
|
|
|
|
|
|
|
|
|
|
|
if (thr->cgpu->api->hw_error) |
|
|
|
if (thr->cgpu->drv->hw_error) |
|
|
|
thr->cgpu->api->hw_error(thr); |
|
|
|
thr->cgpu->drv->hw_error(thr); |
|
|
|
|
|
|
|
|
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
} |
|
|
|
} |
|
|
@ -5277,7 +5340,7 @@ static inline bool abandon_work(struct work *work, struct timeval *wdiff, uint64 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void mt_disable(struct thr_info *mythr, const int thr_id, |
|
|
|
static void mt_disable(struct thr_info *mythr, const int thr_id, |
|
|
|
struct device_api *api) |
|
|
|
struct device_drv *drv) |
|
|
|
{ |
|
|
|
{ |
|
|
|
applog(LOG_WARNING, "Thread %d being disabled", thr_id); |
|
|
|
applog(LOG_WARNING, "Thread %d being disabled", thr_id); |
|
|
|
mythr->rolling = mythr->cgpu->rolling = 0; |
|
|
|
mythr->rolling = mythr->cgpu->rolling = 0; |
|
|
@ -5288,8 +5351,8 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, |
|
|
|
} while (mythr->pause); |
|
|
|
} while (mythr->pause); |
|
|
|
thread_reportin(mythr); |
|
|
|
thread_reportin(mythr); |
|
|
|
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); |
|
|
|
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); |
|
|
|
if (api->thread_enable) |
|
|
|
if (drv->thread_enable) |
|
|
|
api->thread_enable(mythr); |
|
|
|
drv->thread_enable(mythr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void *miner_thread(void *userdata) |
|
|
|
void *miner_thread(void *userdata) |
|
|
@ -5297,7 +5360,7 @@ void *miner_thread(void *userdata) |
|
|
|
struct thr_info *mythr = userdata; |
|
|
|
struct thr_info *mythr = userdata; |
|
|
|
const int thr_id = mythr->id; |
|
|
|
const int thr_id = mythr->id; |
|
|
|
struct cgpu_info *cgpu = mythr->cgpu; |
|
|
|
struct cgpu_info *cgpu = mythr->cgpu; |
|
|
|
struct device_api *api = cgpu->api; |
|
|
|
struct device_drv *drv = cgpu->drv; |
|
|
|
struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats); |
|
|
|
struct cgminer_stats *dev_stats = &(cgpu->cgminer_stats); |
|
|
|
struct cgminer_stats *pool_stats; |
|
|
|
struct cgminer_stats *pool_stats; |
|
|
|
struct timeval getwork_start; |
|
|
|
struct timeval getwork_start; |
|
|
@ -5306,7 +5369,7 @@ void *miner_thread(void *userdata) |
|
|
|
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 = {0, 0}; |
|
|
|
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 = drv->can_limit_work ? drv->can_limit_work(mythr) : 0xffffffff; |
|
|
|
int64_t hashes_done = 0; |
|
|
|
int64_t hashes_done = 0; |
|
|
|
int64_t hashes; |
|
|
|
int64_t hashes; |
|
|
|
struct work *work; |
|
|
|
struct work *work; |
|
|
@ -5320,7 +5383,7 @@ void *miner_thread(void *userdata) |
|
|
|
|
|
|
|
|
|
|
|
gettimeofday(&getwork_start, NULL); |
|
|
|
gettimeofday(&getwork_start, NULL); |
|
|
|
|
|
|
|
|
|
|
|
if (api->thread_init && !api->thread_init(mythr)) { |
|
|
|
if (drv->thread_init && !drv->thread_init(mythr)) { |
|
|
|
dev_error(cgpu, REASON_THREAD_FAIL_INIT); |
|
|
|
dev_error(cgpu, REASON_THREAD_FAIL_INIT); |
|
|
|
goto out; |
|
|
|
goto out; |
|
|
|
} |
|
|
|
} |
|
|
@ -5340,7 +5403,7 @@ void *miner_thread(void *userdata) |
|
|
|
gettimeofday(&tv_workstart, NULL); |
|
|
|
gettimeofday(&tv_workstart, NULL); |
|
|
|
work->blk.nonce = 0; |
|
|
|
work->blk.nonce = 0; |
|
|
|
cgpu->max_hashes = 0; |
|
|
|
cgpu->max_hashes = 0; |
|
|
|
if (api->prepare_work && !api->prepare_work(mythr, work)) { |
|
|
|
if (drv->prepare_work && !drv->prepare_work(mythr, work)) { |
|
|
|
applog(LOG_ERR, "work prepare failed, exiting " |
|
|
|
applog(LOG_ERR, "work prepare failed, exiting " |
|
|
|
"mining thread %d", thr_id); |
|
|
|
"mining thread %d", thr_id); |
|
|
|
break; |
|
|
|
break; |
|
|
@ -5382,16 +5445,16 @@ void *miner_thread(void *userdata) |
|
|
|
gettimeofday(&(work->tv_work_start), NULL); |
|
|
|
gettimeofday(&(work->tv_work_start), NULL); |
|
|
|
|
|
|
|
|
|
|
|
thread_reportin(mythr); |
|
|
|
thread_reportin(mythr); |
|
|
|
hashes = api->scanhash(mythr, work, work->blk.nonce + max_nonce); |
|
|
|
hashes = drv->scanhash(mythr, work, work->blk.nonce + max_nonce); |
|
|
|
thread_reportin(mythr); |
|
|
|
thread_reportin(mythr); |
|
|
|
|
|
|
|
|
|
|
|
gettimeofday(&getwork_start, NULL); |
|
|
|
gettimeofday(&getwork_start, NULL); |
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(hashes == -1)) { |
|
|
|
if (unlikely(hashes == -1)) { |
|
|
|
applog(LOG_ERR, "%s %d failure, disabling!", api->name, cgpu->device_id); |
|
|
|
applog(LOG_ERR, "%s %d failure, disabling!", drv->name, cgpu->device_id); |
|
|
|
cgpu->deven = DEV_DISABLED; |
|
|
|
cgpu->deven = DEV_DISABLED; |
|
|
|
dev_error(cgpu, REASON_THREAD_ZERO_HASH); |
|
|
|
dev_error(cgpu, REASON_THREAD_ZERO_HASH); |
|
|
|
mt_disable(mythr, thr_id, api); |
|
|
|
mt_disable(mythr, thr_id, drv); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hashes_done += hashes; |
|
|
|
hashes_done += hashes; |
|
|
@ -5412,7 +5475,7 @@ void *miner_thread(void *userdata) |
|
|
|
if (unlikely((long)sdiff.tv_sec < cycle)) { |
|
|
|
if (unlikely((long)sdiff.tv_sec < cycle)) { |
|
|
|
int mult; |
|
|
|
int mult; |
|
|
|
|
|
|
|
|
|
|
|
if (likely(!api->can_limit_work || max_nonce == 0xffffffff)) |
|
|
|
if (likely(!drv->can_limit_work || max_nonce == 0xffffffff)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10; |
|
|
|
mult = 1000000 / ((sdiff.tv_usec + 0x400) / 0x400) + 0x10; |
|
|
@ -5421,9 +5484,9 @@ void *miner_thread(void *userdata) |
|
|
|
max_nonce = 0xffffffff; |
|
|
|
max_nonce = 0xffffffff; |
|
|
|
else |
|
|
|
else |
|
|
|
max_nonce = (max_nonce * mult) / 0x400; |
|
|
|
max_nonce = (max_nonce * mult) / 0x400; |
|
|
|
} else if (unlikely(sdiff.tv_sec > cycle) && api->can_limit_work) |
|
|
|
} else if (unlikely(sdiff.tv_sec > cycle) && drv->can_limit_work) |
|
|
|
max_nonce = max_nonce * cycle / sdiff.tv_sec; |
|
|
|
max_nonce = max_nonce * cycle / sdiff.tv_sec; |
|
|
|
else if (unlikely(sdiff.tv_usec > 100000) && api->can_limit_work) |
|
|
|
else if (unlikely(sdiff.tv_usec > 100000) && drv->can_limit_work) |
|
|
|
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)); |
|
|
|
|
|
|
|
|
|
|
|
timersub(&tv_end, &tv_lastupdate, &diff); |
|
|
|
timersub(&tv_end, &tv_lastupdate, &diff); |
|
|
@ -5449,7 +5512,7 @@ void *miner_thread(void *userdata) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) |
|
|
|
if (unlikely(mythr->pause || cgpu->deven != DEV_ENABLED)) |
|
|
|
mt_disable(mythr, thr_id, api); |
|
|
|
mt_disable(mythr, thr_id, drv); |
|
|
|
|
|
|
|
|
|
|
|
sdiff.tv_sec = sdiff.tv_usec = 0; |
|
|
|
sdiff.tv_sec = sdiff.tv_usec = 0; |
|
|
|
} while (!abandon_work(work, &wdiff, cgpu->max_hashes)); |
|
|
|
} while (!abandon_work(work, &wdiff, cgpu->max_hashes)); |
|
|
@ -5457,8 +5520,8 @@ void *miner_thread(void *userdata) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
out: |
|
|
|
out: |
|
|
|
if (api->thread_shutdown) |
|
|
|
if (drv->thread_shutdown) |
|
|
|
api->thread_shutdown(mythr); |
|
|
|
drv->thread_shutdown(mythr); |
|
|
|
|
|
|
|
|
|
|
|
thread_reportin(mythr); |
|
|
|
thread_reportin(mythr); |
|
|
|
applog(LOG_ERR, "Thread %d failure, exiting", thr_id); |
|
|
|
applog(LOG_ERR, "Thread %d failure, exiting", thr_id); |
|
|
@ -5686,8 +5749,8 @@ out: |
|
|
|
|
|
|
|
|
|
|
|
void reinit_device(struct cgpu_info *cgpu) |
|
|
|
void reinit_device(struct cgpu_info *cgpu) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (cgpu->api->reinit_device) |
|
|
|
if (cgpu->drv->reinit_device) |
|
|
|
cgpu->api->reinit_device(cgpu); |
|
|
|
cgpu->drv->reinit_device(cgpu); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static struct timeval rotate_tv; |
|
|
|
static struct timeval rotate_tv; |
|
|
@ -5829,12 +5892,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) |
|
|
|
applog(LOG_WARNING, "Will restart execution as scheduled at %02d:%02d", |
|
|
|
applog(LOG_WARNING, "Will restart execution as scheduled at %02d:%02d", |
|
|
|
schedstart.tm.tm_hour, schedstart.tm.tm_min); |
|
|
|
schedstart.tm.tm_hour, schedstart.tm.tm_min); |
|
|
|
sched_paused = true; |
|
|
|
sched_paused = true; |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
struct thr_info *thr; |
|
|
|
for (i = 0; i < mining_threads; i++) |
|
|
|
thr = &thr_info[i]; |
|
|
|
mining_thr[i]->pause = true; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
thr->pause = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (sched_paused && should_run()) { |
|
|
|
} else if (sched_paused && should_run()) { |
|
|
|
applog(LOG_WARNING, "Restarting execution as per start time %02d:%02d scheduled", |
|
|
|
applog(LOG_WARNING, "Restarting execution as per start time %02d:%02d scheduled", |
|
|
|
schedstart.tm.tm_hour, schedstart.tm.tm_min); |
|
|
|
schedstart.tm.tm_hour, schedstart.tm.tm_min); |
|
|
@ -5845,7 +5906,10 @@ static void *watchdog_thread(void __maybe_unused *userdata) |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
struct thr_info *thr; |
|
|
|
struct thr_info *thr; |
|
|
|
thr = &thr_info[i]; |
|
|
|
|
|
|
|
|
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
thr = mining_thr[i]; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
/* Don't touch disabled devices */ |
|
|
|
/* Don't touch disabled devices */ |
|
|
|
if (thr->cgpu->deven == DEV_DISABLED) |
|
|
|
if (thr->cgpu->deven == DEV_DISABLED) |
|
|
@ -5862,12 +5926,12 @@ static void *watchdog_thread(void __maybe_unused *userdata) |
|
|
|
char dev_str[8]; |
|
|
|
char dev_str[8]; |
|
|
|
int gpu; |
|
|
|
int gpu; |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->api->get_stats) |
|
|
|
if (cgpu->drv->get_stats) |
|
|
|
cgpu->api->get_stats(cgpu); |
|
|
|
cgpu->drv->get_stats(cgpu); |
|
|
|
|
|
|
|
|
|
|
|
gpu = cgpu->device_id; |
|
|
|
gpu = cgpu->device_id; |
|
|
|
denable = &cgpu->deven; |
|
|
|
denable = &cgpu->deven; |
|
|
|
sprintf(dev_str, "%s%d", cgpu->api->name, gpu); |
|
|
|
sprintf(dev_str, "%s%d", cgpu->drv->name, gpu); |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_ADL |
|
|
|
#ifdef HAVE_ADL |
|
|
|
if (adl_active && cgpu->has_adl) |
|
|
|
if (adl_active && cgpu->has_adl) |
|
|
@ -5887,7 +5951,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WANT_CPUMINE |
|
|
|
#ifdef WANT_CPUMINE |
|
|
|
if (!strcmp(cgpu->api->dname, "cpu")) |
|
|
|
if (cgpu->drv->drv == DRIVER_CPU) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { |
|
|
|
if (cgpu->status != LIFE_WELL && (now.tv_sec - thr->last.tv_sec < WATCHDOG_SICK_TIME)) { |
|
|
@ -5944,7 +6008,7 @@ static void log_print_status(struct cgpu_info *cgpu) |
|
|
|
applog(LOG_WARNING, "%s", logline); |
|
|
|
applog(LOG_WARNING, "%s", logline); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void print_summary(void) |
|
|
|
void print_summary(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct timeval diff; |
|
|
|
struct timeval diff; |
|
|
|
int hours, mins, secs, i; |
|
|
|
int hours, mins, secs, i; |
|
|
@ -6277,26 +6341,27 @@ void enable_curses(void) { |
|
|
|
|
|
|
|
|
|
|
|
/* TODO: fix need a dummy CPU device_api even if no support for CPU mining */ |
|
|
|
/* TODO: fix need a dummy CPU device_api even if no support for CPU mining */ |
|
|
|
#ifndef WANT_CPUMINE |
|
|
|
#ifndef WANT_CPUMINE |
|
|
|
struct device_api cpu_api; |
|
|
|
struct device_drv cpu_drv; |
|
|
|
struct device_api cpu_api = { |
|
|
|
struct device_drv cpu_drv = { |
|
|
|
|
|
|
|
.drv = DRIVER_CPU, |
|
|
|
.name = "CPU", |
|
|
|
.name = "CPU", |
|
|
|
}; |
|
|
|
}; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BITFORCE |
|
|
|
#ifdef USE_BITFORCE |
|
|
|
extern struct device_api bitforce_api; |
|
|
|
extern struct device_drv bitforce_drv; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ICARUS |
|
|
|
#ifdef USE_ICARUS |
|
|
|
extern struct device_api icarus_api; |
|
|
|
extern struct device_drv icarus_drv; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_MODMINER |
|
|
|
#ifdef USE_MODMINER |
|
|
|
extern struct device_api modminer_api; |
|
|
|
extern struct device_drv modminer_drv; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ZTEX |
|
|
|
#ifdef USE_ZTEX |
|
|
|
extern struct device_api ztex_api; |
|
|
|
extern struct device_drv ztex_drv; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -6311,7 +6376,7 @@ void enable_device(struct cgpu_info *cgpu) |
|
|
|
adj_width(mining_threads, &dev_width); |
|
|
|
adj_width(mining_threads, &dev_width); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
if (cgpu->api == &opencl_api) { |
|
|
|
if (cgpu->drv->drv == DRIVER_OPENCL) { |
|
|
|
gpu_threads += cgpu->threads; |
|
|
|
gpu_threads += cgpu->threads; |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
@ -6328,12 +6393,12 @@ bool add_cgpu(struct cgpu_info*cgpu) |
|
|
|
static struct _cgpu_devid_counter *devids = NULL; |
|
|
|
static struct _cgpu_devid_counter *devids = NULL; |
|
|
|
struct _cgpu_devid_counter *d; |
|
|
|
struct _cgpu_devid_counter *d; |
|
|
|
|
|
|
|
|
|
|
|
HASH_FIND_STR(devids, cgpu->api->name, d); |
|
|
|
HASH_FIND_STR(devids, cgpu->drv->name, d); |
|
|
|
if (d) |
|
|
|
if (d) |
|
|
|
cgpu->device_id = ++d->lastid; |
|
|
|
cgpu->device_id = ++d->lastid; |
|
|
|
else { |
|
|
|
else { |
|
|
|
d = malloc(sizeof(*d)); |
|
|
|
d = malloc(sizeof(*d)); |
|
|
|
memcpy(d->name, cgpu->api->name, sizeof(d->name)); |
|
|
|
memcpy(d->name, cgpu->drv->name, sizeof(d->name)); |
|
|
|
cgpu->device_id = d->lastid = 0; |
|
|
|
cgpu->device_id = d->lastid = 0; |
|
|
|
HASH_ADD_STR(devids, name, d); |
|
|
|
HASH_ADD_STR(devids, name, d); |
|
|
|
} |
|
|
|
} |
|
|
@ -6342,6 +6407,21 @@ bool add_cgpu(struct cgpu_info*cgpu) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct device_drv *copy_drv(struct device_drv *drv) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct device_drv *copy; |
|
|
|
|
|
|
|
char buf[100]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(!(copy = malloc(sizeof(*copy))))) { |
|
|
|
|
|
|
|
sprintf(buf, "Failed to allocate device_drv copy of %s (%s)", |
|
|
|
|
|
|
|
drv->name, drv->copy ? "copy" : "original"); |
|
|
|
|
|
|
|
quit(1, buf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
memcpy(copy, drv, sizeof(*copy)); |
|
|
|
|
|
|
|
copy->copy = true; |
|
|
|
|
|
|
|
return copy; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
int main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool pools_active = false; |
|
|
|
bool pools_active = false; |
|
|
@ -6382,6 +6462,7 @@ int main(int argc, char *argv[]) |
|
|
|
mutex_init(&sshare_lock); |
|
|
|
mutex_init(&sshare_lock); |
|
|
|
rwlock_init(&blk_lock); |
|
|
|
rwlock_init(&blk_lock); |
|
|
|
rwlock_init(&netacc_lock); |
|
|
|
rwlock_init(&netacc_lock); |
|
|
|
|
|
|
|
mutex_init(&mining_thr_lock); |
|
|
|
|
|
|
|
|
|
|
|
mutex_init(&lp_lock); |
|
|
|
mutex_init(&lp_lock); |
|
|
|
if (unlikely(pthread_cond_init(&lp_cond, NULL))) |
|
|
|
if (unlikely(pthread_cond_init(&lp_cond, NULL))) |
|
|
@ -6551,32 +6632,32 @@ int main(int argc, char *argv[]) |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
if (!opt_nogpu) |
|
|
|
if (!opt_nogpu) |
|
|
|
opencl_api.api_detect(); |
|
|
|
opencl_drv.drv_detect(); |
|
|
|
gpu_threads = 0; |
|
|
|
gpu_threads = 0; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ICARUS |
|
|
|
#ifdef USE_ICARUS |
|
|
|
if (!opt_scrypt) |
|
|
|
if (!opt_scrypt) |
|
|
|
icarus_api.api_detect(); |
|
|
|
icarus_drv.drv_detect(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BITFORCE |
|
|
|
#ifdef USE_BITFORCE |
|
|
|
if (!opt_scrypt) |
|
|
|
if (!opt_scrypt) |
|
|
|
bitforce_api.api_detect(); |
|
|
|
bitforce_drv.drv_detect(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_MODMINER |
|
|
|
#ifdef USE_MODMINER |
|
|
|
if (!opt_scrypt) |
|
|
|
if (!opt_scrypt) |
|
|
|
modminer_api.api_detect(); |
|
|
|
modminer_drv.drv_detect(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_ZTEX |
|
|
|
#ifdef USE_ZTEX |
|
|
|
if (!opt_scrypt) |
|
|
|
if (!opt_scrypt) |
|
|
|
ztex_api.api_detect(); |
|
|
|
ztex_drv.drv_detect(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifdef WANT_CPUMINE |
|
|
|
#ifdef WANT_CPUMINE |
|
|
|
cpu_api.api_detect(); |
|
|
|
cpu_drv.drv_detect(); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
if (devices_enabled == -1) { |
|
|
|
if (devices_enabled == -1) { |
|
|
@ -6584,9 +6665,9 @@ int main(int argc, char *argv[]) |
|
|
|
for (i = 0; i < total_devices; ++i) { |
|
|
|
for (i = 0; i < total_devices; ++i) { |
|
|
|
struct cgpu_info *cgpu = devices[i]; |
|
|
|
struct cgpu_info *cgpu = devices[i]; |
|
|
|
if (cgpu->name) |
|
|
|
if (cgpu->name) |
|
|
|
applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->name, cgpu->api->dname); |
|
|
|
applog(LOG_ERR, " %2d. %s %d: %s (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->name, cgpu->drv->dname); |
|
|
|
else |
|
|
|
else |
|
|
|
applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->api->name, cgpu->device_id, cgpu->api->dname); |
|
|
|
applog(LOG_ERR, " %2d. %s %d (driver: %s)", i, cgpu->drv->name, cgpu->device_id, cgpu->drv->dname); |
|
|
|
} |
|
|
|
} |
|
|
|
quit(0, "%d devices listed", total_devices); |
|
|
|
quit(0, "%d devices listed", total_devices); |
|
|
|
} |
|
|
|
} |
|
|
@ -6600,7 +6681,7 @@ int main(int argc, char *argv[]) |
|
|
|
enable_device(devices[i]); |
|
|
|
enable_device(devices[i]); |
|
|
|
} else if (i < total_devices) { |
|
|
|
} else if (i < total_devices) { |
|
|
|
if (opt_removedisabled) { |
|
|
|
if (opt_removedisabled) { |
|
|
|
if (devices[i]->api == &cpu_api) |
|
|
|
if (devices[i]->drv->drv == DRIVER_CPU) |
|
|
|
--opt_n_threads; |
|
|
|
--opt_n_threads; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
enable_device(devices[i]); |
|
|
|
enable_device(devices[i]); |
|
|
@ -6666,14 +6747,23 @@ int main(int argc, char *argv[]) |
|
|
|
fork_monitor(); |
|
|
|
fork_monitor(); |
|
|
|
#endif // defined(unix)
|
|
|
|
#endif // defined(unix)
|
|
|
|
|
|
|
|
|
|
|
|
total_threads = mining_threads + 7; |
|
|
|
mining_thr = calloc(mining_threads, sizeof(thr)); |
|
|
|
thr_info = calloc(total_threads, sizeof(*thr)); |
|
|
|
if (!mining_thr) |
|
|
|
if (!thr_info) |
|
|
|
quit(1, "Failed to calloc mining_thr"); |
|
|
|
quit(1, "Failed to calloc thr_info"); |
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
|
|
|
|
mining_thr[i] = calloc(1, sizeof(*thr)); |
|
|
|
|
|
|
|
if (!mining_thr[i]) |
|
|
|
|
|
|
|
quit(1, "Failed to calloc mining_thr[%d]", i); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
gwsched_thr_id = mining_threads; |
|
|
|
total_control_threads = 7; |
|
|
|
stage_thr_id = mining_threads + 1; |
|
|
|
control_thr = calloc(total_control_threads, sizeof(*thr)); |
|
|
|
thr = &thr_info[stage_thr_id]; |
|
|
|
if (!control_thr) |
|
|
|
|
|
|
|
quit(1, "Failed to calloc control_thr"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gwsched_thr_id = 0; |
|
|
|
|
|
|
|
stage_thr_id = 1; |
|
|
|
|
|
|
|
thr = &control_thr[stage_thr_id]; |
|
|
|
thr->q = tq_new(); |
|
|
|
thr->q = tq_new(); |
|
|
|
if (!thr->q) |
|
|
|
if (!thr->q) |
|
|
|
quit(1, "Failed to tq_new"); |
|
|
|
quit(1, "Failed to tq_new"); |
|
|
@ -6765,14 +6855,16 @@ begin_bench: |
|
|
|
cgpu->status = LIFE_INIT; |
|
|
|
cgpu->status = LIFE_INIT; |
|
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < cgpu->threads; ++j, ++k) { |
|
|
|
for (j = 0; j < cgpu->threads; ++j, ++k) { |
|
|
|
thr = &thr_info[k]; |
|
|
|
mutex_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
thr = mining_thr[k]; |
|
|
|
|
|
|
|
mutex_unlock(&mining_thr_lock); |
|
|
|
thr->id = k; |
|
|
|
thr->id = k; |
|
|
|
thr->cgpu = cgpu; |
|
|
|
thr->cgpu = cgpu; |
|
|
|
thr->device_thread = j; |
|
|
|
thr->device_thread = j; |
|
|
|
|
|
|
|
|
|
|
|
thr->q = tq_new(); |
|
|
|
thr->q = tq_new(); |
|
|
|
if (!thr->q) |
|
|
|
if (!thr->q) |
|
|
|
quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->api->name, cgpu->device_id, i); |
|
|
|
quit(1, "tq_new failed in starting %s%d mining thread (#%d)", cgpu->drv->name, cgpu->device_id, i); |
|
|
|
|
|
|
|
|
|
|
|
/* Enable threads for devices set not to mine but disable
|
|
|
|
/* Enable threads for devices set not to mine but disable
|
|
|
|
* their queue in case we wish to enable them later */ |
|
|
|
* their queue in case we wish to enable them later */ |
|
|
@ -6782,7 +6874,7 @@ begin_bench: |
|
|
|
tq_push(thr->q, &ping); |
|
|
|
tq_push(thr->q, &ping); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu->api->thread_prepare && !cgpu->api->thread_prepare(thr)) |
|
|
|
if (cgpu->drv->thread_prepare && !cgpu->drv->thread_prepare(thr)) |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
thread_reportout(thr); |
|
|
|
thread_reportout(thr); |
|
|
@ -6810,15 +6902,15 @@ begin_bench: |
|
|
|
gettimeofday(&total_tv_start, NULL); |
|
|
|
gettimeofday(&total_tv_start, NULL); |
|
|
|
gettimeofday(&total_tv_end, NULL); |
|
|
|
gettimeofday(&total_tv_end, NULL); |
|
|
|
|
|
|
|
|
|
|
|
watchpool_thr_id = mining_threads + 2; |
|
|
|
watchpool_thr_id = 2; |
|
|
|
thr = &thr_info[watchpool_thr_id]; |
|
|
|
thr = &control_thr[watchpool_thr_id]; |
|
|
|
/* start watchpool thread */ |
|
|
|
/* start watchpool thread */ |
|
|
|
if (thr_info_create(thr, NULL, watchpool_thread, NULL)) |
|
|
|
if (thr_info_create(thr, NULL, watchpool_thread, NULL)) |
|
|
|
quit(1, "watchpool thread create failed"); |
|
|
|
quit(1, "watchpool thread create failed"); |
|
|
|
pthread_detach(thr->pth); |
|
|
|
pthread_detach(thr->pth); |
|
|
|
|
|
|
|
|
|
|
|
watchdog_thr_id = mining_threads + 3; |
|
|
|
watchdog_thr_id = 3; |
|
|
|
thr = &thr_info[watchdog_thr_id]; |
|
|
|
thr = &control_thr[watchdog_thr_id]; |
|
|
|
/* start watchdog thread */ |
|
|
|
/* start watchdog thread */ |
|
|
|
if (thr_info_create(thr, NULL, watchdog_thread, NULL)) |
|
|
|
if (thr_info_create(thr, NULL, watchdog_thread, NULL)) |
|
|
|
quit(1, "watchdog thread create failed"); |
|
|
|
quit(1, "watchdog thread create failed"); |
|
|
@ -6826,8 +6918,8 @@ begin_bench: |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
/* Create reinit gpu thread */ |
|
|
|
/* Create reinit gpu thread */ |
|
|
|
gpur_thr_id = mining_threads + 4; |
|
|
|
gpur_thr_id = 4; |
|
|
|
thr = &thr_info[gpur_thr_id]; |
|
|
|
thr = &control_thr[gpur_thr_id]; |
|
|
|
thr->q = tq_new(); |
|
|
|
thr->q = tq_new(); |
|
|
|
if (!thr->q) |
|
|
|
if (!thr->q) |
|
|
|
quit(1, "tq_new failed for gpur_thr_id"); |
|
|
|
quit(1, "tq_new failed for gpur_thr_id"); |
|
|
@ -6836,8 +6928,8 @@ begin_bench: |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/* Create API socket thread */ |
|
|
|
/* Create API socket thread */ |
|
|
|
api_thr_id = mining_threads + 5; |
|
|
|
api_thr_id = 5; |
|
|
|
thr = &thr_info[api_thr_id]; |
|
|
|
thr = &control_thr[api_thr_id]; |
|
|
|
if (thr_info_create(thr, NULL, api_thread, thr)) |
|
|
|
if (thr_info_create(thr, NULL, api_thread, thr)) |
|
|
|
quit(1, "API thread create failed"); |
|
|
|
quit(1, "API thread create failed"); |
|
|
|
|
|
|
|
|
|
|
@ -6845,13 +6937,17 @@ begin_bench: |
|
|
|
/* Create curses input thread for keyboard input. Create this last so
|
|
|
|
/* Create curses input thread for keyboard input. Create this last so
|
|
|
|
* that we know all threads are created since this can call kill_work |
|
|
|
* that we know all threads are created since this can call kill_work |
|
|
|
* to try and shut down ll previous threads. */ |
|
|
|
* to try and shut down ll previous threads. */ |
|
|
|
input_thr_id = mining_threads + 6; |
|
|
|
input_thr_id = 6; |
|
|
|
thr = &thr_info[input_thr_id]; |
|
|
|
thr = &control_thr[input_thr_id]; |
|
|
|
if (thr_info_create(thr, NULL, input_thread, thr)) |
|
|
|
if (thr_info_create(thr, NULL, input_thread, thr)) |
|
|
|
quit(1, "input thread create failed"); |
|
|
|
quit(1, "input thread create failed"); |
|
|
|
pthread_detach(thr->pth); |
|
|
|
pthread_detach(thr->pth); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Just to be sure */ |
|
|
|
|
|
|
|
if (total_control_threads != 7) |
|
|
|
|
|
|
|
quit(1, "incorrect total_control_threads (%d) should be 7", total_control_threads); |
|
|
|
|
|
|
|
|
|
|
|
/* Once everything is set up, main() becomes the getwork scheduler */ |
|
|
|
/* Once everything is set up, main() becomes the getwork scheduler */ |
|
|
|
while (42) { |
|
|
|
while (42) { |
|
|
|
int ts, max_staged = opt_queue; |
|
|
|
int ts, max_staged = opt_queue; |
|
|
|