|
|
@ -98,8 +98,7 @@ int opt_queue = 1; |
|
|
|
int opt_scantime = 7; |
|
|
|
int opt_scantime = 7; |
|
|
|
int opt_expiry = 28; |
|
|
|
int opt_expiry = 28; |
|
|
|
|
|
|
|
|
|
|
|
char *opt_algorithm; |
|
|
|
algorithm_t *default_algorithm; |
|
|
|
algorithm_t *algorithm; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const bool opt_time = true; |
|
|
|
static const bool opt_time = true; |
|
|
|
unsigned long long global_hashrate; |
|
|
|
unsigned long long global_hashrate; |
|
|
@ -199,6 +198,11 @@ pthread_rwlock_t devices_lock; |
|
|
|
static pthread_mutex_t lp_lock; |
|
|
|
static pthread_mutex_t lp_lock; |
|
|
|
static pthread_cond_t lp_cond; |
|
|
|
static pthread_cond_t lp_cond; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static pthread_mutex_t algo_switch_lock; |
|
|
|
|
|
|
|
static int algo_switch_n = 0; |
|
|
|
|
|
|
|
static pthread_mutex_t algo_switch_wait_lock; |
|
|
|
|
|
|
|
static pthread_cond_t algo_switch_wait_cond; |
|
|
|
|
|
|
|
|
|
|
|
pthread_mutex_t restart_lock; |
|
|
|
pthread_mutex_t restart_lock; |
|
|
|
pthread_cond_t restart_cond; |
|
|
|
pthread_cond_t restart_cond; |
|
|
|
|
|
|
|
|
|
|
@ -538,6 +542,9 @@ struct pool *add_pool(void) |
|
|
|
buf[0] = '\0'; |
|
|
|
buf[0] = '\0'; |
|
|
|
pool->name = strdup(buf); |
|
|
|
pool->name = strdup(buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Algorithm */ |
|
|
|
|
|
|
|
pool->algorithm = *default_algorithm; |
|
|
|
|
|
|
|
|
|
|
|
pools = (struct pool **)realloc(pools, sizeof(struct pool *) * (total_pools + 2)); |
|
|
|
pools = (struct pool **)realloc(pools, sizeof(struct pool *) * (total_pools + 2)); |
|
|
|
pools[total_pools++] = pool; |
|
|
|
pools[total_pools++] = pool; |
|
|
|
mutex_init(&pool->pool_lock); |
|
|
|
mutex_init(&pool->pool_lock); |
|
|
@ -773,6 +780,35 @@ static char *set_url(char *arg) |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *set_pool_algorithm(char *arg) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct pool *pool; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ((json_array_index + 1) > total_pools) |
|
|
|
|
|
|
|
add_pool(); |
|
|
|
|
|
|
|
pool = pools[json_array_index]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Setting pool %i algorithm to %s", pool->pool_no, arg); |
|
|
|
|
|
|
|
set_algorithm(&pool->algorithm, arg); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static char *set_pool_nfactor(char *arg) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct pool *pool; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ((json_array_index + 1) > total_pools) |
|
|
|
|
|
|
|
add_pool(); |
|
|
|
|
|
|
|
pool = pools[json_array_index]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
applog(LOG_DEBUG, "Setting pool %i N-factor to %s", pool->pool_no, arg); |
|
|
|
|
|
|
|
set_algorithm_nfactor(&pool->algorithm, (const uint8_t) atoi(arg)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char *set_poolname(char *arg) |
|
|
|
static char *set_poolname(char *arg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct pool *pool = get_current_pool(); |
|
|
|
struct pool *pool = get_current_pool(); |
|
|
@ -1034,17 +1070,17 @@ static void load_temp_cutoffs() |
|
|
|
|
|
|
|
|
|
|
|
static char *set_algo(const char *arg) |
|
|
|
static char *set_algo(const char *arg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
set_algorithm(algorithm, arg); |
|
|
|
set_algorithm(default_algorithm, arg); |
|
|
|
applog(LOG_INFO, "Set algorithm to %s", algorithm->name); |
|
|
|
applog(LOG_INFO, "Set default algorithm to %s", default_algorithm->name); |
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char *set_nfactor(const char *arg) |
|
|
|
static char *set_nfactor(const char *arg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
set_algorithm_nfactor(algorithm, (uint8_t)atoi(arg)); |
|
|
|
set_algorithm_nfactor(default_algorithm, (const uint8_t) atoi(arg)); |
|
|
|
applog(LOG_INFO, "Set algorithm N-factor to %d (N to %d)", |
|
|
|
applog(LOG_INFO, "Set algorithm N-factor to %d (N to %d)", |
|
|
|
algorithm->nfactor, algorithm->n); |
|
|
|
default_algorithm->nfactor, default_algorithm->n); |
|
|
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
} |
|
|
|
} |
|
|
@ -1399,6 +1435,12 @@ static struct opt_table opt_config_table[] = { |
|
|
|
OPT_WITH_ARG("--url|-o", |
|
|
|
OPT_WITH_ARG("--url|-o", |
|
|
|
set_url, NULL, NULL, |
|
|
|
set_url, NULL, NULL, |
|
|
|
"URL for bitcoin JSON-RPC server"), |
|
|
|
"URL for bitcoin JSON-RPC server"), |
|
|
|
|
|
|
|
OPT_WITH_ARG("--pool-algorithm", |
|
|
|
|
|
|
|
set_pool_algorithm, NULL, NULL, |
|
|
|
|
|
|
|
"Set algorithm for pool"), |
|
|
|
|
|
|
|
OPT_WITH_ARG("--pool-nfactor", |
|
|
|
|
|
|
|
set_pool_nfactor, NULL, NULL, |
|
|
|
|
|
|
|
"Set N-factor for pool"), |
|
|
|
OPT_WITH_ARG("--user|-u", |
|
|
|
OPT_WITH_ARG("--user|-u", |
|
|
|
set_user, NULL, NULL, |
|
|
|
set_user, NULL, NULL, |
|
|
|
"Username for bitcoin JSON-RPC server"), |
|
|
|
"Username for bitcoin JSON-RPC server"), |
|
|
@ -3783,7 +3825,6 @@ void switch_pools(struct pool *selected) |
|
|
|
mutex_lock(&lp_lock); |
|
|
|
mutex_lock(&lp_lock); |
|
|
|
pthread_cond_broadcast(&lp_cond); |
|
|
|
pthread_cond_broadcast(&lp_cond); |
|
|
|
mutex_unlock(&lp_lock); |
|
|
|
mutex_unlock(&lp_lock); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void discard_work(struct work *work) |
|
|
|
void discard_work(struct work *work) |
|
|
@ -4415,8 +4456,8 @@ void write_config(FILE *fcfg) |
|
|
|
} |
|
|
|
} |
|
|
|
if (opt_removedisabled) |
|
|
|
if (opt_removedisabled) |
|
|
|
fprintf(fcfg, ",\n\"remove-disabled\" : true"); |
|
|
|
fprintf(fcfg, ",\n\"remove-disabled\" : true"); |
|
|
|
if (strcmp(algorithm->name, "scrypt") != 0) |
|
|
|
if (strcmp(default_algorithm->name, "scrypt") != 0) |
|
|
|
fprintf(fcfg, ",\n\"algorithm\" : \"%s\"", json_escape(algorithm->name)); |
|
|
|
fprintf(fcfg, ",\n\"algorithm\" : \"%s\"", json_escape(default_algorithm->name)); |
|
|
|
if (opt_api_allow) |
|
|
|
if (opt_api_allow) |
|
|
|
fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow)); |
|
|
|
fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", json_escape(opt_api_allow)); |
|
|
|
if (strcmp(opt_api_mcast_addr, API_MCAST_ADDR) != 0) |
|
|
|
if (strcmp(opt_api_mcast_addr, API_MCAST_ADDR) != 0) |
|
|
@ -5988,6 +6029,53 @@ static void gen_stratum_work(struct pool *pool, struct work *work) |
|
|
|
cgtime(&work->tv_staged); |
|
|
|
cgtime(&work->tv_staged); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void get_work_prepare_thread(struct thr_info *mythr, struct work *work) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); |
|
|
|
|
|
|
|
mutex_lock(&algo_switch_lock); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (cmp_algorithm(&work->pool->algorithm, &mythr->cgpu->algorithm) && (algo_switch_n == 0)) { |
|
|
|
|
|
|
|
mutex_unlock(&algo_switch_lock); |
|
|
|
|
|
|
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
algo_switch_n++; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If all threads are waiting now
|
|
|
|
|
|
|
|
if (algo_switch_n >= mining_threads) { |
|
|
|
|
|
|
|
rd_lock(&mining_thr_lock); |
|
|
|
|
|
|
|
// Shutdown all threads first (necessary)
|
|
|
|
|
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
|
|
|
|
struct thr_info *thr = mining_thr[i]; |
|
|
|
|
|
|
|
thr->cgpu->drv->thread_shutdown(thr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Change algorithm for each thread (thread_prepare calls initCl)
|
|
|
|
|
|
|
|
for (i = 0; i < mining_threads; i++) { |
|
|
|
|
|
|
|
struct thr_info *thr = mining_thr[i]; |
|
|
|
|
|
|
|
thr->cgpu->algorithm = work->pool->algorithm; |
|
|
|
|
|
|
|
thr->cgpu->drv->thread_prepare(thr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rd_unlock(&mining_thr_lock); |
|
|
|
|
|
|
|
algo_switch_n = 0; |
|
|
|
|
|
|
|
mutex_unlock(&algo_switch_lock); |
|
|
|
|
|
|
|
// Signal other threads to start working now
|
|
|
|
|
|
|
|
mutex_lock(&algo_switch_wait_lock); |
|
|
|
|
|
|
|
pthread_cond_broadcast(&algo_switch_wait_cond); |
|
|
|
|
|
|
|
mutex_unlock(&algo_switch_wait_lock); |
|
|
|
|
|
|
|
// Not all threads are waiting, join the waiting list
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
mutex_unlock(&algo_switch_lock); |
|
|
|
|
|
|
|
// Wait for signal to start working again
|
|
|
|
|
|
|
|
mutex_lock(&algo_switch_wait_lock); |
|
|
|
|
|
|
|
pthread_cond_wait(&algo_switch_wait_cond, &algo_switch_wait_lock); |
|
|
|
|
|
|
|
mutex_unlock(&algo_switch_wait_lock); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct work *get_work(struct thr_info *thr, const int thr_id) |
|
|
|
struct work *get_work(struct thr_info *thr, const int thr_id) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct work *work = NULL; |
|
|
|
struct work *work = NULL; |
|
|
@ -6004,6 +6092,9 @@ struct work *get_work(struct thr_info *thr, const int thr_id) |
|
|
|
wake_gws(); |
|
|
|
wake_gws(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get_work_prepare_thread(thr, work); |
|
|
|
|
|
|
|
|
|
|
|
diff_t = time(NULL) - diff_t; |
|
|
|
diff_t = time(NULL) - diff_t; |
|
|
|
/* Since this is a blocking function, we need to add grace time to
|
|
|
|
/* Since this is a blocking function, we need to add grace time to
|
|
|
|
* the device's last valid work to not make outages appear to be |
|
|
|
* the device's last valid work to not make outages appear to be |
|
|
@ -6084,7 +6175,7 @@ static void rebuild_nonce(struct work *work, uint32_t nonce) |
|
|
|
|
|
|
|
|
|
|
|
*work_nonce = htole32(nonce); |
|
|
|
*work_nonce = htole32(nonce); |
|
|
|
|
|
|
|
|
|
|
|
scrypt_regenhash(work); |
|
|
|
scrypt_regenhash(work, work->pool->algorithm.n); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* For testing a nonce against diff 1 */ |
|
|
|
/* For testing a nonce against diff 1 */ |
|
|
@ -6212,8 +6303,10 @@ static void mt_disable(struct thr_info *mythr, const int thr_id, |
|
|
|
applog(LOG_WARNING, "Thread %d being disabled", thr_id); |
|
|
|
applog(LOG_WARNING, "Thread %d being disabled", thr_id); |
|
|
|
mythr->rolling = mythr->cgpu->rolling = 0; |
|
|
|
mythr->rolling = mythr->cgpu->rolling = 0; |
|
|
|
applog(LOG_DEBUG, "Waiting on sem in miner thread"); |
|
|
|
applog(LOG_DEBUG, "Waiting on sem in miner thread"); |
|
|
|
|
|
|
|
mythr->paused = true; |
|
|
|
cgsem_wait(&mythr->sem); |
|
|
|
cgsem_wait(&mythr->sem); |
|
|
|
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); |
|
|
|
applog(LOG_WARNING, "Thread %d being re-enabled", thr_id); |
|
|
|
|
|
|
|
mythr->paused = false; |
|
|
|
drv->thread_enable(mythr); |
|
|
|
drv->thread_enable(mythr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -6230,7 +6323,7 @@ static void hash_sole_work(struct thr_info *mythr) |
|
|
|
struct sgminer_stats *pool_stats; |
|
|
|
struct sgminer_stats *pool_stats; |
|
|
|
/* Try to cycle approximately 5 times before each log update */ |
|
|
|
/* Try to cycle approximately 5 times before each log update */ |
|
|
|
const long cycle = opt_log_interval / 5 ? 5 : 1; |
|
|
|
const long cycle = opt_log_interval / 5 ? 5 : 1; |
|
|
|
const bool primary = (!mythr->device_thread) || mythr->primary_thread; |
|
|
|
const bool primary = mythr->device_thread == 0; |
|
|
|
struct timeval diff, sdiff, wdiff = {0, 0}; |
|
|
|
struct timeval diff, sdiff, wdiff = {0, 0}; |
|
|
|
uint32_t max_nonce = drv->can_limit_work(mythr); |
|
|
|
uint32_t max_nonce = drv->can_limit_work(mythr); |
|
|
|
int64_t hashes_done = 0; |
|
|
|
int64_t hashes_done = 0; |
|
|
@ -7835,6 +7928,7 @@ int main(int argc, char *argv[]) |
|
|
|
rwlock_init(&netacc_lock); |
|
|
|
rwlock_init(&netacc_lock); |
|
|
|
rwlock_init(&mining_thr_lock); |
|
|
|
rwlock_init(&mining_thr_lock); |
|
|
|
rwlock_init(&devices_lock); |
|
|
|
rwlock_init(&devices_lock); |
|
|
|
|
|
|
|
mutex_init(&algo_switch_lock); |
|
|
|
|
|
|
|
|
|
|
|
mutex_init(&lp_lock); |
|
|
|
mutex_init(&lp_lock); |
|
|
|
if (unlikely(pthread_cond_init(&lp_cond, NULL))) |
|
|
|
if (unlikely(pthread_cond_init(&lp_cond, NULL))) |
|
|
@ -7844,6 +7938,10 @@ int main(int argc, char *argv[]) |
|
|
|
if (unlikely(pthread_cond_init(&restart_cond, NULL))) |
|
|
|
if (unlikely(pthread_cond_init(&restart_cond, NULL))) |
|
|
|
quit(1, "Failed to pthread_cond_init restart_cond"); |
|
|
|
quit(1, "Failed to pthread_cond_init restart_cond"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutex_init(&algo_switch_wait_lock); |
|
|
|
|
|
|
|
if (unlikely(pthread_cond_init(&algo_switch_wait_cond, NULL))) |
|
|
|
|
|
|
|
quit(1, "Failed to pthread_cond_init algo_switch_wait_cond"); |
|
|
|
|
|
|
|
|
|
|
|
if (unlikely(pthread_cond_init(&gws_cond, NULL))) |
|
|
|
if (unlikely(pthread_cond_init(&gws_cond, NULL))) |
|
|
|
quit(1, "Failed to pthread_cond_init gws_cond"); |
|
|
|
quit(1, "Failed to pthread_cond_init gws_cond"); |
|
|
|
|
|
|
|
|
|
|
@ -7887,8 +7985,8 @@ int main(int argc, char *argv[]) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/* Default algorithm specified in algorithm.c ATM */ |
|
|
|
/* Default algorithm specified in algorithm.c ATM */ |
|
|
|
algorithm = (algorithm_t *)alloca(sizeof(algorithm_t)); |
|
|
|
default_algorithm = (algorithm_t *)alloca(sizeof(algorithm_t)); |
|
|
|
set_algorithm(algorithm, "scrypt"); |
|
|
|
set_algorithm(default_algorithm, "scrypt"); |
|
|
|
|
|
|
|
|
|
|
|
devcursor = 8; |
|
|
|
devcursor = 8; |
|
|
|
logstart = devcursor + 1; |
|
|
|
logstart = devcursor + 1; |
|
|
|