1
0
mirror of https://github.com/GOSTSec/sgminer synced 2025-01-09 14:28:12 +00:00

Merge pull request #2 from veox/forward-port

Forward-port relevant changes up to ckolivas/cgminer 3.10.0
This commit is contained in:
Noel Maersk 2014-01-15 04:43:24 -08:00
commit 909af927c3
9 changed files with 205 additions and 78 deletions

View File

@ -1,16 +1,16 @@
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
JANSSON_INCLUDES= -I$(top_builddir)/compat/jansson-2.5/src -I$(top_srcdir)/compat/jansson-2.5/src JANSSON_CPPFLAGS= -I$(top_builddir)/compat/jansson-2.5/src -I$(top_srcdir)/compat/jansson-2.5/src
EXTRA_DIST = example.conf m4/gnulib-cache.m4 linux-usb-cgminer \ EXTRA_DIST = example.conf m4/gnulib-cache.m4 \
ADL_SDK/readme.txt api-example.php miner.php \ ADL_SDK/readme.txt api-example.php miner.php \
API.class API.java api-example.c windows-build.txt \ API.class API.java api-example.c windows-build.txt \
API-README SCRYPT-README hexdump.c GPU-README API-README SCRYPT-README hexdump.c GPU-README
SUBDIRS = lib compat ccan SUBDIRS = lib compat ccan
INCLUDES = $(PTHREAD_FLAGS) -fno-strict-aliasing $(JANSSON_INCLUDES) INCLUDES = $(PTHREAD_FLAGS) -fno-strict-aliasing $(JANSSON_CPPFLAGS)
bin_PROGRAMS = cgminer bin_PROGRAMS = cgminer
@ -19,10 +19,10 @@ cgminer_LDADD = $(DLOPEN_FLAGS) @LIBCURL_LIBS@ @JANSSON_LIBS@ @PTHREAD_LIBS@ \
@OPENCL_LIBS@ @NCURSES_LIBS@ @PDCURSES_LIBS@ @WS2_LIBS@ \ @OPENCL_LIBS@ @NCURSES_LIBS@ @PDCURSES_LIBS@ @WS2_LIBS@ \
@MM_LIBS@ @RT_LIBS@ @MATH_LIBS@ lib/libgnu.a ccan/libccan.a @MM_LIBS@ @RT_LIBS@ @MATH_LIBS@ lib/libgnu.a ccan/libccan.a
if HAVE_WINDOWS cgminer_CPPFLAGS += -I$(top_builddir)/lib -I$(top_srcdir)/lib @OPENCL_FLAGS@
cgminer_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib @OPENCL_FLAGS@
else if !HAVE_WINDOWS
cgminer_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib @OPENCL_FLAGS@ @LIBCURL_CFLAGS@ cgminer_CPPFLAGS += @LIBCURL_CFLAGS@
endif endif
cgminer_CPPFLAGS += $(ADL_CPPFLAGS) cgminer_CPPFLAGS += $(ADL_CPPFLAGS)

View File

@ -8,7 +8,7 @@
*/ */
/* Compile: /* Compile:
* gcc api-example.c -Icompat/jansson -Icompat/libusb-1.0/libusb -o cgminer-api * gcc api-example.c -Icompat/jansson-2.5 -Icompat/libusb-1.0/libusb -o cgminer-api
*/ */
#include "config.h" #include "config.h"

33
api.c
View File

