@ -3511,9 +3511,23 @@ static void *submit_work_thread(void __maybe_unused *userdata)
}
}
# endif /* HAVE_LIBCURL */
# endif /* HAVE_LIBCURL */
/* Return an adjusted ntime if we're submitting work that a device has
* internally offset the ntime . */
static char * offset_ntime ( const char * ntime , int noffset )
{
unsigned char bin [ 4 ] ;
uint32_t h32 , * be32 = ( uint32_t * ) bin ;
hex2bin ( bin , ntime , 4 ) ;
h32 = be32toh ( * be32 ) + noffset ;
* be32 = htobe32 ( h32 ) ;
return bin2hex ( bin , 4 ) ;
}
/* Duplicates any dynamically allocated arrays within the work struct to
/* Duplicates any dynamically allocated arrays within the work struct to
* prevent a copied work struct from freeing ram belonging to another struct */
* prevent a copied work struct from freeing ram belonging to another struct */
void __copy_work ( struct work * work , struct work * base_work )
static void _copy_work ( struct work * work , const struct work * base_work , int noffset )
{
{
int id = work - > id ;
int id = work - > id ;
@ -3526,8 +3540,12 @@ void __copy_work(struct work *work, struct work *base_work)
work - > job_id = strdup ( base_work - > job_id ) ;
work - > job_id = strdup ( base_work - > job_id ) ;
if ( base_work - > nonce1 )
if ( base_work - > nonce1 )
work - > nonce1 = strdup ( base_work - > nonce1 ) ;
work - > nonce1 = strdup ( base_work - > nonce1 ) ;
if ( base_work - > ntime )
if ( base_work - > ntime ) {
if ( noffset )
work - > ntime = offset_ntime ( base_work - > ntime , noffset ) ;
else
work - > ntime = strdup ( base_work - > ntime ) ;
work - > ntime = strdup ( base_work - > ntime ) ;
}
if ( base_work - > coinbase )
if ( base_work - > coinbase )
work - > coinbase = strdup ( base_work - > coinbase ) ;
work - > coinbase = strdup ( base_work - > coinbase ) ;
}
}
@ -3538,7 +3556,7 @@ struct work *copy_work(struct work *base_work)
{
{
struct work * work = make_work ( ) ;
struct work * work = make_work ( ) ;
__ copy_work ( work , base_work ) ;
_copy_work ( work , base_work , 0 ) ;
return work ;
return work ;
}
}
@ -5972,14 +5990,13 @@ static struct work *get_work(struct thr_info *thr, const int thr_id)
return work ;
return work ;
}
}
static void submit_work_async ( struct work * work_in , struct timeval * tv_work_found )
/* Submit a copy of the tested, statistic recorded work item asynchronously */
static void submit_work_async ( struct work * work )
{
{
struct work * work = copy_work ( work_in ) ;
struct pool * pool = work - > pool ;
struct pool * pool = work - > pool ;
pthread_t submit_thread ;
pthread_t submit_thread ;
if ( tv_work_found )
cgtime ( & work - > tv_work_found ) ;
copy_time ( & work - > tv_work_found , tv_work_found ) ;
if ( stale_work ( work , true ) ) {
if ( stale_work ( work , true ) ) {
if ( opt_submit_stale )
if ( opt_submit_stale )
@ -6018,6 +6035,9 @@ static void submit_work_async(struct work *work_in, struct timeval *tv_work_foun
void inc_hw_errors ( struct thr_info * thr )
void inc_hw_errors ( struct thr_info * thr )
{
{
applog ( LOG_INFO , " %s%d: invalid nonce - HW error " , thr - > cgpu - > drv - > name ,
thr - > cgpu - > device_id ) ;
mutex_lock ( & stats_lock ) ;
mutex_lock ( & stats_lock ) ;
hw_errors + + ;
hw_errors + + ;
thr - > cgpu - > hw_errors + + ;
thr - > cgpu - > hw_errors + + ;
@ -6042,12 +6062,8 @@ bool test_nonce(struct work *work, uint32_t nonce)
return ( be32toh ( hash2_32 [ 7 ] ) < = diff1targ ) ;
return ( be32toh ( hash2_32 [ 7 ] ) < = diff1targ ) ;
}
}
/* To be used once the work has been tested to be meet diff1 and has had its
static void update_work_stats ( struct thr_info * thr , struct work * work )
* nonce adjusted . */
void submit_tested_work ( struct thr_info * thr , struct work * work )
{
{
struct timeval tv_work_found ;
work - > share_diff = share_diff ( work ) ;
work - > share_diff = share_diff ( work ) ;
mutex_lock ( & stats_lock ) ;
mutex_lock ( & stats_lock ) ;
@ -6056,50 +6072,63 @@ void submit_tested_work(struct thr_info *thr, struct work *work)
work - > pool - > diff1 + = work - > device_diff ;
work - > pool - > diff1 + = work - > device_diff ;
thr - > cgpu - > last_device_valid_work = time ( NULL ) ;
thr - > cgpu - > last_device_valid_work = time ( NULL ) ;
mutex_unlock ( & stats_lock ) ;
mutex_unlock ( & stats_lock ) ;
}
/* To be used once the work has been tested to be meet diff1 and has had its
* nonce adjusted . */
void submit_tested_work ( struct thr_info * thr , struct work * work )
{
struct work * work_out ;
update_work_stats ( thr , work ) ;
if ( ! fulltest ( work - > hash2 , work - > target ) ) {
if ( ! fulltest ( work - > hash2 , work - > target ) ) {
applog ( LOG_INFO , " Share below target " ) ;
applog ( LOG_INFO , " Share below target " ) ;
return ;
return ;
}
}
work_out = copy_work ( work ) ;
cgtime ( & tv_work_found ) ;
submit_work_async ( work_out ) ;
submit_work_async ( work , & tv_work_found ) ;
}
}
/* Returns true if nonce for work was a valid share */
/* Returns true if nonce for work was a valid share */
bool submit_nonce ( struct thr_info * thr , struct work * work , uint32_t nonce )
bool submit_nonce ( struct thr_info * thr , struct work * work , uint32_t nonce )
{
{
bool ret = true ;
if ( test_nonce ( work , nonce ) )
if ( test_nonce ( work , nonce ) )
submit_tested_work ( thr , work ) ;
submit_tested_work ( thr , work ) ;
else {
else {
applog ( LOG_INFO , " %s%d: invalid nonce - HW error " ,
thr - > cgpu - > drv - > name , thr - > cgpu - > device_id ) ;
inc_hw_errors ( thr ) ;
inc_hw_errors ( thr ) ;
ret = false ;
return false ;
}
}
return ret ;
return t ru e;
}
}
/* Allows drivers to submit work items where the driver has changed the ntime
/* Allows drivers to submit work items where the driver has changed the ntime
* value by noffset . Must be only used with a work protocol that does not ntime
* value by noffset . Must be only used with a work protocol that does not ntime
* roll itself intrinsically to generate work ( eg stratum ) . */
* roll itself intrinsically to generate work ( eg stratum ) . We do not touch
bool submit_noffset_nonce ( struct thr_info * thr , struct work * work , uint32_t nonce ,
* the original work struct , but the copy of it only . */
bool submit_noffset_nonce ( struct thr_info * thr , struct work * work_in , uint32_t nonce ,
int noffset )
int noffset )
{
{
unsigned char bin [ 4 ] ;
struct work * work = make_work ( ) ;
uint32_t h32 , * be32 = ( uint32_t * ) bin ;
bool ret = false ;
hex2bin ( bin , work - > ntime , 4 ) ;
_copy_work ( work , work_in , noffset ) ;
h32 = be32toh ( * be32 ) + noffset ;
if ( ! test_nonce ( work , nonce ) ) {
* be32 = htobe32 ( h32 ) ;
inc_hw_errors ( thr ) ;
free ( work - > ntime ) ;
goto out ;
work - > ntime = bin2hex ( bin , 4 ) ;
}
ret = true ;
update_work_stats ( thr , work ) ;
if ( ! fulltest ( work - > hash2 , work - > target ) ) {
applog ( LOG_INFO , " Share below target " ) ;
goto out ;
}
submit_work_async ( work ) ;
return submit_nonce ( thr , work , nonce ) ;
out :
if ( ! ret )
free_work ( work ) ;
return ret ;
}
}
static inline bool abandon_work ( struct work * work , struct timeval * wdiff , uint64_t hashes )
static inline bool abandon_work ( struct work * work , struct timeval * wdiff , uint64_t hashes )