|
|
@ -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; |
|
|
@ -377,7 +378,7 @@ 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; |
|
|
|
cgpu = mining_thr[thr_id]->cgpu; |
|
|
|
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)); |
|
|
@ -1722,7 +1723,7 @@ out: |
|
|
|
|
|
|
|
|
|
|
|
int dev_from_id(int thr_id) |
|
|
|
int dev_from_id(int thr_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return thr_info[thr_id].cgpu->device_id; |
|
|
|
return mining_thr[thr_id]->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
|
|
|
@ -1894,7 +1895,7 @@ static void get_statline(char *buf, struct cgpu_info *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 = mining_thr[thr_id]->cgpu; |
|
|
|
char logline[256]; |
|
|
|
char logline[256]; |
|
|
|
|
|
|
|
|
|
|
|
if (cgpu) { |
|
|
|
if (cgpu) { |
|
|
@ -1960,7 +1961,7 @@ 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 = mining_thr[thr_id]->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; |
|
|
@ -2212,7 +2213,7 @@ 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 = mining_thr[work->thr_id]->cgpu; |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
@ -2362,7 +2363,7 @@ 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 = mining_thr[thr_id]->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; |
|
|
@ -2744,18 +2745,18 @@ 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]; |
|
|
|
thr = mining_thr[i]; |
|
|
|
thr_info_freeze(thr); |
|
|
|
thr_info_freeze(thr); |
|
|
|
thr->pause = true; |
|
|
|
thr->pause = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -2765,17 +2766,17 @@ 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]; |
|
|
|
thr = mining_thr[i]; |
|
|
|
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,7 +3370,7 @@ static void restart_threads(void) |
|
|
|
discard_stale(); |
|
|
|
discard_stale(); |
|
|
|
|
|
|
|
|
|
|
|
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_lock(&restart_lock); |
|
|
|
mutex_lock(&restart_lock); |
|
|
|
pthread_cond_broadcast(&restart_cond); |
|
|
|
pthread_cond_broadcast(&restart_cond); |
|
|
@ -4409,16 +4410,16 @@ static void hashmeter(int thr_id, struct timeval *diff, |
|
|
|
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); |
|
|
|
gettimeofday(&(mining_thr[thr_id]->last), NULL); |
|
|
|
thr_info[thr_id].cgpu->device_last_well = time(NULL); |
|
|
|
mining_thr[thr_id]->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 thr_info *thr = mining_thr[thr_id]; |
|
|
|
struct cgpu_info *cgpu = thr_info[thr_id].cgpu; |
|
|
|
struct cgpu_info *cgpu = thr->cgpu; |
|
|
|
double thread_rolling = 0.0; |
|
|
|
double thread_rolling = 0.0; |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
@ -4908,7 +4909,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; |
|
|
@ -5858,7 +5859,7 @@ static void *watchdog_thread(void __maybe_unused *userdata) |
|
|
|
sched_paused = true; |
|
|
|
sched_paused = true; |
|
|
|
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]; |
|
|
|
thr = mining_thr[i]; |
|
|
|
|
|
|
|
|
|
|
|
thr->pause = true; |
|
|
|
thr->pause = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -5872,7 +5873,7 @@ 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]; |
|
|
|
thr = mining_thr[i]; |
|
|
|
|
|
|
|
|
|
|
|
/* Don't touch disabled devices */ |
|
|
|
/* Don't touch disabled devices */ |
|
|
|
if (thr->cgpu->deven == DEV_DISABLED) |
|
|
|
if (thr->cgpu->deven == DEV_DISABLED) |
|
|
@ -6709,14 +6710,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"); |
|
|
@ -6808,7 +6818,7 @@ 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]; |
|
|
|
thr = mining_thr[k]; |
|
|
|
thr->id = k; |
|
|
|
thr->id = k; |
|
|
|
thr->cgpu = cgpu; |
|
|
|
thr->cgpu = cgpu; |
|
|
|
thr->device_thread = j; |
|
|
|
thr->device_thread = j; |
|
|
@ -6853,15 +6863,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"); |
|
|
@ -6869,8 +6879,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"); |
|
|
@ -6879,8 +6889,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"); |
|
|
|
|
|
|
|
|
|
|
@ -6888,13 +6898,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; |
|
|
|