Browse Source

Make a separate thread for work submission that returns immediately so that miner threads aren't kept waiting when submitting results to slow pools.

nfactor-troky
Con Kolivas 13 years ago
parent
commit
b7a177532d
  1. 88
      cpu-miner.c

88
cpu-miner.c

@ -326,20 +326,12 @@ err_out:
return false; return false;
} }
static bool submit_upstream_work(CURL *curl, const struct work *work) static bool submit_upstream_work(CURL *curl, char *hexstr)
{ {
char *hexstr = NULL;
json_t *val, *res; json_t *val, *res;
char s[345]; char s[345];
bool rc = false; bool rc = false;
/* build hex string */
hexstr = bin2hex(work->data, sizeof(work->data));
if (unlikely(!hexstr)) {
applog(LOG_ERR, "submit_upstream_work OOM");
goto out;
}
/* build JSON-RPC request */ /* build JSON-RPC request */
sprintf(s, sprintf(s,
"{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n", "{\"method\": \"getwork\", \"params\": [ \"%s\" ], \"id\":1}\r\n",
@ -357,6 +349,9 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
res = json_object_get(val, "result"); res = json_object_get(val, "result");
/* Theoretically threads could race when modifying accepted and
* rejected values but the chance of two submits completing at the
* same time is zero so there is no point adding extra locking */
if (json_is_true(res)) { if (json_is_true(res)) {
accepted++; accepted++;
applog(LOG_INFO, "PROOF OF WORK RESULT: true (yay!!!)"); applog(LOG_INFO, "PROOF OF WORK RESULT: true (yay!!!)");
@ -370,7 +365,6 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
rc = true; rc = true;
out: out:
free(hexstr);
return rc; return rc;
} }
@ -411,21 +405,29 @@ static void workio_cmd_free(struct workio_cmd *wc)
free(wc); free(wc);
} }
static bool workio_get_work(struct workio_cmd *wc, CURL *curl) static bool workio_get_work(struct workio_cmd *wc)
{ {
struct work *ret_work; struct work *ret_work;
int failures = 0; int failures = 0;
bool ret = false;
CURL *curl;
ret_work = calloc(1, sizeof(*ret_work)); ret_work = calloc(1, sizeof(*ret_work));
if (!ret_work) if (!ret_work)
return false; goto out;
curl = curl_easy_init();
if (unlikely(!curl)) {
applog(LOG_ERR, "CURL initialization failed");
return ret;
}
/* obtain new work from bitcoin via JSON-RPC */ /* obtain new work from bitcoin via JSON-RPC */
while (!get_upstream_work(curl, ret_work)) { while (!get_upstream_work(curl, ret_work)) {
if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) { if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
applog(LOG_ERR, "json_rpc_call failed, terminating workio thread"); applog(LOG_ERR, "json_rpc_call failed, terminating workio thread");
free(ret_work); free(ret_work);
return false; goto out;
} }
/* pause, then restart work-request loop */ /* pause, then restart work-request loop */
@ -434,22 +436,33 @@ static bool workio_get_work(struct workio_cmd *wc, CURL *curl)
sleep(opt_fail_pause); sleep(opt_fail_pause);
} }
ret = true;
/* send work to requesting thread */ /* send work to requesting thread */
if (!tq_push(wc->thr->q, ret_work)) if (!tq_push(wc->thr->q, ret_work))
free(ret_work); free(ret_work);
return true; out:
curl_easy_cleanup(curl);
return ret;
} }
static bool workio_submit_work(struct workio_cmd *wc, CURL *curl) static void *submit_thread(void *userdata)
{ {
char *hexstr = (char *)userdata;
int failures = 0; int failures = 0;
CURL *curl;
curl = curl_easy_init();
if (unlikely(!curl)) {
applog(LOG_ERR, "CURL initialization failed");
return NULL;
}
/* submit solution to bitcoin via JSON-RPC */ /* submit solution to bitcoin via JSON-RPC */
while (!submit_upstream_work(curl, wc->u.work)) { while (!submit_upstream_work(curl, hexstr)) {
if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) { if (unlikely((opt_retries >= 0) && (++failures > opt_retries))) {
applog(LOG_ERR, "...terminating workio thread"); applog(LOG_ERR, "...terminating workio thread");
return false; exit (1);
} }
/* pause, then restart work-request loop */ /* pause, then restart work-request loop */
@ -458,21 +471,43 @@ static bool workio_submit_work(struct workio_cmd *wc, CURL *curl)
sleep(opt_fail_pause); sleep(opt_fail_pause);
} }
free(hexstr);
out:
curl_easy_cleanup(curl);
}
/* Work is submitted asynchronously by creating a thread for each submit
* thus avoiding the mining threads having to wait till work is submitted
* before they can continue working. */
static bool workio_submit_work(struct workio_cmd *wc)
{
struct work *work;
pthread_t thr;
char *hexstr;
pid_t child;
work = wc->u.work;
/* build hex string */
hexstr = bin2hex(work->data, sizeof(work->data));
if (unlikely(!hexstr)) {
applog(LOG_ERR, "workio_submit_work OOM");
return false;
}
if (pthread_create(&thr, NULL, submit_thread, (void *)hexstr)) {
applog(LOG_ERR, "Failed to create submit_thread");
return false;
}
return true; return true;
} }
static void *workio_thread(void *userdata) static void *workio_thread(void *userdata)
{ {
struct thr_info *mythr = userdata; struct thr_info *mythr = userdata;
CURL *curl;
bool ok = true; bool ok = true;
curl = curl_easy_init();
if (unlikely(!curl)) {
applog(LOG_ERR, "CURL initialization failed");
return NULL;
}
while (ok) { while (ok) {
struct workio_cmd *wc; struct workio_cmd *wc;
@ -486,10 +521,10 @@ static void *workio_thread(void *userdata)
/* process workio_cmd */ /* process workio_cmd */
switch (wc->cmd) { switch (wc->cmd) {
case WC_GET_WORK: case WC_GET_WORK:
ok = workio_get_work(wc, curl); ok = workio_get_work(wc);
break; break;
case WC_SUBMIT_WORK: case WC_SUBMIT_WORK:
ok = workio_submit_work(wc, curl); ok = workio_submit_work(wc);
break; break;
default: /* should never happen */ default: /* should never happen */
@ -501,7 +536,6 @@ static void *workio_thread(void *userdata)
} }
tq_freeze(mythr->q); tq_freeze(mythr->q);
curl_easy_cleanup(curl);
return NULL; return NULL;
} }

Loading…
Cancel
Save