Browse Source

Avoid taking recursive locks in new_enonce1 in proxy mode

master
Con Kolivas 10 years ago
parent
commit
61576761ba
  1. 34
      src/stratifier.c

34
src/stratifier.c

@ -1761,7 +1761,8 @@ static void *blockupdate(void *arg)
return NULL; return NULL;
} }
static inline bool enonce1_free(sdata_t *sdata, uint64_t enonce1) /* Enter holding instance_lock */
static bool __enonce1_free(sdata_t *sdata, uint64_t enonce1)
{ {
stratum_instance_t *client, *tmp; stratum_instance_t *client, *tmp;
bool ret = true; bool ret = true;
@ -1771,14 +1772,12 @@ static inline bool enonce1_free(sdata_t *sdata, uint64_t enonce1)
goto out; goto out;
} }
ck_rlock(&sdata->instance_lock);
HASH_ITER(hh, sdata->stratum_instances, client, tmp) { HASH_ITER(hh, sdata->stratum_instances, client, tmp) {
if (client->enonce1_64 == enonce1) { if (client->enonce1_64 == enonce1) {
ret = false; ret = false;
break; break;
} }
} }
ck_runlock(&sdata->instance_lock);
out: out:
return ret; return ret;
} }
@ -1801,13 +1800,19 @@ static void __fill_enonce1data(workbase_t *wb, stratum_instance_t *client)
static bool new_enonce1(stratum_instance_t *client) static bool new_enonce1(stratum_instance_t *client)
{ {
sdata_t *sdata = client->ckp->data; sdata_t *sdata = client->ckp->data;
int enonce1varlen, i;
bool ret = false; bool ret = false;
workbase_t *wb;
int i;
ck_wlock(&sdata->workbase_lock); /* Extract the enonce1varlen from the current workbase which may be
wb = sdata->current_workbase; * a different workbase to when we __fill_enonce1data but the value
switch(wb->enonce1varlen) { * will not change and this avoids grabbing recursive locks */
ck_rlock(&sdata->workbase_lock);
enonce1varlen = sdata->current_workbase->enonce1varlen;
ck_runlock(&sdata->workbase_lock);
/* instance_lock protects sdata->enonce1u */
ck_wlock(&sdata->instance_lock);
switch(enonce1varlen) {
case 8: case 8:
sdata->enonce1u.u64++; sdata->enonce1u.u64++;
ret = true; ret = true;
@ -1823,7 +1828,7 @@ static bool new_enonce1(stratum_instance_t *client)
case 2: case 2:
for (i = 0; i < 65536; i++) { for (i = 0; i < 65536; i++) {
sdata->enonce1u.u16++; sdata->enonce1u.u16++;
ret = enonce1_free(sdata, sdata->enonce1u.u64); ret = __enonce1_free(sdata, sdata->enonce1u.u64);
if (ret) if (ret)
break; break;
} }
@ -1831,18 +1836,21 @@ static bool new_enonce1(stratum_instance_t *client)
case 1: case 1:
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
sdata->enonce1u.u8++; sdata->enonce1u.u8++;
ret = enonce1_free(sdata, sdata->enonce1u.u64); ret = __enonce1_free(sdata, sdata->enonce1u.u64);
if (ret) if (ret)
break; break;
} }
break; break;
default: default:
quit(0, "Invalid enonce1varlen %d", wb->enonce1varlen); quit(0, "Invalid enonce1varlen %d", enonce1varlen);
} }
if (ret) if (ret)
client->enonce1_64 = sdata->enonce1u.u64; client->enonce1_64 = sdata->enonce1u.u64;
__fill_enonce1data(wb, client); ck_wunlock(&sdata->instance_lock);
ck_wunlock(&sdata->workbase_lock);
ck_rlock(&sdata->workbase_lock);
__fill_enonce1data(sdata->current_workbase, client);
ck_runlock(&sdata->workbase_lock);
if (unlikely(!ret)) if (unlikely(!ret))
LOGWARNING("Enonce1 space exhausted! Proxy rejecting clients"); LOGWARNING("Enonce1 space exhausted! Proxy rejecting clients");

Loading…
Cancel
Save