@ -157,7 +157,14 @@ static int input_thr_id;
@@ -157,7 +157,14 @@ static int input_thr_id;
# endif
int gpur_thr_id ;
static int api_thr_id ;
# if defined(USE_MODMINER) || defined(USE_BITFORCE)
static int hotplug_thr_id ;
# endif
static int total_control_threads ;
bool hotplug_mode ;
static int new_devices ;
static int new_threads ;
static int start_devices ;
# ifdef HAVE_LIBUSB
pthread_mutex_t cgusb_lock ;
@ -173,6 +180,7 @@ static pthread_mutex_t sshare_lock;
@@ -173,6 +180,7 @@ static pthread_mutex_t sshare_lock;
pthread_rwlock_t netacc_lock ;
pthread_mutex_t mining_thr_lock ;
pthread_mutex_t devices_lock ;
static pthread_mutex_t lp_lock ;
static pthread_cond_t lp_cond ;
@ -742,18 +750,24 @@ static void load_temp_cutoffs()
@@ -742,18 +750,24 @@ static void load_temp_cutoffs()
if ( val < 0 | | val > 200 )
quit ( 1 , " Invalid value passed to set temp cutoff " ) ;
mutex_lock ( & devices_lock ) ;
devices [ device ] - > cutofftemp = val ;
mutex_unlock ( & devices_lock ) ;
}
} else {
mutex_lock ( & devices_lock ) ;
for ( i = device ; i < total_devices ; + + i ) {
if ( ! devices [ i ] - > cutofftemp )
devices [ i ] - > cutofftemp = opt_cutofftemp ;
}
mutex_unlock ( & devices_lock ) ;
return ;
}
if ( device < = 1 ) {
mutex_lock ( & devices_lock ) ;
for ( i = device ; i < total_devices ; + + i )
devices [ i ] - > cutofftemp = val ;
mutex_unlock ( & devices_lock ) ;
}
}
@ -1990,9 +2004,12 @@ static void curses_print_devstatus(int thr_id)
@@ -1990,9 +2004,12 @@ static void curses_print_devstatus(int thr_id)
char displayed_hashes [ 16 ] , displayed_rolling [ 16 ] ;
uint64_t dh64 , dr64 ;
if ( opt_compact )
return ;
cgpu = get_thr_cgpu ( thr_id ) ;
if ( devcursor + cgpu - > cgminer_id > LINES - 2 | | opt_compact )
if ( cgpu - > cgminer_id > = start_devices | | devcursor + cgpu - > cgminer_id > LINES - 2 )
return ;
cgpu - > utility = cgpu - > accepted / total_secs * 60 ;
@ -2782,6 +2799,16 @@ static void __kill_work(void)
@@ -2782,6 +2799,16 @@ static void __kill_work(void)
applog ( LOG_INFO , " Received kill message " ) ;
# if defined(USE_MODMINER) || defined(USE_BITFORCE)
/* Best to get rid of it first so it doesn't
* try to create any new devices */
if ( ! opt_scrypt ) {
applog ( LOG_DEBUG , " Killing off HotPlug thread " ) ;
thr = & control_thr [ hotplug_thr_id ] ;
thr_info_cancel ( thr ) ;
}
# endif
applog ( LOG_DEBUG , " Killing off watchpool thread " ) ;
/* Kill the watchpool thread */
thr = & control_thr [ watchpool_thr_id ] ;
@ -4015,10 +4042,14 @@ void zero_stats(void)
@@ -4015,10 +4042,14 @@ void zero_stats(void)
zero_bestshare ( ) ;
mutex_lock ( & hash_lock ) ;
for ( i = 0 ; i < total_devices ; + + i ) {
struct cgpu_info * cgpu = devices [ i ] ;
struct cgpu_info * cgpu ;
mutex_lock ( & devices_lock ) ;
cgpu = devices [ i ] ;
mutex_unlock ( & devices_lock ) ;
mutex_lock ( & hash_lock ) ;
cgpu - > total_mhashes = 0 ;
cgpu - > accepted = 0 ;
cgpu - > rejected = 0 ;
@ -4029,8 +4060,8 @@ void zero_stats(void)
@@ -4029,8 +4060,8 @@ void zero_stats(void)
cgpu - > diff_accepted = 0 ;
cgpu - > diff_rejected = 0 ;
cgpu - > last_share_diff = 0 ;
mutex_unlock ( & hash_lock ) ;
}
mutex_unlock ( & hash_lock ) ;
}
# ifdef HAVE_CURSES
@ -5936,12 +5967,17 @@ static void *watchdog_thread(void __maybe_unused *userdata)
@@ -5936,12 +5967,17 @@ static void *watchdog_thread(void __maybe_unused *userdata)
}
for ( i = 0 ; i < total_devices ; + + i ) {
struct cgpu_info * cgpu = devices [ i ] ;
struct thr_info * thr = cgpu - > thr [ 0 ] ;
struct cgpu_info * cgpu ;
struct thr_info * thr ;
enum dev_enable * denable ;
char dev_str [ 8 ] ;
int gpu ;
mutex_lock ( & devices_lock ) ;
cgpu = devices [ i ] ;
mutex_unlock ( & devices_lock ) ;
thr = cgpu - > thr [ 0 ] ;
if ( cgpu - > drv - > get_stats )
cgpu - > drv - > get_stats ( cgpu ) ;
@ -6104,8 +6140,13 @@ void print_summary(void)
@@ -6104,8 +6140,13 @@ void print_summary(void)
}
applog ( LOG_WARNING , " Summary of per device statistics: \n " ) ;
for ( i = 0 ; i < total_devices ; + + i )
log_print_status ( devices [ i ] ) ;
for ( i = 0 ; i < total_devices ; + + i ) {
struct cgpu_info * cgpu ;
mutex_lock ( & devices_lock ) ;
cgpu = devices [ i ] ;
mutex_unlock ( & devices_lock ) ;
log_print_status ( cgpu ) ;
}
if ( opt_shares )
applog ( LOG_WARNING , " Mined %d accepted shares of %d requested \n " , total_accepted , opt_shares ) ;
@ -6355,7 +6396,7 @@ void enable_curses(void) {
@@ -6355,7 +6396,7 @@ void enable_curses(void) {
}
# endif
/* TODO: fix need a dummy CPU device_api even if no support for CPU mining */
/* TODO: fix need a dummy CPU device_drv even if no support for CPU mining */
# ifndef WANT_CPUMINE
struct device_drv cpu_drv ;
struct device_drv cpu_drv = {
@ -6386,11 +6427,18 @@ static int cgminer_id_count = 0;
@@ -6386,11 +6427,18 @@ static int cgminer_id_count = 0;
void enable_device ( struct cgpu_info * cgpu )
{
cgpu - > deven = DEV_ENABLED ;
mutex_lock ( & devices_lock ) ;
devices [ cgpu - > cgminer_id = cgminer_id_count + + ] = cgpu ;
mining_threads + = cgpu - > threads ;
mutex_unlock ( & devices_lock ) ;
if ( hotplug_mode ) {
new_threads + = cgpu - > threads ;
adj_width ( mining_threads + new_threads , & dev_width ) ;
} else {
mining_threads + = cgpu - > threads ;
# ifdef HAVE_CURSES
adj_width ( mining_threads , & dev_width ) ;
adj_width ( mining_threads , & dev_width ) ;
# endif
}
# ifdef HAVE_OPENCL
if ( cgpu - > drv - > drv_id = = DRIVER_OPENCL ) {
gpu_threads + = cgpu - > threads ;
@ -6418,8 +6466,13 @@ bool add_cgpu(struct cgpu_info*cgpu)
@@ -6418,8 +6466,13 @@ bool add_cgpu(struct cgpu_info*cgpu)
cgpu - > device_id = d - > lastid = 0 ;
HASH_ADD_STR ( devids , name , d ) ;
}
devices = realloc ( devices , sizeof ( struct cgpu_info * ) * ( total_devices + 2 ) ) ;
devices [ total_devices + + ] = cgpu ;
mutex_lock ( & devices_lock ) ;
devices = realloc ( devices , sizeof ( struct cgpu_info * ) * ( total_devices + new_devices + 2 ) ) ;
mutex_unlock ( & devices_lock ) ;
if ( hotplug_mode )
devices [ total_devices + new_devices + + ] = cgpu ;
else
devices [ total_devices + + ] = cgpu ;
return true ;
}
@ -6438,6 +6491,105 @@ struct device_drv *copy_drv(struct device_drv *drv)
@@ -6438,6 +6491,105 @@ struct device_drv *copy_drv(struct device_drv *drv)
return copy ;
}
# if defined(USE_MODMINER) || defined(USE_BITFORCE)
static void hotplug_process ( )
{
struct thr_info * thr ;
int i , j ;
for ( i = 0 ; i < new_devices ; i + + ) {
struct cgpu_info * cgpu = devices [ total_devices + i ] ;
enable_device ( cgpu ) ;
cgpu - > cgminer_stats . getwork_wait_min . tv_sec = MIN_SEC_UNSET ;
cgpu - > rolling = cgpu - > total_mhashes = 0 ;
}
mutex_lock ( & mining_thr_lock ) ;
mining_thr = realloc ( mining_thr , sizeof ( thr ) * ( mining_threads + new_threads + 1 ) ) ;
mutex_unlock ( & mining_thr_lock ) ;
if ( ! mining_thr )
quit ( 1 , " Failed to hotplug realloc mining_thr " ) ;
for ( i = 0 ; i < new_threads ; i + + ) {
mining_thr [ mining_threads + i ] = calloc ( 1 , sizeof ( * thr ) ) ;
if ( ! mining_thr [ mining_threads + i ] )
quit ( 1 , " Failed to hotplug calloc mining_thr[%d] " , i ) ;
}
// Start threads
for ( i = 0 ; i < new_devices ; + + i ) {
struct cgpu_info * cgpu = devices [ total_devices ] ;
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 ) {
mutex_lock ( & mining_thr_lock ) ;
thr = mining_thr [ mining_threads ] ;
mutex_unlock ( & mining_thr_lock ) ;
thr - > id = mining_threads ;
thr - > cgpu = cgpu ;
thr - > device_thread = j ;
thr - > q = tq_new ( ) ;
if ( ! thr - > q )
quit ( 1 , " tq_new hotplug failed in starting %s%d mining thread (#%d) " , cgpu - > drv - > name , cgpu - > device_id , total_devices ) ;
/* 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 hotplug ping to thread %d " , thr - > id ) ;
tq_push ( thr - > q , & ping ) ;
}
if ( cgpu - > drv - > thread_prepare & & ! cgpu - > drv - > thread_prepare ( thr ) )
continue ;
thread_reportout ( thr ) ;
if ( unlikely ( thr_info_create ( thr , NULL , miner_thread , thr ) ) )
quit ( 1 , " hotplug thread %d create failed " , thr - > id ) ;
cgpu - > thr [ j ] = thr ;
mining_threads + + ;
}
total_devices + + ;
applog ( LOG_WARNING , " Hotplug: %s added %s %i " , cgpu - > drv - > dname , cgpu - > drv - > name , cgpu - > device_id ) ;
}
}
static void * hotplug_thread ( void __maybe_unused * userdata )
{
pthread_setcanceltype ( PTHREAD_CANCEL_ASYNCHRONOUS , NULL ) ;
RenameThread ( " hotplug " ) ;
hotplug_mode = true ;
while ( 0x2a ) {
sleep ( 5 ) ;
// Version 0.1 just add the devices on - worry about using nodev later
new_devices = 0 ;
new_threads = 0 ;
# ifdef USE_BITFORCE
bitforce_drv . drv_detect ( ) ;
# endif
# ifdef USE_MODMINER
modminer_drv . drv_detect ( ) ;
# endif
if ( new_devices )
hotplug_process ( ) ;
}
return NULL ;
}
# endif
int main ( int argc , char * argv [ ] )
{
bool pools_active = false ;
@ -6479,6 +6631,7 @@ int main(int argc, char *argv[])
@@ -6479,6 +6631,7 @@ int main(int argc, char *argv[])
rwlock_init ( & blk_lock ) ;
rwlock_init ( & netacc_lock ) ;
mutex_init ( & mining_thr_lock ) ;
mutex_init ( & devices_lock ) ;
mutex_init ( & lp_lock ) ;
if ( unlikely ( pthread_cond_init ( & lp_cond , NULL ) ) )
@ -6714,6 +6867,8 @@ int main(int argc, char *argv[])
@@ -6714,6 +6867,8 @@ int main(int argc, char *argv[])
if ( ! total_devices )
quit ( 1 , " All devices disabled, cannot mine! " ) ;
start_devices = total_devices ;
load_temp_cutoffs ( ) ;
for ( i = 0 ; i < total_devices ; + + i )
@ -6772,7 +6927,7 @@ int main(int argc, char *argv[])
@@ -6772,7 +6927,7 @@ int main(int argc, char *argv[])
quit ( 1 , " Failed to calloc mining_thr[%d] " , i ) ;
}
total_control_threads = 7 ;
total_control_threads = 8 ;
control_thr = calloc ( total_control_threads , sizeof ( * thr ) ) ;
if ( ! control_thr )
quit ( 1 , " Failed to calloc control_thr " ) ;
@ -6947,11 +7102,21 @@ begin_bench:
@@ -6947,11 +7102,21 @@ begin_bench:
if ( thr_info_create ( thr , NULL , api_thread , thr ) )
quit ( 1 , " API thread create failed " ) ;
# if defined(USE_MODMINER) || defined(USE_BITFORCE)
if ( ! opt_scrypt ) {
hotplug_thr_id = 6 ;
thr = & control_thr [ hotplug_thr_id ] ;
if ( thr_info_create ( thr , NULL , hotplug_thread , thr ) )
quit ( 1 , " hotplug thread create failed " ) ;
pthread_detach ( thr - > pth ) ;
}
# endif
# ifdef HAVE_CURSES
/* Create curses input thread for keyboard input. Create this last so
* that we know all threads are created since this can call kill_work
* to try and shut down ll previous threads . */
input_thr_id = 6 ;
* to try and shut down a ll previous threads . */
input_thr_id = 7 ;
thr = & control_thr [ input_thr_id ] ;
if ( thr_info_create ( thr , NULL , input_thread , thr ) )
quit ( 1 , " input thread create failed " ) ;
@ -6959,8 +7124,8 @@ begin_bench:
@@ -6959,8 +7124,8 @@ begin_bench:
# endif
/* Just to be sure */
if ( total_control_threads ! = 7 )
quit ( 1 , " incorrect total_control_threads (%d) should be 7 " , total_control_threads ) ;
if ( total_control_threads ! = 8 )
quit ( 1 , " incorrect total_control_threads (%d) should be 8 " , total_control_threads ) ;
/* Once everything is set up, main() becomes the getwork scheduler */
while ( 42 ) {