Browse Source

add support for setting algorithm/nfactor for each pool separately, and fix bugged OpenCL thread cleanup (thread shutdown)

refactor
Jan Berdajs 11 years ago
parent
commit
c2131df6aa
  1. 5
      algorithm.c
  2. 4
      algorithm.h
  3. 4
      api.c
  4. 6
      doc/configuration.md
  5. 33
      driver-opencl.c
  6. 10
      miner.h
  7. 12
      ocl.c
  8. 2
      ocl.h
  9. 96
      scrypt.c
  10. 2
      scrypt.h
  11. 148
      sgminer.c

5
algorithm.c

@ -33,3 +33,8 @@ void set_algorithm_nfactor(algorithm_t* algo, const uint8_t nfactor) { @@ -33,3 +33,8 @@ void set_algorithm_nfactor(algorithm_t* algo, const uint8_t nfactor) {
return;
}
bool cmp_algorithm(algorithm_t* algo1, algorithm_t* algo2) {
return (strcmp(algo1->name, algo2->name) == 0) &&
(algo1->nfactor == algo2->nfactor);
}

4
algorithm.h

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
#define ALGORITHM_H
#include <inttypes.h>
#include <stdbool.h>
/* Describes the Scrypt parameters and hashing functions used to mine
* a specific coin.
@ -18,4 +19,7 @@ void set_algorithm(algorithm_t* algo, const char* name); @@ -18,4 +19,7 @@ void set_algorithm(algorithm_t* algo, const char* name);
/* Set to specific N factor. */
void set_algorithm_nfactor(algorithm_t* algo, const uint8_t nfactor);
/* Compare two algorithm parameters */
bool cmp_algorithm(algorithm_t* algo1, algorithm_t* algo2);
#endif /* ALGORITHM_H */

4
api.c

@ -2856,7 +2856,7 @@ static void minecoin(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may @@ -2856,7 +2856,7 @@ static void minecoin(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __may
message(io_data, MSG_MINECOIN, 0, NULL, isjson);
io_open = io_add(io_data, isjson ? COMSTR JSON_MINECOIN : _MINECOIN COMSTR);
root = api_add_string(root, "Hash Method", algorithm->name, false);
root = api_add_string(root, "Hash Method", get_devices(0)->algorithm.name, false);
cg_rlock(&ch_lock);
root = api_add_timeval(root, "Current Block Time", &block_timeval, true);
@ -4027,7 +4027,7 @@ die: @@ -4027,7 +4027,7 @@ die:
pthread_cleanup_pop(true);
free(apisock);
if (opt_debug)
applog(LOG_DEBUG, "API: terminating due to: %s",
do_a_quit ? "QUIT" : (do_a_restart ? "RESTART" : (bye ? "BYE" : "UNKNOWN!")));

6
doc/configuration.md

@ -23,6 +23,9 @@ cryptocurrencies. @@ -23,6 +23,9 @@ cryptocurrencies.
* everything else - currently defaults to `scrypt`, subject to change
without warning.
### pool-algorithm
Allows choosing the algorithm for a specific pool. See `algorithm`.
### nfactor
@ -33,6 +36,9 @@ Overrides the default scrypt parameter N, specified as the factor of 2 @@ -33,6 +36,9 @@ Overrides the default scrypt parameter N, specified as the factor of 2
*Default:* depends on `algorithm`; otherwise `10`.
### pool-nfactor
Overrides the default scrypt parameter N for a specific pool. See `nfactor`.
## CLI-only options

33
driver-opencl.c

@ -283,7 +283,7 @@ char *set_gpu_threads(char *arg) @@ -283,7 +283,7 @@ char *set_gpu_threads(char *arg)
for (i = device; i < MAX_GPUDEVICES; i++)
gpus[i].threads = gpus[0].threads;
}
return NULL;
}
@ -880,7 +880,7 @@ retry: // TODO: refactor @@ -880,7 +880,7 @@ retry: // TODO: refactor
intvar = curses_input("Set GPU scan intensity (d or "
MIN_INTENSITY_STR " -> "
MAX_INTENSITY_STR ")");
MAX_INTENSITY_STR ")");
if (!intvar) {
wlogprint("Invalid input\n");
goto retry;
@ -937,14 +937,14 @@ retry: // TODO: refactor @@ -937,14 +937,14 @@ retry: // TODO: refactor
} else if (!strncasecmp(&input, "a", 1)) {
int rawintensity;
char *intvar;
if (selected)
selected = curses_int("Select GPU to change raw intensity on");
if (selected < 0 || selected >= nDevs) {
wlogprint("Invalid selection\n");
goto retry;
}
intvar = curses_input("Set raw GPU scan intensity (" MIN_RAWINTENSITY_STR " -> " MAX_RAWINTENSITY_STR ")");
if (!intvar) {
wlogprint("Invalid input\n");
@ -1094,6 +1094,8 @@ select_cgpu: @@ -1094,6 +1094,8 @@ select_cgpu:
cgtime(&thr->sick);
if (!pthread_cancel(thr->pth)) {
applog(LOG_WARNING, "Thread %d still exists, killing it off", thr_id);
pthread_join(thr->pth, NULL);
thr->cgpu->drv->thread_shutdown(thr);
} else
applog(LOG_WARNING, "Thread %d no longer exists", thr_id);
}
@ -1120,7 +1122,7 @@ select_cgpu: @@ -1120,7 +1122,7 @@ select_cgpu:
//free(clState);
applog(LOG_INFO, "Reinit GPU thread %d", thr_id);
clStates[thr_id] = initCl(virtual_gpu, name, sizeof(name));
clStates[thr_id] = initCl(virtual_gpu, name, sizeof(name), &cgpu->algorithm);
if (!clStates[thr_id]) {
applog(LOG_ERR, "Failed to reinit GPU thread %d", thr_id);
goto select_cgpu;
@ -1186,6 +1188,7 @@ static void opencl_detect(bool hotplug) @@ -1186,6 +1188,7 @@ static void opencl_detect(bool hotplug)
cgpu->threads = 1;
#endif
cgpu->virtual_gpu = i;
cgpu->algorithm = *default_algorithm;
add_cgpu(cgpu);
}
@ -1261,7 +1264,7 @@ static bool opencl_thread_prepare(struct thr_info *thr) @@ -1261,7 +1264,7 @@ static bool opencl_thread_prepare(struct thr_info *thr)
strcpy(name, "");
applog(LOG_INFO, "Init GPU thread %i GPU %i virtual GPU %i", i, gpu, virtual_gpu);
clStates[i] = initCl(virtual_gpu, name, sizeof(name));
clStates[i] = initCl(virtual_gpu, name, sizeof(name), &cgpu->algorithm);
if (!clStates[i]) {
#ifdef HAVE_CURSES
if (use_curses)
@ -1443,15 +1446,25 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work, @@ -1443,15 +1446,25 @@ static int64_t opencl_scanhash(struct thr_info *thr, struct work *work,
return hashes;
}
// Cleanup OpenCL memory on the GPU
// Note: This function is not thread-safe (clStates modification not atomic)
static void opencl_thread_shutdown(struct thr_info *thr)
{
const int thr_id = thr->id;
_clState *clState = clStates[thr_id];
clStates[thr_id] = NULL;
clReleaseKernel(clState->kernel);
clReleaseProgram(clState->program);
clReleaseCommandQueue(clState->commandQueue);
clReleaseContext(clState->context);
if (clState) {
clFinish(clState->commandQueue);
clReleaseMemObject(clState->outputBuffer);
clReleaseMemObject(clState->CLbuffer0);
clReleaseMemObject(clState->padbuffer8);
clReleaseKernel(clState->kernel);
clReleaseProgram(clState->program);
clReleaseCommandQueue(clState->commandQueue);
clReleaseContext(clState->context);
free(clState);
}
}
struct device_drv opencl_drv = {

10
miner.h

@ -241,7 +241,7 @@ enum drv_driver { @@ -241,7 +241,7 @@ enum drv_driver {
/* Use DRIVER_PARSE_COMMANDS to generate extern device_drv prototypes */
#ifndef _MSC_VER
DRIVER_PARSE_COMMANDS(DRIVER_PROTOTYPE)
#endif
#endif
enum alive {
LIFE_WELL,
@ -475,6 +475,7 @@ struct cgpu_info { @@ -475,6 +475,7 @@ struct cgpu_info {
cl_uint vwidth;
size_t work_size;
cl_ulong max_alloc;
algorithm_t algorithm;
int opt_lg, lookup_gap;
size_t opt_tc, thread_concurrency;
@ -548,7 +549,6 @@ struct thread_q { @@ -548,7 +549,6 @@ struct thread_q {
struct thr_info {
int id;
int device_thread;
bool primary_thread;
pthread_t pth;
cgsem_t sem;
@ -559,6 +559,7 @@ struct thr_info { @@ -559,6 +559,7 @@ struct thr_info {
struct timeval sick;
bool pause;
bool paused;
bool getwork;
double rolling;
@ -1014,8 +1015,7 @@ extern int opt_queue; @@ -1014,8 +1015,7 @@ extern int opt_queue;
extern int opt_scantime;
extern int opt_expiry;
extern char *opt_algorithm;
extern algorithm_t *algorithm;
extern algorithm_t *default_algorithm;
extern cglock_t control_lock;
extern pthread_mutex_t hash_lock;
@ -1219,6 +1219,8 @@ struct pool { @@ -1219,6 +1219,8 @@ struct pool {
proxytypes_t rpc_proxytype;
char *rpc_proxy;
algorithm_t algorithm;
pthread_mutex_t pool_lock;
cglock_t data_lock;

12
ocl.c

@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
#include <unistd.h>
#include "findnonce.h"
#include "algorithm.h"
#include "ocl.h"
/* FIXME: only here for global config vars, replace with configuration.h
@ -218,7 +219,7 @@ void patch_opcodes(char *w, unsigned remaining) @@ -218,7 +219,7 @@ void patch_opcodes(char *w, unsigned remaining)
applog(LOG_DEBUG, "Patched a total of %i BFI_INT instructions", patched);
}
_clState *initCl(unsigned int gpu, char *name, size_t nameSize)
_clState *initCl(unsigned int gpu, char *name, size_t nameSize, algorithm_t *algorithm)
{
_clState *clState = (_clState *)calloc(1, sizeof(_clState));
bool patchbfi = false, prog_built = false;
@ -350,7 +351,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize) @@ -350,7 +351,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
find = strstr(extensions, camo);
if (find)
clState->hasBitAlign = true;
/* Check for OpenCL >= 1.0 support, needed for global offset parameter usage. */
char * devoclver = (char *)malloc(1024);
const char * ocl10 = "OpenCL 1.0";
@ -382,7 +383,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize) @@ -382,7 +383,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
return NULL;
}
applog(LOG_DEBUG, "Max work group size reported %d", (int)(clState->max_work_size));
size_t compute_units = 0;
status = clGetDeviceInfo(devices[gpu], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(size_t), (void *)&compute_units, NULL);
if (status != CL_SUCCESS) {
@ -732,8 +733,9 @@ built: @@ -732,8 +733,9 @@ built:
free(binaries);
free(binary_sizes);
applog(LOG_NOTICE, "Initialising kernel %s with%s bitalign, %spatched BFI",
filename, clState->hasBitAlign ? "" : "out", patchbfi ? "" : "un");
applog(LOG_NOTICE, "Initialising kernel %s with%s bitalign, %spatched BFI, nfactor %d, n %d",
filename, clState->hasBitAlign ? "" : "out", patchbfi ? "" : "un",
algorithm->nfactor, algorithm->n);
if (!prog_built) {
/* create a cl program executable for all the devices specified */

2
ocl.h

@ -34,5 +34,5 @@ typedef struct { @@ -34,5 +34,5 @@ typedef struct {
extern char *file_contents(const char *filename, int *length);
extern int clDevicesNum(void);
extern _clState *initCl(unsigned int gpu, char *name, size_t nameSize);
extern _clState *initCl(unsigned int gpu, char *name, size_t nameSize, algorithm_t *algorithm);
#endif /* __OCL_H__ */

96
scrypt.c

@ -204,7 +204,7 @@ PBKDF2_SHA256_80_128(const uint32_t * passwd, uint32_t * buf) @@ -204,7 +204,7 @@ PBKDF2_SHA256_80_128(const uint32_t * passwd, uint32_t * buf)
uint32_t ihash[8];
uint32_t i;
uint32_t pad[16];
static const uint32_t innerpad[11] = {0x00000080, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xa0040000};
/* If Klen > 64, the key is really SHA256(K). */
@ -237,7 +237,7 @@ PBKDF2_SHA256_80_128(const uint32_t * passwd, uint32_t * buf) @@ -237,7 +237,7 @@ PBKDF2_SHA256_80_128(const uint32_t * passwd, uint32_t * buf)
for (i = 0; i < 4; i++) {
uint32_t istate[8];
uint32_t ostate[8];
memcpy(istate, PShictx.state, 32);
PShictx.buf[4] = i + 1;
SHA256_Transform(istate, PShictx.buf, 0);
@ -259,7 +259,7 @@ PBKDF2_SHA256_80_128_32(const uint32_t * passwd, const uint32_t * salt, uint32_t @@ -259,7 +259,7 @@ PBKDF2_SHA256_80_128_32(const uint32_t * passwd, const uint32_t * salt, uint32_t
/* Compute HMAC state after processing P and S. */
uint32_t pad[16];
static const uint32_t ihash_finalblk[16] = {0x00000001,0x80000000,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0x00000620};
/* If Klen > 64, the key is really SHA256(K). */
@ -358,7 +358,7 @@ salsa20_8(uint32_t B[16], const uint32_t Bx[16]) @@ -358,7 +358,7 @@ salsa20_8(uint32_t B[16], const uint32_t Bx[16])
* scratchpad size needs to be at least (bytes):
* 63 + (128 * r * p) + (256 * r + 64) + (128 * r * N)
*/
static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_t *ostate)
static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_t *ostate, uint32_t n)
{
uint32_t * V;
uint32_t X[32];
@ -372,7 +372,7 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_ @@ -372,7 +372,7 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_
PBKDF2_SHA256_80_128(input, X);
for (i = 0; i < algorithm->n; i += 2) {
for (i = 0; i < n; i += 2) {
memcpy(&V[i * 32], X, 128);
salsa20_8(&X[0], &X[16]);
@ -383,8 +383,8 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_ @@ -383,8 +383,8 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_
salsa20_8(&X[0], &X[16]);
salsa20_8(&X[16], &X[0]);
}
for (i = 0; i < algorithm->n; i += 2) {
j = X[16] & (algorithm->n-1);
for (i = 0; i < n; i += 2) {
j = X[16] & (n-1);
p2 = (uint64_t *)(&V[j * 32]);
for(k = 0; k < 16; k++)
p1[k] ^= p2[k];
@ -392,7 +392,7 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_ @@ -392,7 +392,7 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_
salsa20_8(&X[0], &X[16]);
salsa20_8(&X[16], &X[0]);
j = X[16] & (algorithm->n-1);
j = X[16] & (n-1);
p2 = (uint64_t *)(&V[j * 32]);
for(k = 0; k < 16; k++)
p1[k] ^= p2[k];
@ -404,91 +404,19 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_ @@ -404,91 +404,19 @@ static void scrypt_n_1_1_256_sp(const uint32_t* input, char* scratchpad, uint32_
PBKDF2_SHA256_80_128_32(input, X, ostate);
}
void scrypt_regenhash(struct work *work)
void scrypt_regenhash(struct work *work, uint32_t n)
{
uint32_t data[20];
char *scratchbuf;
uint32_t *nonce = (uint32_t *)(work->data + 76);
uint32_t *ohash = (uint32_t *)(work->hash);
be32enc_vect(data, (const uint32_t *)work->data, 19);
data[19] = htobe32(*nonce);
scratchbuf = (char *)alloca(algorithm->n * 128 + 512);
scrypt_n_1_1_256_sp(data, scratchbuf, ohash);
scratchbuf = (char *)alloca(n * 128 + 512);
scrypt_n_1_1_256_sp(data, scratchbuf, ohash, n);
flip32(ohash, ohash);
}
static const uint32_t diff1targ = 0x0000ffff;
/* Used externally as confirmation of correct OCL code */
/* FIXME: find reference in git blame and see why it was present, remove if obsolete */
/*
int scrypt_test(unsigned char *pdata, const unsigned char *ptarget, uint32_t nonce)
{
uint32_t tmp_hash7, Htarg = le32toh(((const uint32_t *)ptarget)[7]);
uint32_t data[20], ohash[8];
char *scratchbuf;
be32enc_vect(data, (const uint32_t *)pdata, 19);
data[19] = htobe32(nonce);
scratchbuf = (char *)alloca(SCRATCHBUF_SIZE);
scrypt_n_1_1_256_sp(data, scratchbuf, ohash, algorithm->n);
tmp_hash7 = be32toh(ohash[7]);
applog(LOG_DEBUG, "htarget %08lx diff1 %08lx hash %08lx",
(long unsigned int)Htarg,
(long unsigned int)diff1targ,
(long unsigned int)tmp_hash7);
if (tmp_hash7 > diff1targ)
return -1;
if (tmp_hash7 > Htarg)
return 0;
return 1;
}
bool scanhash_scrypt(struct thr_info *thr, const unsigned char __maybe_unused *pmidstate,
unsigned char *pdata, unsigned char __maybe_unused *phash1,
unsigned char __maybe_unused *phash, const unsigned char *ptarget,
uint32_t max_nonce, uint32_t *last_nonce, uint32_t n)
{
uint32_t *nonce = (uint32_t *)(pdata + 76);
char *scratchbuf;
uint32_t data[20];
uint32_t tmp_hash7;
uint32_t Htarg = le32toh(((const uint32_t *)ptarget)[7]);
bool ret = false;
be32enc_vect(data, (const uint32_t *)pdata, 19);
scratchbuf = (char *)malloc(SCRATCHBUF_SIZE);
if (unlikely(!scratchbuf)) {
applog(LOG_ERR, "Failed to malloc scratchbuf in scanhash_scrypt");
return ret;
}
while(1) {
uint32_t ostate[8];
*nonce = ++n;
data[19] = htobe32(n);
scrypt_n_1_1_256_sp(data, scratchbuf, ostate, algorithm->n);
tmp_hash7 = be32toh(ostate[7]);
if (unlikely(tmp_hash7 <= Htarg)) {
((uint32_t *)pdata)[19] = htobe32(n);
*last_nonce = n;
ret = true;
break;
}
if (unlikely((n >= max_nonce) || thr->work_restart)) {
*last_nonce = n;
break;
}
}
free(scratchbuf);;
return ret;
}
*/

2
scrypt.h

@ -5,6 +5,6 @@ @@ -5,6 +5,6 @@
/* extern int scrypt_test(unsigned char *pdata, const unsigned char *ptarget, */
/* uint32_t nonce); */
extern void scrypt_regenhash(struct work *work);
extern void scrypt_regenhash(struct work *work, uint32_t n);
#endif /* SCRYPT_H */

148
sgminer.c

@ -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);

Loading…
Cancel
Save