|
@@ -167,6 +167,8 @@ static int work_thr_id;
|
|
|
int longpoll_thr_id;
|
|
int longpoll_thr_id;
|
|
|
static int stage_thr_id;
|
|
static int stage_thr_id;
|
|
|
static int watchdog_thr_id;
|
|
static int watchdog_thr_id;
|
|
|
|
|
+static int input_thr_id;
|
|
|
|
|
+static int total_threads;
|
|
|
|
|
|
|
|
struct work_restart *work_restart = NULL;
|
|
struct work_restart *work_restart = NULL;
|
|
|
|
|
|
|
@@ -794,6 +796,14 @@ void log_curses(const char *f, va_list ap)
|
|
|
vprintf(f, ap);
|
|
vprintf(f, ap);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void clear_logwin(void)
|
|
|
|
|
+{
|
|
|
|
|
+ pthread_mutex_lock(&curses_lock);
|
|
|
|
|
+ wclear(logwin);
|
|
|
|
|
+ wrefresh(logwin);
|
|
|
|
|
+ pthread_mutex_unlock(&curses_lock);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static bool submit_upstream_work(const struct work *work)
|
|
static bool submit_upstream_work(const struct work *work)
|
|
|
{
|
|
{
|
|
|
char *hexstr = NULL;
|
|
char *hexstr = NULL;
|
|
@@ -1316,6 +1326,45 @@ static void *stage_thread(void *userdata)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static void *input_thread(void *userdata)
|
|
|
|
|
+{
|
|
|
|
|
+ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ if (!curses_active)
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+
|
|
|
|
|
+ while (1) {
|
|
|
|
|
+ char input;
|
|
|
|
|
+
|
|
|
|
|
+ input = getch();
|
|
|
|
|
+ if (!strncasecmp(&input, "q", 1)) {
|
|
|
|
|
+ kill_work();
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+ } else if (!strncasecmp(&input, "s", 1)) {
|
|
|
|
|
+ opt_quiet ^= true;
|
|
|
|
|
+ applog(LOG_WARNING, "Silent mode %s", opt_quiet ? "enabled" : "disabled");
|
|
|
|
|
+ } else if (!strncasecmp(&input, "v", 1)) {
|
|
|
|
|
+ opt_log_output ^= true;
|
|
|
|
|
+ applog(LOG_WARNING, "Verbose mode %s", opt_log_output ? "enabled" : "disabled");
|
|
|
|
|
+ } else if (!strncasecmp(&input, "n", 1)) {
|
|
|
|
|
+ opt_log_output = true;
|
|
|
|
|
+ opt_debug = false;
|
|
|
|
|
+ opt_quiet = false;
|
|
|
|
|
+ opt_protocol = false;
|
|
|
|
|
+ applog(LOG_WARNING, "Output mode reset to normal");
|
|
|
|
|
+ } else if (!strncasecmp(&input, "d", 1)) {
|
|
|
|
|
+ opt_debug ^= true;
|
|
|
|
|
+ applog(LOG_WARNING, "Debug mode %s", opt_debug ? "enabled" : "disabled");
|
|
|
|
|
+ } else if (!strncasecmp(&input, "r", 1)) {
|
|
|
|
|
+ opt_protocol ^= true;
|
|
|
|
|
+ applog(LOG_WARNING, "RPC protocl debugging %s", opt_protocol ? "enabled" : "disabled");
|
|
|
|
|
+ } else if (!strncasecmp(&input, "c", 1))
|
|
|
|
|
+ clear_logwin();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void *workio_thread(void *userdata)
|
|
static void *workio_thread(void *userdata)
|
|
|
{
|
|
{
|
|
|
struct thr_info *mythr = userdata;
|
|
struct thr_info *mythr = userdata;
|
|
@@ -2710,6 +2759,7 @@ int main (int argc, char *argv[])
|
|
|
scrollok(logwin, true);
|
|
scrollok(logwin, true);
|
|
|
leaveok(logwin, true);
|
|
leaveok(logwin, true);
|
|
|
cbreak();
|
|
cbreak();
|
|
|
|
|
+ noecho();
|
|
|
test_and_set(&curses_active);
|
|
test_and_set(&curses_active);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2749,11 +2799,13 @@ int main (int argc, char *argv[])
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
mining_threads = opt_n_threads + gpu_threads;
|
|
mining_threads = opt_n_threads + gpu_threads;
|
|
|
- work_restart = calloc(mining_threads + 4, sizeof(*work_restart));
|
|
|
|
|
|
|
+
|
|
|
|
|
+ total_threads = mining_threads + 5;
|
|
|
|
|
+ work_restart = calloc(total_threads, sizeof(*work_restart));
|
|
|
if (!work_restart)
|
|
if (!work_restart)
|
|
|
quit(1, "Failed to calloc work_restart");
|
|
quit(1, "Failed to calloc work_restart");
|
|
|
|
|
|
|
|
- thr_info = calloc(mining_threads + 4, sizeof(*thr));
|
|
|
|
|
|
|
+ thr_info = calloc(total_threads, sizeof(*thr));
|
|
|
if (!thr_info)
|
|
if (!thr_info)
|
|
|
quit(1, "Failed to calloc thr_info");
|
|
quit(1, "Failed to calloc thr_info");
|
|
|
|
|
|
|
@@ -2804,6 +2856,7 @@ int main (int argc, char *argv[])
|
|
|
/* start stage thread */
|
|
/* start stage thread */
|
|
|
if (pthread_create(&thr->pth, NULL, stage_thread, thr))
|
|
if (pthread_create(&thr->pth, NULL, stage_thread, thr))
|
|
|
quit(1, "stage thread create failed");
|
|
quit(1, "stage thread create failed");
|
|
|
|
|
+ pthread_detach(thr->pth);
|
|
|
|
|
|
|
|
/* Flag the work as ready forcing the mining threads to wait till we
|
|
/* Flag the work as ready forcing the mining threads to wait till we
|
|
|
* actually put something into the queue */
|
|
* actually put something into the queue */
|
|
@@ -2926,6 +2979,13 @@ int main (int argc, char *argv[])
|
|
|
print_status(i);
|
|
print_status(i);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /* Create curses input thread for keyboard input */
|
|
|
|
|
+ input_thr_id = mining_threads + 4;
|
|
|
|
|
+ thr = &thr_info[input_thr_id];
|
|
|
|
|
+ if (pthread_create(&thr->pth, NULL, input_thread, thr))
|
|
|
|
|
+ quit(1, "input thread create failed");
|
|
|
|
|
+ pthread_detach(thr->pth);
|
|
|
|
|
+
|
|
|
/* main loop - simply wait for workio thread to exit */
|
|
/* main loop - simply wait for workio thread to exit */
|
|
|
pthread_join(thr_info[work_thr_id].pth, NULL);
|
|
pthread_join(thr_info[work_thr_id].pth, NULL);
|
|
|
applog(LOG_INFO, "workio thread dead, exiting.");
|
|
applog(LOG_INFO, "workio thread dead, exiting.");
|