@ -587,6 +587,7 @@ static void io_free()
do { do {
io_next = io_list->next; io_next = io_list->next;
free(io_list->io_data->ptr);
free(io_list->io_data); free(io_list->io_data);
free(io_list); free(io_list);
@ -1392,10 +1393,14 @@ uint64_t api_trylock(void *lock, const char *file, const char *func, const int l
LOCKINFO *info; LOCKINFO *info;
uint64_t id; uint64_t id;
locklock();
info = findlock(lock, CGLOCK_UNKNOWN, file, func, linenum); info = findlock(lock, CGLOCK_UNKNOWN, file, func, linenum);
id = lock_id++; id = lock_id++;
addgettry(info, id, file, func, linenum, false); addgettry(info, id, file, func, linenum, false);
lockunlock();
return id; return id;
} }
@ -3559,7 +3564,7 @@ static void mcast()
count++; count++;
came_from_siz = sizeof(came_from); came_from_siz = sizeof(came_from);
if (SOCKETFAIL(rep = recvfrom(mcast_sock, buf, sizeof(buf), if (SOCKETFAIL(rep = recvfrom(mcast_sock, buf, sizeof(buf) - 1,
0, (struct sockaddr *)(&came_from), &came_from_siz))) { 0, (struct sockaddr *)(&came_from), &came_from_siz))) {
applog(LOG_DEBUG, "API mcast failed count=%d (%s) (%d)", applog(LOG_DEBUG, "API mcast failed count=%d (%s) (%d)",
count, SOCKERRMSG, (int)mcast_sock); count, SOCKERRMSG, (int)mcast_sock);
@ -3663,12 +3668,12 @@ void api(int api_thr_id)
struct sockaddr_in cli; struct sockaddr_in cli;
socklen_t clisiz; socklen_t clisiz;
char cmdbuf[100]; char cmdbuf[100];
char *cmd; char *cmd = NULL;
char *param; char *param;
bool addrok; bool addrok;
char group; char group;
json_error_t json_err; json_error_t json_err;
json_t *json_config; json_t *json_config = NULL;
json_t *json_val; json_t *json_val;
bool isjson; bool isjson;
bool did; bool did;
@ -3681,6 +3686,7 @@ void api(int api_thr_id)
if (!opt_api_listen) { if (!opt_api_listen) {
applog(LOG_DEBUG, "API not running%s", UNAVAILABLE); applog(LOG_DEBUG, "API not running%s", UNAVAILABLE);
free(apisock);
return; return;
} }
@ -3698,6 +3704,7 @@ void api(int api_thr_id)
if (ips == 0) { if (ips == 0) {
applog(LOG_WARNING, "API not running (no valid IPs specified)%s", UNAVAILABLE); applog(LOG_WARNING, "API not running (no valid IPs specified)%s", UNAVAILABLE);
free(apisock);
return; return;
} }
} }
@ -3709,6 +3716,7 @@ void api(int api_thr_id)
*apisock = socket(AF_INET, SOCK_STREAM, 0); *apisock = socket(AF_INET, SOCK_STREAM, 0);
if (*apisock == INVSOCK) { if (*apisock == INVSOCK) {
applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
free(apisock);
return; return;
} }
@ -3720,6 +3728,7 @@ void api(int api_thr_id)
serv.sin_addr.s_addr = inet_addr(localaddr); serv.sin_addr.s_addr = inet_addr(localaddr);
if (serv.sin_addr.s_addr == (in_addr_t)INVINETADDR) { if (serv.sin_addr.s_addr == (in_addr_t)INVINETADDR) {
applog(LOG_ERR, "API2 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); applog(LOG_ERR, "API2 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
free(apisock);
return; return;
} }
} }
@ -3758,12 +3767,14 @@ void api(int api_thr_id)
if (bound == 0) { if (bound == 0) {
applog(LOG_ERR, "API bind to port %d failed (%s)%s", port, binderror, UNAVAILABLE); applog(LOG_ERR, "API bind to port %d failed (%s)%s", port, binderror, UNAVAILABLE);
free(apisock);
return; return;
} }
if (SOCKETFAIL(listen(*apisock, QUEUE))) { if (SOCKETFAIL(listen(*apisock, QUEUE))) {
applog(LOG_ERR, "API3 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE); applog(LOG_ERR, "API3 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
CLOSESOCKET(*apisock); CLOSESOCKET(*apisock);
free(apisock);
return; return;
} }
@ -3837,21 +3848,18 @@ void api(int api_thr_id)
message(io_data, MSG_INVJSON, 0, NULL, isjson); message(io_data, MSG_INVJSON, 0, NULL, isjson);
send_result(io_data, c, isjson); send_result(io_data, c, isjson);
did = true; did = true;
} } else {
else {
json_val = json_object_get(json_config, JSON_COMMAND); json_val = json_object_get(json_config, JSON_COMMAND);
if (json_val == NULL) { if (json_val == NULL) {
message(io_data, MSG_MISCMD, 0, NULL, isjson); message(io_data, MSG_MISCMD, 0, NULL, isjson);
send_result(io_data, c, isjson); send_result(io_data, c, isjson);
did = true; did = true;
} } else {
else {
if (!json_is_string(json_val)) { if (!json_is_string(json_val)) {
message(io_data, MSG_INVCMD, 0, NULL, isjson); message(io_data, MSG_INVCMD, 0, NULL, isjson);
send_result(io_data, c, isjson); send_result(io_data, c, isjson);
did = true; did = true;
} } else {
else {
cmd = (char *)json_string_value(json_val); cmd = (char *)json_string_value(json_val);
json_val = json_object_get(json_config, JSON_PARAMETER); json_val = json_object_get(json_config, JSON_PARAMETER);
if (json_is_string(json_val)) if (json_is_string(json_val))
@ -3868,7 +3876,7 @@ void api(int api_thr_id)
} }
} }
if (!did) if (!did) {
for (i = 0; cmds[i].name != NULL; i++) { for (i = 0; cmds[i].name != NULL; i++) {
if (strcmp(cmd, cmds[i].name) == 0) { if (strcmp(cmd, cmds[i].name) == 0) {
sprintf(cmdbuf, "|%s|", cmd); sprintf(cmdbuf, "|%s|", cmd);
@ -3884,11 +3892,14 @@ void api(int api_thr_id)
break; break;
} }
} }
}
if (!did) { if (!did) {
message(io_data, MSG_INVCMD, 0, NULL, isjson); message(io_data, MSG_INVCMD, 0, NULL, isjson);
send_result(io_data, c, isjson); send_result(io_data, c, isjson);
} }
if (isjson && json_is_object(json_config))
json_decref(json_config);
} }
} }
CLOSESOCKET(c); CLOSESOCKET(c);
@ -3900,6 +3911,8 @@ die:
; ;
pthread_cleanup_pop(true); pthread_cleanup_pop(true);
free(apisock);
if (opt_debug) if (opt_debug)
applog(LOG_DEBUG, "API: terminating due to: %s", applog(LOG_DEBUG, "API: terminating due to: %s",
do_a_quit ? "QUIT" : (do_a_restart ? "RESTART" : (bye ? "BYE" : "UNKNOWN!"))); do_a_quit ? "QUIT" : (do_a_restart ? "RESTART" : (bye ? "BYE" : "UNKNOWN!")));

