diff --git a/miner.c b/miner.c index 4d9a565bb7..abdb862988 100644 --- a/miner.c +++ b/miner.c @@ -9710,31 +9710,57 @@ void *cmd_idle_thread(void * const __maybe_unused userp) static struct work *hash_pop(struct cgpu_info * const proc) { - struct work *work_found = NULL, *work, *tmp, *work_highdiff = NULL; + int hc; + struct work *work, *work_found, *tmp; + enum { + HPWS_NONE = 0, + HPWS_LOWDIFF = 1, + HPWS_ROLLABLE = 2, + HPWS_PERFECT = 3, + } work_score = HPWS_NONE; bool did_cmd_idle = false; pthread_t cmd_idle_thr; +retry: mutex_lock(stgd_lock); while (true) { + work_found = NULL; + work_score = 0; + hc = HASH_COUNT(staged_work); HASH_ITER(hh, staged_work, work, tmp) { const struct mining_algorithm * const work_malgo = work_mining_algorithm(work); const float min_nonce_diff = drv_min_nonce_diff(proc->drv, proc, work_malgo); if (min_nonce_diff < work->work_difficulty) { - if (unlikely((!work_highdiff) && min_nonce_diff >= 0)) - work_highdiff = work; + if (unlikely(min_nonce_diff >= 0 && work_score < HPWS_LOWDIFF)) + { + work_found = work; + work_score = HPWS_LOWDIFF; + } + continue; + } + if (work->rolltime && hc > staged_rollable) + { + if (work_score < HPWS_ROLLABLE) + { + work_found = work; + work_score = HPWS_ROLLABLE; + } continue; } // Good match work_found = work; + work_score = HPWS_PERFECT; break; } - work = work_found ?: work_highdiff; - if (work) + if (work_found) + { + work = work_found; break; + } // Failed to get a usable work if (unlikely(staged_full)) @@ -9763,6 +9789,14 @@ static struct work *hash_pop(struct cgpu_info * const proc) no_work = false; + if (can_roll(work) && should_roll(work)) + { + // Instead of consuming it, force it to be cloned and grab the clone + mutex_unlock(stgd_lock); + clone_available(); + goto retry; + } + HASH_DEL(staged_work, work); if (work_rollable(work)) staged_rollable--;