diff --git a/cgminer.c b/cgminer.c index 11153a1e..20fee0cc 100644 --- a/cgminer.c +++ b/cgminer.c @@ -1367,6 +1367,40 @@ static void calc_midstate(struct work *work) #endif } +static struct work *make_work(void) +{ + struct work *work = calloc(1, sizeof(struct work)); + + if (unlikely(!work)) + quit(1, "Failed to calloc work in make_work"); + mutex_lock(&control_lock); + work->id = total_work++; + mutex_unlock(&control_lock); + return work; +} + +/* This is the central place all work that is about to be retired should be + * cleaned to remove any dynamically allocated arrays within the struct */ +void clean_work(struct work *work) +{ + free(work->job_id); + free(work->nonce2); + free(work->ntime); + free(work->gbt_coinbase); + work->job_id = NULL; + work->nonce2 = NULL; + work->ntime = NULL; + work->gbt_coinbase = NULL; +} + +/* All dynamically allocated work structs should be freed here to not leak any + * ram from arrays allocated within the work struct */ +void free_work(struct work *work) +{ + clean_work(work); + free(work); +} + /* Generate a GBT coinbase from the existing GBT variables stored. Must be * entered under gbt_lock */ static void __build_gbt_coinbase(struct pool *pool) @@ -1477,10 +1511,52 @@ static unsigned char *__gbt_merkleroot(struct pool *pool) } static void calc_diff(struct work *work, int known); +static bool work_decode(struct pool *pool, struct work *work, json_t *val); + +static void update_gbt(struct pool *pool) +{ + int rolltime; + json_t *val; + CURL *curl; + + curl = curl_easy_init(); + if (unlikely(!curl)) + quit (1, "CURL initialisation failed in update_gbt"); + + val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, + pool->rpc_req, true, false, &rolltime, pool, false); + + if (val) { + struct work *work = make_work(); + bool rc = work_decode(pool, work, val); + + total_getworks++; + pool->getwork_requested++; + if (rc) { + applog(LOG_DEBUG, "Successfully retrieved and updated GBT from pool %u %s", + pool->pool_no, pool->rpc_url); + gettimeofday(&pool->tv_idle, NULL); + } else { + applog(LOG_DEBUG, "Successfully retrieved but FAILED to decipher GBT from pool %u %s", + pool->pool_no, pool->rpc_url); + } + json_decref(val); + free_work(work); + } else { + applog(LOG_DEBUG, "FAILED to update GBT from pool %u %s", + pool->pool_no, pool->rpc_url); + } + curl_easy_cleanup(curl); +} static void gen_gbt_work(struct pool *pool, struct work *work) { unsigned char *merkleroot; + struct timeval now; + + gettimeofday(&now, NULL); + if (now.tv_sec - pool->tv_lastwork.tv_sec > 60) + update_gbt(pool); mutex_lock(&pool->gbt_lock); __build_gbt_coinbase(pool); @@ -2646,40 +2722,6 @@ static bool get_upstream_work(struct work *work, CURL *curl) return rc; } -static struct work *make_work(void) -{ - struct work *work = calloc(1, sizeof(struct work)); - - if (unlikely(!work)) - quit(1, "Failed to calloc work in make_work"); - mutex_lock(&control_lock); - work->id = total_work++; - mutex_unlock(&control_lock); - return work; -} - -/* This is the central place all work that is about to be retired should be - * cleaned to remove any dynamically allocated arrays within the struct */ -void clean_work(struct work *work) -{ - free(work->job_id); - free(work->nonce2); - free(work->ntime); - free(work->gbt_coinbase); - work->job_id = NULL; - work->nonce2 = NULL; - work->ntime = NULL; - work->gbt_coinbase = NULL; -} - -/* All dynamically allocated work structs should be freed here to not leak any - * ram from arrays allocated within the work struct */ -void free_work(struct work *work) -{ - clean_work(work); - free(work); -} - static void workio_cmd_free(struct workio_cmd *wc) { if (!wc) @@ -5785,7 +5827,7 @@ static struct pool *select_longpoll_pool(struct pool *cp) */ static void wait_lpcurrent(struct pool *pool) { - if (pool->enabled == POOL_REJECTING || pool_strategy == POOL_LOADBALANCE || pool_strategy == POOL_BALANCE) + if (cnx_needed(pool)) return; while (pool != current_pool() && pool_strategy != POOL_LOADBALANCE && pool_strategy != POOL_BALANCE) { @@ -5953,48 +5995,6 @@ static void reap_curl(struct pool *pool) applog(LOG_DEBUG, "Reaped %d curl%s from pool %d", reaped, reaped > 1 ? "s" : "", pool->pool_no); } -static bool pool_getswork(struct pool *pool) -{ - bool ret = false; - int rolltime; - json_t *val; - CURL *curl; - - curl = curl_easy_init(); - if (unlikely(!curl)) - quit (1, "CURL initialisation failed in pool_getswork"); - - val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, - pool->rpc_req, true, false, &rolltime, pool, false); - - if (val) { - struct work *work = make_work(); - bool rc = work_decode(pool, work, val); - - if (pool->has_gbt && pool == current_pool()) { - total_getworks++; - pool->getwork_requested++; - } - if (rc) { - applog(LOG_DEBUG, "Successfully retrieved and deciphered work from pool %u %s", - pool->pool_no, pool->rpc_url); - gettimeofday(&pool->tv_idle, NULL); - ret = true; - } else { - applog(LOG_DEBUG, "Successfully retrieved but FAILED to decipher work from pool %u %s", - pool->pool_no, pool->rpc_url); - } - json_decref(val); - free_work(work); - } else { - applog(LOG_DEBUG, "FAILED to retrieve pool_getswork work from pool %u %s", - pool->pool_no, pool->rpc_url); - } - curl_easy_cleanup(curl); - - return ret; -} - static void *watchpool_thread(void __maybe_unused *userdata) { int intervals = 0; @@ -6020,16 +6020,6 @@ static void *watchpool_thread(void __maybe_unused *userdata) if (pool->enabled == POOL_DISABLED || pool->has_stratum) continue; - /* Stratum works off pushing work, but GBT and getwork - * off requests so even for the non current pool, get - * new work once per minute to ensure the pool is still - * alive and to maintain the current block template for - * GBT pools in case we switch to them. */ - if (!pool->idle && now.tv_sec - pool->tv_lastwork.tv_sec > 60) { - if (!pool_getswork(pool)) - pool_died(pool); - } - /* Test pool is idle once every minute */ if (pool->idle && now.tv_sec - pool->tv_idle.tv_sec > 30) { gettimeofday(&pool->tv_idle, NULL);