194
cgminer.c
View File

@ -1615,13 +1615,15 @@ static void gen_gbt_work(struct pool *pool, struct work *work)
{ {
unsigned char *merkleroot; unsigned char *merkleroot;
struct timeval now; struct timeval now;
uint64_t nonce2le;
cgtime(&now); cgtime(&now);
if (now.tv_sec - pool->tv_lastwork.tv_sec > 60) if (now.tv_sec - pool->tv_lastwork.tv_sec > 60)
update_gbt(pool); update_gbt(pool);
cg_wlock(&pool->gbt_lock); cg_wlock(&pool->gbt_lock);
memcpy(pool->coinbase + pool->nonce2_offset, &pool->nonce2, 4); nonce2le = htole64(pool->nonce2);
memcpy(pool->coinbase + pool->nonce2_offset, &nonce2le, pool->n2size);
pool->nonce2++; pool->nonce2++;
cg_dwlock(&pool->gbt_lock); cg_dwlock(&pool->gbt_lock);
merkleroot = __gbt_merkleroot(pool); merkleroot = __gbt_merkleroot(pool);
@ -1720,8 +1722,9 @@ static bool gbt_decode(struct pool *pool, json_t *res_val)
free(pool->coinbasetxn); free(pool->coinbasetxn);
pool->coinbasetxn = strdup(coinbasetxn); pool->coinbasetxn = strdup(coinbasetxn);
cbt_len = strlen(pool->coinbasetxn) / 2; cbt_len = strlen(pool->coinbasetxn) / 2;
pool->coinbase_len = cbt_len + 4; /* We add 8 bytes of extra data corresponding to nonce2 */
/* We add 4 bytes of extra data corresponding to nonce2 of stratum */ pool->n2size = 8;
pool->coinbase_len = cbt_len + pool->n2size;
cal_len = pool->coinbase_len + 1; cal_len = pool->coinbase_len + 1;
align_len(&cal_len); align_len(&cal_len);
free(pool->coinbase); free(pool->coinbase);
@ -1732,7 +1735,7 @@ static bool gbt_decode(struct pool *pool, json_t *res_val)
extra_len = (uint8_t *)(pool->coinbase + 41); extra_len = (uint8_t *)(pool->coinbase + 41);
orig_len = *extra_len; orig_len = *extra_len;
hex2bin(pool->coinbase + 42, pool->coinbasetxn + 84, orig_len); hex2bin(pool->coinbase + 42, pool->coinbasetxn + 84, orig_len);
*extra_len += 4; *extra_len += pool->n2size;
hex2bin(pool->coinbase + 42 + *extra_len, pool->coinbasetxn + 84 + (orig_len * 2), hex2bin(pool->coinbase + 42 + *extra_len, pool->coinbasetxn + 84 + (orig_len * 2),
cbt_len - orig_len - 42); cbt_len - orig_len - 42);
pool->nonce2_offset = orig_len + 42; pool->nonce2_offset = orig_len + 42;
@ -3350,6 +3353,17 @@ static void _copy_work(struct work *work, const struct work *base_work, int noff
work->coinbase = strdup(base_work->coinbase); work->coinbase = strdup(base_work->coinbase);
} }
void set_work_ntime(struct work *work, int ntime)
{
uint32_t *work_ntime = (uint32_t *)(work->data + 68);
*work_ntime = htobe32(ntime);
if (work->ntime) {
free(work->ntime);
work->ntime = bin2hex((unsigned char *)work_ntime, 4);
}
}
/* Generates a copy of an existing work struct, creating fresh heap allocations /* Generates a copy of an existing work struct, creating fresh heap allocations
* for all dynamically allocated arrays within the struct. noffset is used for * for all dynamically allocated arrays within the struct. noffset is used for
* when a driver has internally rolled the ntime, noffset is a relative value. * when a driver has internally rolled the ntime, noffset is a relative value.
@ -3660,11 +3674,13 @@ int restart_wait(struct thr_info *thr, unsigned int mstime)
static void flush_queue(struct cgpu_info *cgpu); static void flush_queue(struct cgpu_info *cgpu);
static void restart_threads(void) static void *restart_thread(void __maybe_unused *arg)
{ {
struct pool *cp = current_pool(); struct pool *cp = current_pool();
struct cgpu_info *cgpu; struct cgpu_info *cgpu;
int i; int i, mt;
pthread_detach(pthread_self());
/* Artificially set the lagging flag to avoid pool not providing work /* Artificially set the lagging flag to avoid pool not providing work
* fast enough messages after every long poll */ * fast enough messages after every long poll */
@ -3674,19 +3690,35 @@ static void restart_threads(void)
discard_stale(); discard_stale();
rd_lock(&mining_thr_lock); rd_lock(&mining_thr_lock);
for (i = 0; i < mining_threads; i++) { mt = mining_threads;
rd_unlock(&mining_thr_lock);
for (i = 0; i < mt; i++) {
cgpu = mining_thr[i]->cgpu; cgpu = mining_thr[i]->cgpu;
if (unlikely(!cgpu)) if (unlikely(!cgpu))
continue; continue;
if (cgpu->deven != DEV_ENABLED)
continue;
mining_thr[i]->work_restart = true; mining_thr[i]->work_restart = true;
flush_queue(cgpu); flush_queue(cgpu);
cgpu->drv->flush_work(cgpu); cgpu->drv->flush_work(cgpu);
} }
rd_unlock(&mining_thr_lock);
mutex_lock(&restart_lock); mutex_lock(&restart_lock);
pthread_cond_broadcast(&restart_cond); pthread_cond_broadcast(&restart_cond);
mutex_unlock(&restart_lock); mutex_unlock(&restart_lock);
return NULL;
}
/* In order to prevent a deadlock via the various drv->flush_work
* implementations we send the restart messages via a separate thread. */
static void restart_threads(void)
{
pthread_t rthread;
if (unlikely(pthread_create(&rthread, NULL, restart_thread, NULL)))
quit(1, "Failed to create restart thread");
} }
static void signal_work_update(void) static void signal_work_update(void)
@ -4299,6 +4331,30 @@ void zero_stats(void)
} }
} }
static void set_highprio(void)
{
#ifndef WIN32
int ret = nice(-10);
if (!ret)
applog(LOG_DEBUG, "Unable to set thread to high priority");
#else
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
#endif
}
static void set_lowprio(void)
{
#ifndef WIN32
int ret = nice(10);
if (!ret)
applog(LOG_INFO, "Unable to set thread to low priority");
#else
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST);
#endif
}
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
static void display_pools(void) static void display_pools(void)
{ {
@ -4706,6 +4762,7 @@ static void *api_thread(void *userdata)
RenameThread("api"); RenameThread("api");
set_lowprio();
api(api_thr_id); api(api_thr_id);
PTH(mythr) = 0L; PTH(mythr) = 0L;
@ -5195,10 +5252,11 @@ static void *stratum_sthread(void *userdata)
quit(1, "Failed to create stratum_q in stratum_sthread"); quit(1, "Failed to create stratum_q in stratum_sthread");
while (42) { while (42) {
char noncehex[12], nonce2hex[20]; char noncehex[12], nonce2hex[20], s[1024];
struct stratum_share *sshare; struct stratum_share *sshare;
uint32_t *hash32, nonce; uint32_t *hash32, nonce;
char s[1024], nonce2[8]; unsigned char nonce2[8];
uint64_t *nonce2_64;
struct work *work; struct work *work;
bool submitted; bool submitted;
@ -5233,10 +5291,9 @@ static void *stratum_sthread(void *userdata)
sshare->id = swork_id++; sshare->id = swork_id++;
mutex_unlock(&sshare_lock); mutex_unlock(&sshare_lock);
memset(nonce2, 0, 8); nonce2_64 = (uint64_t *)nonce2;
/* We only use uint32_t sized nonce2 increments internally */ *nonce2_64 = htole64(work->nonce2);
memcpy(nonce2, &work->nonce2, sizeof(uint32_t)); __bin2hex(nonce2hex, nonce2, work->nonce2_len);
__bin2hex(nonce2hex, (const unsigned char *)nonce2, work->nonce2_len);
snprintf(s, sizeof(s), snprintf(s, sizeof(s),
"{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}", "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
@ -5368,7 +5425,7 @@ retry_stratum:
} }
/* Probe for GBT support on first pass */ /* Probe for GBT support on first pass */
if (!pool->probed && !opt_fix_protocol) { if (!pool->probed) {
applog(LOG_DEBUG, "Probing for GBT support"); applog(LOG_DEBUG, "Probing for GBT support");
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass,
gbt_req, true, false, &rolltime, pool, false); gbt_req, true, false, &rolltime, pool, false);
@ -5641,12 +5698,15 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
{ {
unsigned char merkle_root[32], merkle_sha[64]; unsigned char merkle_root[32], merkle_sha[64];
uint32_t *data32, *swap32; uint32_t *data32, *swap32;
uint64_t nonce2le;
int i; int i;
cg_wlock(&pool->data_lock); cg_wlock(&pool->data_lock);
/* Update coinbase */ /* Update coinbase. Always use an LE encoded nonce2 to fill in values
memcpy(pool->coinbase + pool->nonce2_offset, &pool->nonce2, sizeof(uint32_t)); * from left to right and prevent overflow errors with small n2sizes */
nonce2le = htole64(pool->nonce2);
memcpy(pool->coinbase + pool->nonce2_offset, &nonce2le, pool->n2size);
work->nonce2 = pool->nonce2++; work->nonce2 = pool->nonce2++;
work->nonce2_len = pool->n2size; work->nonce2_len = pool->n2size;
@ -5686,7 +5746,8 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
merkle_hash = bin2hex((const unsigned char *)merkle_root, 32); merkle_hash = bin2hex((const unsigned char *)merkle_root, 32);
applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash); applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash);
applog(LOG_DEBUG, "Generated stratum header %s", header); applog(LOG_DEBUG, "Generated stratum header %s", header);
applog(LOG_DEBUG, "Work job_id %s nonce2 %d ntime %s", work->job_id, work->nonce2, work->ntime); applog(LOG_DEBUG, "Work job_id %s nonce2 %"PRIu64" ntime %s", work->job_id,
work->nonce2, work->ntime);
free(header); free(header);
free(merkle_hash); free(merkle_hash);
} }
@ -6197,6 +6258,30 @@ void __work_completed(struct cgpu_info *cgpu, struct work *work)
cgpu->queued_count--; cgpu->queued_count--;
HASH_DEL(cgpu->queued_work, work); HASH_DEL(cgpu->queued_work, work);
} }
/* This iterates over a queued hashlist finding work started more than secs
* seconds ago and discards the work as completed. The driver must set the
* work->tv_work_start value appropriately. Returns the number of items aged. */
int age_queued_work(struct cgpu_info *cgpu, double secs)
{
struct work *work, *tmp;
struct timeval tv_now;
int aged = 0;
cgtime(&tv_now);
wr_lock(&cgpu->qlock);
HASH_ITER(hh, cgpu->queued_work, work, tmp) {
if (tdiff(&tv_now, &work->tv_work_start) > secs) {
__work_completed(cgpu, work);
aged++;
}
}
wr_unlock(&cgpu->qlock);
return aged;
}
/* This function should be used by queued device drivers when they're sure /* This function should be used by queued device drivers when they're sure
* the work struct is no longer in use. */ * the work struct is no longer in use. */
void work_completed(struct cgpu_info *cgpu, struct work *work) void work_completed(struct cgpu_info *cgpu, struct work *work)
@ -6368,6 +6453,7 @@ void *miner_thread(void *userdata)
applog(LOG_DEBUG, "Waiting on sem in miner thread"); applog(LOG_DEBUG, "Waiting on sem in miner thread");
cgsem_wait(&mythr->sem); cgsem_wait(&mythr->sem);
set_highprio();
drv->hash_work(mythr); drv->hash_work(mythr);
out: out:
drv->thread_shutdown(mythr); drv->thread_shutdown(mythr);
@ -6646,6 +6732,8 @@ static void *watchpool_thread(void __maybe_unused *userdata)
RenameThread("watchpool"); RenameThread("watchpool");
set_lowprio();
while (42) { while (42) {
struct timeval now; struct timeval now;
int i; int i;
@ -6729,6 +6817,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
RenameThread("watchdog"); RenameThread("watchdog");
set_lowprio();
memset(&zero_tv, 0, sizeof(struct timeval)); memset(&zero_tv, 0, sizeof(struct timeval));
cgtime(&rotate_tv); cgtime(&rotate_tv);
@ -7719,6 +7808,37 @@ int main(int argc, char *argv[])
quit(1, "Failed to calloc mining_thr[%d]", i); quit(1, "Failed to calloc mining_thr[%d]", i);
} }
// Start threads
k = 0;
for (i = 0; i < total_devices; ++i) {
struct cgpu_info *cgpu = devices[i];
cgpu->thr = malloc(sizeof(*cgpu->thr) * (cgpu->threads+1));
cgpu->thr[cgpu->threads] = NULL;
cgpu->status = LIFE_INIT;
for (j = 0; j < cgpu->threads; ++j, ++k) {
thr = get_thread(k);
thr->id = k;
thr->cgpu = cgpu;
thr->device_thread = j;
if (!cgpu->drv->thread_prepare(thr))
continue;
if (unlikely(thr_info_create(thr, NULL, miner_thread, thr)))
quit(1, "thread %d create failed", thr->id);
cgpu->thr[j] = thr;
/* Enable threads for devices set not to mine but disable
* their queue in case we wish to enable them later */
if (cgpu->deven != DEV_DISABLED) {
applog(LOG_DEBUG, "Pushing sem post to thread %d", thr->id);
cgsem_post(&thr->sem);
}
}
}
if (opt_benchmark) if (opt_benchmark)
goto begin_bench; goto begin_bench;
@ -7776,44 +7896,6 @@ begin_bench:
cgtime(&total_tv_end); cgtime(&total_tv_end);
get_datestamp(datestamp, sizeof(datestamp), &total_tv_start); get_datestamp(datestamp, sizeof(datestamp), &total_tv_start);
// Start threads
k = 0;
for (i = 0; i < total_devices; ++i) {
struct cgpu_info *cgpu = devices[i];
cgpu->thr = malloc(sizeof(*cgpu->thr) * (cgpu->threads+1));
cgpu->thr[cgpu->threads] = NULL;
cgpu->status = LIFE_INIT;
for (j = 0; j < cgpu->threads; ++j, ++k) {
thr = get_thread(k);
thr->id = k;
thr->cgpu = cgpu;
thr->device_thread = j;
if (!cgpu->drv->thread_prepare(thr))
continue;
if (unlikely(thr_info_create(thr, NULL, miner_thread, thr)))
quit(1, "thread %d create failed", thr->id);
cgpu->thr[j] = thr;
/* Enable threads for devices set not to mine but disable
* their queue in case we wish to enable them later */
if (cgpu->deven != DEV_DISABLED) {
applog(LOG_DEBUG, "Pushing sem post to thread %d", thr->id);
cgsem_post(&thr->sem);
}
}
}
applog(LOG_INFO, "%d gpu miner threads started", gpu_threads);
for (i = 0; i < nDevs; i++)
pause_dynamic_threads(i);
cgtime(&total_tv_start);
cgtime(&total_tv_end);
watchpool_thr_id = 2; watchpool_thr_id = 2;
thr = &control_thr[watchpool_thr_id]; thr = &control_thr[watchpool_thr_id];
/* start watchpool thread */ /* start watchpool thread */

