@ -98,8 +98,7 @@ int opt_queue = 1;
@@ -98,8 +98,7 @@ int opt_queue = 1;
int opt_scantime = 7 ;
int opt_expiry = 28 ;
char * opt_algorithm ;
algorithm_t * algorithm ;
algorithm_t * default_algorithm ;
static const bool opt_time = true ;
unsigned long long global_hashrate ;
@ -199,6 +198,9 @@ pthread_rwlock_t devices_lock;
@@ -199,6 +198,9 @@ pthread_rwlock_t devices_lock;
static pthread_mutex_t lp_lock ;
static pthread_cond_t lp_cond ;
static pthread_mutex_t algo_switch_lock ;
static pthread_t algo_switch_thr = 0 ;
pthread_mutex_t restart_lock ;
pthread_cond_t restart_cond ;
@ -536,6 +538,9 @@ struct pool *add_pool(void)
@@ -536,6 +538,9 @@ struct pool *add_pool(void)
buf [ 0 ] = ' \0 ' ;
pool - > name = strdup ( buf ) ;
/* Algorithm */
pool - > algorithm = * default_algorithm ;
pools = ( struct pool * * ) realloc ( pools , sizeof ( struct pool * ) * ( total_pools + 2 ) ) ;
pools [ total_pools + + ] = pool ;
mutex_init ( & pool - > pool_lock ) ;
@ -559,7 +564,7 @@ struct pool *add_pool(void)
@@ -559,7 +564,7 @@ struct pool *add_pool(void)
return pool ;
}
static struct pool * get_current_pool ( )
static struct pool * get_current_pool ( )
{
while ( ( json_array_index + 1 ) > total_pools )
add_pool ( ) ;
@ -569,8 +574,8 @@ static struct pool* get_current_pool()
@@ -569,8 +574,8 @@ static struct pool* get_current_pool()
add_pool ( ) ;
return pools [ total_pools - 1 ] ;
}
return pools [ json_array_index ] ;
return pools [ json_array_index ] ;
}
/* Pool variant of test and set */
@ -769,10 +774,39 @@ static char *set_url(char *arg)
@@ -769,10 +774,39 @@ static char *set_url(char *arg)
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 )
{
struct pool * pool = get_current_pool ( ) ;
applog ( LOG_DEBUG , " Setting pool %i name to %s " , pool - > pool_no , arg ) ;
opt_set_charp ( arg , & pool - > name ) ;
@ -1030,17 +1064,17 @@ static void load_temp_cutoffs()
@@ -1030,17 +1064,17 @@ static void load_temp_cutoffs()
static char * set_algo ( const char * arg )
{
set_algorithm ( algorithm , arg ) ;
applog ( LOG_INFO , " Set algorithm to %s " , algorithm - > name ) ;
set_algorithm ( default_ algorithm, arg ) ;
applog ( LOG_INFO , " Set default algorithm to %s " , default_ algorithm- > name ) ;
return NULL ;
}
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) " ,
algorithm - > nfactor , algorithm - > n ) ;
default_ algorithm- > nfactor , default_ algorithm- > n ) ;
return NULL ;
}
@ -1392,6 +1426,12 @@ static struct opt_table opt_config_table[] = {
@@ -1392,6 +1426,12 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_ARG ( " --url|-o " ,
set_url , NULL , NULL ,
" 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 " ,
set_user , NULL , NULL ,
" Username for bitcoin JSON-RPC server " ) ,
@ -3779,7 +3819,6 @@ void switch_pools(struct pool *selected)
@@ -3779,7 +3819,6 @@ void switch_pools(struct pool *selected)
mutex_lock ( & lp_lock ) ;
pthread_cond_broadcast ( & lp_cond ) ;
mutex_unlock ( & lp_lock ) ;
}
void discard_work ( struct work * work )
@ -4411,8 +4450,8 @@ void write_config(FILE *fcfg)
@@ -4411,8 +4450,8 @@ void write_config(FILE *fcfg)
}
if ( opt_removedisabled )
fprintf ( fcfg , " , \n \" remove-disabled \" : true " ) ;
if ( strcmp ( algorithm - > name , " scrypt " ) ! = 0 )
fprintf ( fcfg , " , \n \" algorithm \" : \" %s \" " , json_escape ( algorithm - > name ) ) ;
if ( strcmp ( default_ algorithm- > name , " scrypt " ) ! = 0 )
fprintf ( fcfg , " , \n \" algorithm \" : \" %s \" " , json_escape ( default_ algorithm- > name ) ) ;
if ( opt_api_allow )
fprintf ( fcfg , " , \n \" api-allow \" : \" %s \" " , json_escape ( opt_api_allow ) ) ;
if ( strcmp ( opt_api_mcast_addr , API_MCAST_ADDR ) ! = 0 )
@ -5984,6 +6023,69 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
@@ -5984,6 +6023,69 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
cgtime ( & work - > tv_staged ) ;
}
static void * switch_algo_thread ( void * arg )
{
algorithm_t * new_algo = ( algorithm_t * ) arg ;
int i ;
pthread_detach ( pthread_self ( ) ) ;
applog ( LOG_WARNING , " Switching algorithm to %s (%d) " ,
new_algo - > name , new_algo - > nfactor ) ;
// TODO: When threads are canceled, they may leak memory, for example
// the "work" variable in get_work.
rd_lock ( & devices_lock ) ;
for ( i = 0 ; i < total_devices ; i + + ) {
devices [ i ] - > algorithm = * new_algo ;
reinit_device ( devices [ i ] ) ;
}
rd_unlock ( & devices_lock ) ;
// Wait for reinit_gpu to finish
while ( 42 ) {
struct thread_q * tq = control_thr [ gpur_thr_id ] . q ;
bool stop = false ;
mutex_lock ( & tq - > mutex ) ;
stop = list_empty ( & tq - > q ) ;
mutex_unlock ( & tq - > mutex ) ;
if ( stop ) break ;
usleep ( 50000 ) ;
}
mutex_lock ( & algo_switch_lock ) ;
algo_switch_thr = 0 ;
mutex_unlock ( & algo_switch_lock ) ;
return NULL ;
}
static void wait_to_die ( void )
{
mutex_unlock ( & algo_switch_lock ) ;
pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE , NULL ) ;
sleep ( 60 ) ;
applog ( LOG_ERR , " Thread not canceled within 60 seconds " ) ;
}
static void get_work_prepare_thread ( struct thr_info * mythr , struct work * work )
{
struct cgpu_info * cgpu = mythr - > cgpu ;
mutex_lock ( & algo_switch_lock ) ;
pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE , NULL ) ;
if ( ! cmp_algorithm ( & work - > pool - > algorithm , & cgpu - > algorithm ) ) {
// stage work back to queue, we cannot process it yet
stage_work ( work ) ;
if ( algo_switch_thr = = 0 )
pthread_create ( & algo_switch_thr , NULL , & switch_algo_thread , & work - > pool - > algorithm ) ;
wait_to_die ( ) ;
} else {
mutex_unlock ( & algo_switch_lock ) ;
pthread_setcancelstate ( PTHREAD_CANCEL_ENABLE , NULL ) ;
}
}
struct work * get_work ( struct thr_info * thr , const int thr_id )
{
struct work * work = NULL ;
@ -6000,6 +6102,9 @@ struct work *get_work(struct thr_info *thr, const int thr_id)
@@ -6000,6 +6102,9 @@ struct work *get_work(struct thr_info *thr, const int thr_id)
wake_gws ( ) ;
}
}
get_work_prepare_thread ( thr , work ) ;
diff_t = time ( NULL ) - diff_t ;
/* 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
@ -6080,7 +6185,7 @@ static void rebuild_nonce(struct work *work, uint32_t nonce)
@@ -6080,7 +6185,7 @@ static void rebuild_nonce(struct work *work, uint32_t nonce)
* work_nonce = htole32 ( nonce ) ;
scrypt_regenhash ( work ) ;
scrypt_regenhash ( work , work - > pool - > algorithm . n ) ;
}
/* For testing a nonce against diff 1 */
@ -6208,8 +6313,10 @@ static void mt_disable(struct thr_info *mythr, const int thr_id,
@@ -6208,8 +6313,10 @@ static void mt_disable(struct thr_info *mythr, const int thr_id,
applog ( LOG_WARNING , " Thread %d being disabled " , thr_id ) ;
mythr - > rolling = mythr - > cgpu - > rolling = 0 ;
applog ( LOG_DEBUG , " Waiting on sem in miner thread " ) ;
mythr - > paused = true ;
cgsem_wait ( & mythr - > sem ) ;
applog ( LOG_WARNING , " Thread %d being re-enabled " , thr_id ) ;
mythr - > paused = false ;
drv - > thread_enable ( mythr ) ;
}
@ -6226,7 +6333,7 @@ static void hash_sole_work(struct thr_info *mythr)
@@ -6226,7 +6333,7 @@ static void hash_sole_work(struct thr_info *mythr)
struct sgminer_stats * pool_stats ;
/* Try to cycle approximately 5 times before each log update */
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 } ;
uint32_t max_nonce = drv - > can_limit_work ( mythr ) ;
int64_t hashes_done = 0 ;
@ -7174,7 +7281,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
@@ -7174,7 +7281,7 @@ static void *watchdog_thread(void __maybe_unused *userdata)
temp , fanpercent , fanspeed , engineclock , memclock , vddc , activity , powertune ) ;
}
# endif
/* Thread is disabled or waiting on getwork */
if ( * denable = = DEV_DISABLED | | thr - > getwork )
continue ;
@ -7737,7 +7844,7 @@ bool add_cgpu(struct cgpu_info *cgpu)
@@ -7737,7 +7844,7 @@ bool add_cgpu(struct cgpu_info *cgpu)
{
static struct _cgpu_devid_counter * devids = NULL ;
struct _cgpu_devid_counter * d ;
HASH_FIND_STR ( devids , cgpu - > drv - > name , d ) ;
if ( d )
cgpu - > device_id = + + d - > lastid ;
@ -7831,6 +7938,7 @@ int main(int argc, char *argv[])
@@ -7831,6 +7938,7 @@ int main(int argc, char *argv[])
rwlock_init ( & netacc_lock ) ;
rwlock_init ( & mining_thr_lock ) ;
rwlock_init ( & devices_lock ) ;
mutex_init ( & algo_switch_lock ) ;
mutex_init ( & lp_lock ) ;
if ( unlikely ( pthread_cond_init ( & lp_cond , NULL ) ) )
@ -7883,8 +7991,8 @@ int main(int argc, char *argv[])
@@ -7883,8 +7991,8 @@ int main(int argc, char *argv[])
# endif
/* Default algorithm specified in algorithm.c ATM */
algorithm = ( algorithm_t * ) alloca ( sizeof ( algorithm_t ) ) ;
set_algorithm ( algorithm , " scrypt " ) ;
default_ algorithm = ( algorithm_t * ) alloca ( sizeof ( algorithm_t ) ) ;
set_algorithm ( default_ algorithm, " scrypt " ) ;
devcursor = 8 ;
logstart = devcursor + 1 ;
@ -8180,7 +8288,7 @@ begin_bench:
@@ -8180,7 +8288,7 @@ begin_bench:
cgpu - > rolling = cgpu - > total_mhashes = 0 ;
}
cgtime ( & total_tv_start ) ;
cgtime ( & total_tv_end ) ;
get_datestamp ( datestamp , sizeof ( datestamp ) , & total_tv_start ) ;