static void *miner_thread(void *thr_id_int) { int thr_id = (unsigned long) thr_id_int; int failures = 0; uint32_t max_nonce = 0xffffff, max_nonce2; CURL *curl; if (opt_randomize) { srandom(time(0)); } curl = curl_easy_init(); if (!curl) { fprintf(stderr, "CURL initialization failed\n"); return NULL; } while (1) { struct work work __attribute__((aligned(128))); unsigned long hashes_done; struct timeval tv_start, tv_end, diff; bool rc; /* obtain new work from bitcoin */ if (!get_work(curl, &work)) { fprintf(stderr, "json_rpc_call failed, "); if ((opt_retries >= 0) && (++failures > opt_retries)) { fprintf(stderr, "terminating thread\n"); return NULL; /* exit thread */ } /* pause, then restart work loop */ fprintf(stderr, "retry after %d seconds\n", opt_fail_pause); sleep(opt_fail_pause); continue; } if (!validate_midstate(work.data, work.midstate)) { printf("SERVER PROBLEM: work.midstate does not equal SHA256 state after first 64-byte chunk\n"); } hashes_done = 0; gettimeofday(&tv_start, NULL); if (opt_randomize) { max_nonce2 = max_nonce*(1.0 + (double)random()/(RAND_MAX+1.0) - 0.5); } else { max_nonce2 = max_nonce; } /* scan nonces for a proof-of-work hash */ switch (opt_algo) { case ALGO_C: rc = scanhash_c(work.midstate, work.data + 64, work.hash1, work.hash, work.target, max_nonce2, &hashes_done); break; #ifdef WANT_SSE2_4WAY case ALGO_4WAY: { unsigned int rc4 = ScanHash_4WaySSE2(work.midstate, work.data + 64, work.hash1, work.hash, work.target, max_nonce2, &hashes_done); rc = (rc4 == -1) ? false : true; } break; #endif #ifdef WANT_VIA_PADLOCK case ALGO_VIA: rc = scanhash_via(work.data, work.target, max_nonce2, &hashes_done); break; #endif case ALGO_CRYPTOPP: rc = scanhash_cryptopp(work.midstate, work.data + 64, work.hash1, work.hash, work.target, max_nonce2, &hashes_done); break; #ifdef WANT_CRYPTOPP_ASM32 case ALGO_CRYPTOPP_ASM32: rc = scanhash_asm32(work.midstate, work.data + 64, work.hash1, work.hash, work.target, max_nonce2, &hashes_done); break; #endif default: /* should never happen */ return NULL; } /* record scanhash elapsed time */ gettimeofday(&tv_end, NULL); timeval_subtract(&diff, &tv_end, &tv_start); hashmeter(thr_id, &diff, hashes_done); /* adjust max_nonce to meet target scan time */ if (diff.tv_sec > (opt_scantime * 2)) max_nonce /= 2; /* large decrease */ else if ((diff.tv_sec > opt_scantime) && (max_nonce > 1500000)) max_nonce -= 1000000; /* small decrease */ else if ((diff.tv_sec < opt_scantime) && (max_nonce < 0xffffec76)) max_nonce += 100000; /* small increase */ /* if nonce found, submit work */ if (rc) submit_work(curl, &work); failures = 0; } curl_easy_cleanup(curl); return NULL; }
static void *miner_thread(void *userdata) { struct thr_info *mythr = userdata; int thr_id = mythr->id; uint32_t max_nonce = 0xffffff; /* Set worker threads to nice 19 and then preferentially to SCHED_IDLE * and if that fails, then SCHED_BATCH. No need for this to be an * error if it fails */ setpriority(PRIO_PROCESS, 0, 19); drop_policy(); /* Cpu affinity only makes sense if the number of threads is a multiple * of the number of CPUs */ if (!(opt_n_threads % num_processors)) affine_to_cpu(mythr->id, mythr->id % num_processors); while (1) { struct work work __attribute__((aligned(128))); uint64_t hashes_done; struct timeval tv_start, tv_end, diff; uint64_t max64; bool rc; /* obtain new work from internal workio thread */ if (unlikely(!get_work(mythr, &work))) { applog(LOG_ERR, "work retrieval failed, exiting " "mining thread %d", mythr->id); goto out; } hashes_done = 0; gettimeofday(&tv_start, NULL); rc = scanhash(thr_id, work.data, work.target, max_nonce, &hashes_done); /* record scanhash elapsed time */ gettimeofday(&tv_end, NULL); timeval_subtract(&diff, &tv_end, &tv_start); hashmeter(thr_id, &diff, hashes_done); /* adjust max_nonce to meet target scan time */ if (diff.tv_usec > 500000) diff.tv_sec++; if (diff.tv_sec > 0) { max64 = (hashes_done / 65536 * opt_scantime) / diff.tv_sec; if (max64 > 0xfffffffaULL) max64 = 0xfffffffaULL; max_nonce = max64; } /* if nonce found, submit work */ if (rc && !submit_work(mythr, &work)) break; } out: tq_freeze(mythr->q); return NULL; }