View File

@ -4,6 +4,7 @@ AC_INIT([jansson], [2.5], [petri@digip.org])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.10 foreign]) AM_INIT_AUTOMAKE([1.10 foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_SRCDIR([src/value.c]) AC_CONFIG_SRCDIR([src/value.c])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])

View File

@ -1234,7 +1234,7 @@ struct pool {
char *nonce1; char *nonce1;
unsigned char *nonce1bin; unsigned char *nonce1bin;
size_t n1_len; size_t n1_len;
uint32_t nonce2; uint64_t nonce2;
int n2size; int n2size;
char *sessionid; char *sessionid;
bool has_stratum; bool has_stratum;
@ -1311,7 +1311,7 @@ struct work {
bool stratum; bool stratum;
char *job_id; char *job_id;
uint32_t nonce2; uint64_t nonce2;
size_t nonce2_len; size_t nonce2_len;
char *ntime; char *ntime;
double sdiff; double sdiff;
@ -1368,6 +1368,7 @@ extern struct work *__find_work_bymidstate(struct work *que, char *midstate, siz
extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen); extern struct work *find_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
extern struct work *clone_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen); extern struct work *clone_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
extern void __work_completed(struct cgpu_info *cgpu, struct work *work); extern void __work_completed(struct cgpu_info *cgpu, struct work *work);
extern int age_queued_work(struct cgpu_info *cgpu, double secs);
extern void work_completed(struct cgpu_info *cgpu, struct work *work); extern void work_completed(struct cgpu_info *cgpu, struct work *work);
extern struct work *take_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen); extern struct work *take_queued_work_bymidstate(struct cgpu_info *cgpu, char *midstate, size_t midstatelen, char *data, int offset, size_t datalen);
extern void hash_driver_work(struct thr_info *mythr); extern void hash_driver_work(struct thr_info *mythr);
@ -1399,6 +1400,7 @@ extern void adl(void);
extern void app_restart(void); extern void app_restart(void);
extern void clean_work(struct work *work); extern void clean_work(struct work *work);
extern void free_work(struct work *work); extern void free_work(struct work *work);
extern void set_work_ntime(struct work *work, int ntime);
extern struct work *copy_work_noffset(struct work *base_work, int noffset); extern struct work *copy_work_noffset(struct work *base_work, int noffset);
#define copy_work(work_in) copy_work_noffset(work_in, 0) #define copy_work(work_in) copy_work_noffset(work_in, 0)
extern struct thr_info *get_thread(int thr_id); extern struct thr_info *get_thread(int thr_id);

