mirror of
https://github.com/GOSTSec/sgminer
synced 2025-02-08 13:04:27 +00:00
Implement a completely curses based display and don't output to stderr when log is enabled unless it's redirected away from the terminal.
This commit is contained in:
parent
f12edd2fb8
commit
90839cdf5a
@ -22,7 +22,7 @@ cgminer_SOURCES = elist.h miner.h compat.h \
|
|||||||
sha256_cryptopp.c sha256_sse2_amd64.c
|
sha256_cryptopp.c sha256_sse2_amd64.c
|
||||||
|
|
||||||
cgminer_LDFLAGS = $(PTHREAD_FLAGS)
|
cgminer_LDFLAGS = $(PTHREAD_FLAGS)
|
||||||
cgminer_LDADD = @LIBCURL@ @JANSSON_LIBS@ @PTHREAD_LIBS@ @OPENCL_LIBS@ lib/libgnu.a ccan/libccan.a
|
cgminer_LDADD = @LIBCURL@ @JANSSON_LIBS@ @PTHREAD_LIBS@ @OPENCL_LIBS@ @NCURSES_LIBS@ lib/libgnu.a ccan/libccan.a
|
||||||
cgminer_CPPFLAGS = @LIBCURL_CPPFLAGS@ -I$(top_builddir)/lib -I$(top_srcdir)/lib
|
cgminer_CPPFLAGS = @LIBCURL_CPPFLAGS@ -I$(top_builddir)/lib -I$(top_srcdir)/lib
|
||||||
|
|
||||||
if HAVE_x86_64
|
if HAVE_x86_64
|
||||||
|
1
README
1
README
@ -7,6 +7,7 @@ Dependencies:
|
|||||||
libcurl http://curl.haxx.se/libcurl/
|
libcurl http://curl.haxx.se/libcurl/
|
||||||
jansson http://www.digip.org/jansson/
|
jansson http://www.digip.org/jansson/
|
||||||
(jansson is included in-tree and an installed one may conflict)
|
(jansson is included in-tree and an installed one may conflict)
|
||||||
|
libncurses5-dev (or libpdcurses on WIN32)
|
||||||
|
|
||||||
Basic *nix build instructions:
|
Basic *nix build instructions:
|
||||||
To build with GPU mining support:
|
To build with GPU mining support:
|
||||||
|
@ -60,6 +60,7 @@ LIBS=$SAVED_LIBS
|
|||||||
|
|
||||||
AC_CHECK_LIB(jansson, json_loads, request_jansson=false, request_jansson=true)
|
AC_CHECK_LIB(jansson, json_loads, request_jansson=false, request_jansson=true)
|
||||||
AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIBS=-lpthread)
|
AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIBS=-lpthread)
|
||||||
|
AC_CHECK_LIB(ncurses, addstr, NCURSES_LIBS=-lncurses)
|
||||||
|
|
||||||
AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue])
|
AM_CONDITIONAL([WANT_JANSSON], [test x$request_jansson = xtrue])
|
||||||
AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
|
AM_CONDITIONAL([HAVE_WINDOWS], [test x$have_win32 = xtrue])
|
||||||
@ -148,6 +149,7 @@ AC_SUBST(OPENCL_LIBS)
|
|||||||
AC_SUBST(JANSSON_LIBS)
|
AC_SUBST(JANSSON_LIBS)
|
||||||
AC_SUBST(PTHREAD_FLAGS)
|
AC_SUBST(PTHREAD_FLAGS)
|
||||||
AC_SUBST(PTHREAD_LIBS)
|
AC_SUBST(PTHREAD_LIBS)
|
||||||
|
AC_SUBST(NCURSES_LIBS)
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
|
165
main.c
165
main.c
@ -28,6 +28,7 @@
|
|||||||
#include <ccan/opt/opt.h>
|
#include <ccan/opt/opt.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
#include <curses.h>
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
#include "findnonce.h"
|
#include "findnonce.h"
|
||||||
@ -507,13 +508,108 @@ err_out:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double total_secs;
|
static inline int gpu_from_thr_id(int thr_id)
|
||||||
static char statusline[256];
|
|
||||||
|
|
||||||
static inline void print_status(void)
|
|
||||||
{
|
{
|
||||||
printf("%s\r", statusline);
|
return thr_id % nDevs;
|
||||||
fflush(stdout);
|
}
|
||||||
|
|
||||||
|
static inline int cpu_from_thr_id(int thr_id)
|
||||||
|
{
|
||||||
|
return (thr_id - gpu_threads) % num_processors;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WINDOW * mainwin;
|
||||||
|
static double total_secs = 0.1;
|
||||||
|
static char statusline[256];
|
||||||
|
static int cpucursor, gpucursor, logstart, logcursor;
|
||||||
|
static bool curses_active = false;
|
||||||
|
static struct cgpu_info *gpus, *cpus;
|
||||||
|
|
||||||
|
static inline void print_status(int thr_id)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
|
||||||
|
if (unlikely(!curses_active))
|
||||||
|
return;
|
||||||
|
getyx(mainwin, logcursor, x);
|
||||||
|
|
||||||
|
move(2,0);
|
||||||
|
printw("Totals: %s", statusline);
|
||||||
|
clrtoeol();
|
||||||
|
|
||||||
|
if (thr_id && thr_id < gpu_threads) {
|
||||||
|
int gpu = gpu_from_thr_id(thr_id);
|
||||||
|
struct cgpu_info *cgpu = &gpus[gpu];
|
||||||
|
|
||||||
|
move(gpucursor + gpu, 0);
|
||||||
|
printw("GPU %d: [%.1f Mh/s] [Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.2f/m] ",
|
||||||
|
gpu, cgpu->total_mhashes / total_secs,
|
||||||
|
cgpu->getworks, cgpu->accepted, cgpu->rejected, cgpu->hw_errors,
|
||||||
|
cgpu->efficiency, cgpu->utility);
|
||||||
|
clrtoeol();
|
||||||
|
} else if (thr_id && thr_id >= gpu_threads) {
|
||||||
|
int cpu = cpu_from_thr_id(thr_id);
|
||||||
|
struct cgpu_info *cgpu = &cpus[cpu];
|
||||||
|
|
||||||
|
move(cpucursor + cpu, 0);
|
||||||
|
printw("CPU %d: [%.1f Mh/s] [Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.2f/m]",
|
||||||
|
cpu, cgpu->total_mhashes / total_secs,
|
||||||
|
cgpu->getworks, cgpu->accepted, cgpu->rejected, cgpu->hw_errors,
|
||||||
|
cgpu->efficiency, cgpu->utility);
|
||||||
|
clrtoeol();
|
||||||
|
}
|
||||||
|
|
||||||
|
move(logcursor, 0);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void refresh_display(void)
|
||||||
|
{
|
||||||
|
int i, x, maxy;
|
||||||
|
|
||||||
|
if (unlikely(!curses_active))
|
||||||
|
return;
|
||||||
|
getyx(mainwin, logcursor, x);
|
||||||
|
|
||||||
|
move(0,0);
|
||||||
|
attron(A_BOLD);
|
||||||
|
printw(PROGRAM_NAME " version " VERSION);
|
||||||
|
attroff(A_BOLD);
|
||||||
|
clrtoeol();
|
||||||
|
move(1, 0);
|
||||||
|
clrtoeol();
|
||||||
|
hline('-', 80);
|
||||||
|
move(3, 0);
|
||||||
|
clrtoeol();
|
||||||
|
hline('-', 80);
|
||||||
|
move(logstart, 0);
|
||||||
|
clrtoeol();
|
||||||
|
hline('-', 80);
|
||||||
|
move(logcursor, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < mining_threads; i++)
|
||||||
|
print_status(i);
|
||||||
|
|
||||||
|
move(logcursor, 0);
|
||||||
|
redrawwin(mainwin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_curses(const char *f, va_list ap)
|
||||||
|
{
|
||||||
|
int i, x, maxy;
|
||||||
|
|
||||||
|
if (unlikely(!curses_active))
|
||||||
|
return;
|
||||||
|
vwprintw(mainwin, f, ap);
|
||||||
|
clrtoeol();
|
||||||
|
getyx(mainwin, logcursor, x);
|
||||||
|
|
||||||
|
/* Scroll log output downwards */
|
||||||
|
getmaxyx(mainwin, maxy, x);
|
||||||
|
if (logcursor >= maxy - 1)
|
||||||
|
refresh_display();
|
||||||
|
else
|
||||||
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool submit_fail = false;
|
static bool submit_fail = false;
|
||||||
@ -526,7 +622,6 @@ static bool submit_upstream_work(const struct work *work)
|
|||||||
bool rc = false;
|
bool rc = false;
|
||||||
struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu;
|
struct cgpu_info *cgpu = thr_info[work->thr_id].cgpu;
|
||||||
CURL *curl = curl_easy_init();
|
CURL *curl = curl_easy_init();
|
||||||
double utility, efficiency;
|
|
||||||
|
|
||||||
if (unlikely(!curl)) {
|
if (unlikely(!curl)) {
|
||||||
applog(LOG_ERR, "CURL initialisation failed");
|
applog(LOG_ERR, "CURL initialisation failed");
|
||||||
@ -573,29 +668,26 @@ static bool submit_upstream_work(const struct work *work)
|
|||||||
if (opt_debug)
|
if (opt_debug)
|
||||||
applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
|
applog(LOG_DEBUG, "PROOF OF WORK RESULT: true (yay!!!)");
|
||||||
if (!opt_quiet)
|
if (!opt_quiet)
|
||||||
printf("[Accepted] ");
|
applog(LOG_WARNING, "Share accepted from %sPU %d",
|
||||||
|
cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu);
|
||||||
} else {
|
} else {
|
||||||
cgpu->rejected++;
|
cgpu->rejected++;
|
||||||
rejected++;
|
rejected++;
|
||||||
if (opt_debug)
|
if (opt_debug)
|
||||||
applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)");
|
applog(LOG_DEBUG, "PROOF OF WORK RESULT: false (booooo)");
|
||||||
if (!opt_quiet)
|
if (!opt_quiet)
|
||||||
printf("[Rejected] ");
|
applog(LOG_WARNING, "Share rejected from %sPU %d",
|
||||||
|
cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
|
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
|
||||||
efficiency = cgpu->getworks ? cgpu->accepted * 100.0 / cgpu->getworks : 0.0;
|
cgpu->efficiency = cgpu->getworks ? cgpu->accepted * 100.0 / cgpu->getworks : 0.0;
|
||||||
|
|
||||||
if (!opt_quiet) {
|
if (!opt_quiet)
|
||||||
printf("[%sPU %d] [%.1f Mh/s] [Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.2f/m] \n",
|
print_status(work->thr_id);
|
||||||
cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, cgpu->total_mhashes / total_secs,
|
|
||||||
cgpu->getworks, cgpu->accepted, cgpu->rejected, cgpu->hw_errors,
|
|
||||||
efficiency, utility);
|
|
||||||
print_status();
|
|
||||||
}
|
|
||||||
applog(LOG_INFO, "%sPU %d Requested:%d Accepted:%d Rejected:%d HW errors:%d Efficiency:%.0f%% Utility:%.2f/m",
|
applog(LOG_INFO, "%sPU %d Requested:%d Accepted:%d Rejected:%d HW errors:%d Efficiency:%.0f%% Utility:%.2f/m",
|
||||||
cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, cgpu->getworks, cgpu->accepted, cgpu->rejected, cgpu->hw_errors, efficiency, utility
|
cgpu->is_gpu? "G" : "C", cgpu->cpu_gpu, cgpu->getworks, cgpu->accepted,
|
||||||
);
|
cgpu->rejected, cgpu->hw_errors, cgpu->efficiency, cgpu->utility);
|
||||||
|
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
|
|
||||||
@ -960,7 +1052,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
|
|||||||
sprintf(statusline, "[(%ds):%.1f (avg):%.1f Mh/s] [Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.2f/m] ",
|
sprintf(statusline, "[(%ds):%.1f (avg):%.1f Mh/s] [Q:%d A:%d R:%d HW:%d E:%.0f%% U:%.2f/m] ",
|
||||||
opt_log_interval, rolling_local / local_secs, total_mhashes_done / total_secs,
|
opt_log_interval, rolling_local / local_secs, total_mhashes_done / total_secs,
|
||||||
getwork_requested, accepted, rejected, hw_errors, efficiency, utility);
|
getwork_requested, accepted, rejected, hw_errors, efficiency, utility);
|
||||||
print_status();
|
print_status(thr_id);
|
||||||
applog(LOG_INFO, "[Rate (%ds):%.1f (avg):%.2f Mhash/s] [Requested:%d Accepted:%d Rejected:%d HW errors:%d Efficiency:%.0f%% Utility:%.2f/m]",
|
applog(LOG_INFO, "[Rate (%ds):%.1f (avg):%.2f Mhash/s] [Requested:%d Accepted:%d Rejected:%d HW errors:%d Efficiency:%.0f%% Utility:%.2f/m]",
|
||||||
opt_log_interval, rolling_local / local_secs, total_mhashes_done / total_secs,
|
opt_log_interval, rolling_local / local_secs, total_mhashes_done / total_secs,
|
||||||
getwork_requested, accepted, rejected, hw_errors, efficiency, utility);
|
getwork_requested, accepted, rejected, hw_errors, efficiency, utility);
|
||||||
@ -1183,11 +1275,6 @@ bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce)
|
|||||||
return submit_work_sync(thr, work);
|
return submit_work_sync(thr, work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cpu_from_thr_id(int thr_id)
|
|
||||||
{
|
|
||||||
return (thr_id - gpu_threads) % num_processors;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *miner_thread(void *userdata)
|
static void *miner_thread(void *userdata)
|
||||||
{
|
{
|
||||||
struct thr_info *mythr = userdata;
|
struct thr_info *mythr = userdata;
|
||||||
@ -1404,11 +1491,6 @@ static inline cl_int queue_kernel_parameters(_clState *clState, dev_blk_ctx *blk
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int gpu_from_thr_id(int thr_id)
|
|
||||||
{
|
|
||||||
return thr_id % nDevs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *gpuminer_thread(void *userdata)
|
static void *gpuminer_thread(void *userdata)
|
||||||
{
|
{
|
||||||
const unsigned long cycle = opt_log_interval / 5 ? : 1;
|
const unsigned long cycle = opt_log_interval / 5 ? : 1;
|
||||||
@ -1661,7 +1743,6 @@ int main (int argc, char *argv[])
|
|||||||
struct thr_info *thr;
|
struct thr_info *thr;
|
||||||
unsigned int i, j = 0;
|
unsigned int i, j = 0;
|
||||||
char name[32];
|
char name[32];
|
||||||
struct cgpu_info *gpus = NULL, *cpus = NULL;
|
|
||||||
|
|
||||||
if (unlikely(pthread_mutex_init(&time_lock, NULL)))
|
if (unlikely(pthread_mutex_init(&time_lock, NULL)))
|
||||||
return 1;
|
return 1;
|
||||||
@ -1726,7 +1807,12 @@ int main (int argc, char *argv[])
|
|||||||
opt_n_threads = num_processors;
|
opt_n_threads = num_processors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logcursor = 4;
|
||||||
mining_threads = opt_n_threads + gpu_threads;
|
mining_threads = opt_n_threads + gpu_threads;
|
||||||
|
gpucursor = logcursor;
|
||||||
|
cpucursor = gpucursor + total_devices + 1;
|
||||||
|
logstart = cpucursor + (opt_n_threads ? num_processors : 0);
|
||||||
|
logcursor = logstart + 1;
|
||||||
|
|
||||||
if (!rpc_userpass) {
|
if (!rpc_userpass) {
|
||||||
if (!rpc_user || !rpc_pass) {
|
if (!rpc_user || !rpc_pass) {
|
||||||
@ -1907,6 +1993,17 @@ int main (int argc, char *argv[])
|
|||||||
total_mhashes_done = 0;
|
total_mhashes_done = 0;
|
||||||
pthread_mutex_unlock(&hash_lock);
|
pthread_mutex_unlock(&hash_lock);
|
||||||
|
|
||||||
|
/* Set up the ncurses interface */
|
||||||
|
if ((mainwin = initscr()) == NULL) {
|
||||||
|
applog(LOG_ERR, "Failed to initscr");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
idlok(mainwin, true);
|
||||||
|
scrollok(mainwin, true);
|
||||||
|
curses_active = true;
|
||||||
|
move(logcursor, 0);
|
||||||
|
refresh_display();
|
||||||
|
|
||||||
/* 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);
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
@ -1917,6 +2014,10 @@ int main (int argc, char *argv[])
|
|||||||
|
|
||||||
applog(LOG_INFO, "workio thread dead, exiting.");
|
applog(LOG_INFO, "workio thread dead, exiting.");
|
||||||
|
|
||||||
|
delwin(mainwin);
|
||||||
|
endwin();
|
||||||
|
refresh();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
miner.h
3
miner.h
@ -135,6 +135,8 @@ struct cgpu_info {
|
|||||||
double local_mhashes;
|
double local_mhashes;
|
||||||
double total_mhashes;
|
double total_mhashes;
|
||||||
unsigned int getworks;
|
unsigned int getworks;
|
||||||
|
double efficiency;
|
||||||
|
double utility;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thr_info {
|
struct thr_info {
|
||||||
@ -267,6 +269,7 @@ struct work {
|
|||||||
|
|
||||||
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
|
bool submit_nonce(struct thr_info *thr, struct work *work, uint32_t nonce);
|
||||||
|
|
||||||
|
extern void log_curses(const char *f, va_list ap);
|
||||||
extern void vapplog(int prio, const char *fmt, va_list ap);
|
extern void vapplog(int prio, const char *fmt, va_list ap);
|
||||||
extern void applog(int prio, const char *fmt, ...);
|
extern void applog(int prio, const char *fmt, ...);
|
||||||
extern struct thread_q *tq_new(void);
|
extern struct thread_q *tq_new(void);
|
||||||
|
20
util.c
20
util.c
@ -20,6 +20,7 @@
|
|||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <curses.h>
|
||||||
#include "miner.h"
|
#include "miner.h"
|
||||||
#include "elist.h"
|
#include "elist.h"
|
||||||
|
|
||||||
@ -68,7 +69,7 @@ void vapplog(int prio, const char *fmt, va_list ap)
|
|||||||
#endif
|
#endif
|
||||||
else if (opt_log_output || prio == LOG_WARNING || prio == LOG_ERR) {
|
else if (opt_log_output || prio == LOG_WARNING || prio == LOG_ERR) {
|
||||||
char *f;
|
char *f;
|
||||||
int len, i, extra = 0;
|
int len;
|
||||||
struct timeval tv = { };
|
struct timeval tv = { };
|
||||||
struct tm tm, *tm_p;
|
struct tm tm, *tm_p;
|
||||||
|
|
||||||
@ -80,10 +81,8 @@ void vapplog(int prio, const char *fmt, va_list ap)
|
|||||||
pthread_mutex_unlock(&time_lock);
|
pthread_mutex_unlock(&time_lock);
|
||||||
|
|
||||||
len = 40 + strlen(fmt) + 2;
|
len = 40 + strlen(fmt) + 2;
|
||||||
if (len < 80)
|
f = alloca(len);
|
||||||
extra = 80 - len;
|
sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d] %s\n",
|
||||||
f = alloca(len + extra);
|
|
||||||
sprintf(f, "[%d-%02d-%02d %02d:%02d:%02d] %s",
|
|
||||||
tm.tm_year + 1900,
|
tm.tm_year + 1900,
|
||||||
tm.tm_mon + 1,
|
tm.tm_mon + 1,
|
||||||
tm.tm_mday,
|
tm.tm_mday,
|
||||||
@ -91,11 +90,12 @@ void vapplog(int prio, const char *fmt, va_list ap)
|
|||||||
tm.tm_min,
|
tm.tm_min,
|
||||||
tm.tm_sec,
|
tm.tm_sec,
|
||||||
fmt);
|
fmt);
|
||||||
vfprintf(stderr, f, ap); /* atomic write to stderr */
|
/* Only output to stderr if it's not going to the screen as well */
|
||||||
for (i = 0; i < extra; i++)
|
if (opt_log_output && !isatty(fileno((FILE *)stderr))) {
|
||||||
fprintf(stderr, " ");
|
vfprintf(stderr, f, ap); /* atomic write to stderr */
|
||||||
fprintf(stderr, "\n");
|
fflush(stderr);
|
||||||
fflush(stderr);
|
}
|
||||||
|
log_curses(f, ap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user