View File

@ -2910,7 +2910,7 @@ function display()
if ($allowcustompages === true) if ($allowcustompages === true)
{ {
$pg = trim(getparam('pg', true)); $pg = urlencode(trim(getparam('pg', true)));
if ($pagesonly === true) if ($pagesonly === true)
{ {
if ($pg !== null && $pg !== '') if ($pg !== null && $pg !== '')

30
util.c
View File

@ -1837,7 +1837,7 @@ bool auth_stratum(struct pool *pool)
ss = json_dumps(err_val, JSON_INDENT(3)); ss = json_dumps(err_val, JSON_INDENT(3));
else else
ss = strdup("(unknown reason)"); ss = strdup("(unknown reason)");
applog(LOG_WARNING, "pool %d JSON stratum auth failed: %s", pool->pool_no, ss); applog(LOG_INFO, "pool %d JSON stratum auth failed: %s", pool->pool_no, ss);
free(ss); free(ss);
goto out; goto out;
@ -2599,6 +2599,25 @@ int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, co
/* We don't reach here */ /* We don't reach here */
return 0; return 0;
} }
/* Reset semaphore count back to zero */
void cgsem_reset(cgsem_t *cgsem)
{
int ret, fd;
fd_set rd;
char buf;
fd = cgsem->pipefd[0];
FD_ZERO(&rd);
FD_SET(fd, &rd);
do {
struct timeval timeout = {0, 0};
ret = select(fd + 1, &rd, NULL, NULL, &timeout);
if (ret > 0)
ret = read(fd, &buf, 1);
} while (ret > 0);
}
#else #else
void _cgsem_init(cgsem_t *cgsem, const char *file, const char *func, const int line) void _cgsem_init(cgsem_t *cgsem, const char *file, const char *func, const int line)
{ {
@ -2639,6 +2658,15 @@ int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, co
return 0; return 0;
} }
void cgsem_reset(cgsem_t *cgsem)
{
int ret;
do {
ret = sem_trywait(cgsem);
} while (!ret);
}
void cgsem_destroy(cgsem_t *cgsem) void cgsem_destroy(cgsem_t *cgsem)
{ {
sem_destroy(cgsem); sem_destroy(cgsem);

1
util.h
View File

@ -138,6 +138,7 @@ 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_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); 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); int _cgsem_mswait(cgsem_t *cgsem, int ms, const char *file, const char *func, const int line);
void cgsem_reset(cgsem_t *cgsem);
void cgsem_destroy(cgsem_t *cgsem); void cgsem_destroy(cgsem_t *cgsem);
bool cg_completion_timeout(void *fn, void *fnarg, int timeout); bool cg_completion_timeout(void *fn, void *fnarg, int timeout);