Skip to content

Commit

Permalink
fix: Avoid data race with read-write lock
Browse files Browse the repository at this point in the history
Use libtuv read-write lock API to avoid the data race
detected by thread Sanitizer.

Related #95.
  • Loading branch information
marktwtn committed Mar 21, 2019
1 parent 6374e02 commit c4547da
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 35 deletions.
38 changes: 26 additions & 12 deletions src/pow_avx.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,15 @@ static int loop256(__m256i *lmid,
__m256i *hmid,
int m,
int8_t *nonce,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
int i = 0, n = 0;
__m256i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2];

uv_rwlock_rdlock(lock);
for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) {
uv_rwlock_rdunlock(lock);
for (int j = 0; j < STATE_TRITS_LENGTH; j++) {
lcpy[j] = lmid[j];
hcpy[j] = hmid[j];
Expand All @@ -175,15 +178,18 @@ static int loop256(__m256i *lmid,
seri256(lmid, hmid, n, nonce);
return i * 256;
}
uv_rwlock_rdlock(lock);
}
uv_rwlock_rdunlock(lock);
return -i * 256 - 1;
}

static int64_t pwork256(int8_t mid[],
int mwm,
int8_t nonce[],
int n,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
__m256i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH];
int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH;
Expand All @@ -202,7 +208,7 @@ static int64_t pwork256(int8_t mid[],
hmid[offset + 5] = _mm256_set_epi64x(HIGH50, HIGH51, HIGH52, HIGH53);
incrN256(n, lmid, hmid);

return loop256(lmid, hmid, mwm, nonce, stopPoW);
return loop256(lmid, hmid, mwm, nonce, stopPoW, lock);
}

#else /* AVX1 */
Expand Down Expand Up @@ -360,12 +366,15 @@ static int loop256(__m256d *lmid,
__m256d *hmid,
int m,
int8_t *nonce,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
int i = 0, n = 0, j = 0;

__m256d lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2];
uv_rwlock_rdlock(lock);
for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) {
uv_rwlock_rdunlock(lock);
for (j = 0; j < STATE_TRITS_LENGTH; j++) {
lcpy[j] = lmid[j];
hcpy[j] = hmid[j];
Expand All @@ -376,15 +385,18 @@ static int loop256(__m256d *lmid,
seri256(lmid, hmid, n, nonce);
return i * 256;
}
uv_rwlock_rdlock(lock);
}
uv_rwlock_rdunlock(lock);
return -i * 256 - 1;
}

static long long int pwork256(int8_t mid[],
int mwm,
int8_t nonce[],
int n,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
__m256d lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH];
int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH;
Expand All @@ -403,24 +415,25 @@ static long long int pwork256(int8_t mid[],
hmid[offset + 5] = _mm256_set_pd(HIGH50, HIGH51, HIGH52, HIGH53);
incrN256(n, lmid, hmid);

return loop256(lmid, hmid, mwm, nonce, stopPoW);
return loop256(lmid, hmid, mwm, nonce, stopPoW, lock);
}

#endif /* __AVX2__ */

static void work_cb(uv_work_t *req)
{
Pwork_struct *pworkInfo = (Pwork_struct *) req->data;
pworkInfo->ret = pwork256(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce,
pworkInfo->n, pworkInfo->stopPoW);
pworkInfo->ret =
pwork256(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce, pworkInfo->n,
pworkInfo->stopPoW, pworkInfo->lock);

pthread_mutex_lock(pworkInfo->lock);
uv_rwlock_wrlock(pworkInfo->lock);
if (pworkInfo->ret >= 0) {
*pworkInfo->stopPoW = 1;
/* This means this thread got the result */
pworkInfo->n = -1;
}
pthread_mutex_unlock(pworkInfo->lock);
uv_rwlock_wrunlock(pworkInfo->lock);
}

static int8_t *tx_to_cstate(Trytes_t *tx)
Expand Down Expand Up @@ -490,7 +503,7 @@ static bool PowAVX(void *pow_ctx)
ctx->stopPoW = 0;
ctx->pow_info.time = 0;
ctx->pow_info.hash_count = 0;
pthread_mutex_init(&ctx->lock, NULL);
uv_rwlock_init(&ctx->lock);
uv_loop_t *loop_ptr = &ctx->loop;
uv_work_t *work_req = ctx->work_req;
Pwork_struct *pitem = ctx->pitem;
Expand Down Expand Up @@ -548,7 +561,8 @@ static bool PowAVX(void *pow_ctx)
nonce_to_result(tx_tryte, nonce_tryte, ctx->output_trytes);

fail:
/* Free memory */
/* Free resource */
uv_rwlock_destroy(&ctx->lock);
free(c_state);
freeTrobject(tx_tryte);
freeTrobject(nonce_trit);
Expand Down
4 changes: 2 additions & 2 deletions src/pow_avx.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct _pwork_struct {
int mwm;
int8_t *nonce;
int n;
pthread_mutex_t *lock;
uv_rwlock_t *lock;
int *stopPoW;
int64_t ret;
};
Expand All @@ -25,7 +25,7 @@ typedef struct _pow_avx_context PoW_AVX_Context;

struct _pow_avx_context {
/* Resource of computing */
pthread_mutex_t lock;
uv_rwlock_t lock;
/* Data type of libtuv */
uv_loop_t loop;
uv_work_t *work_req;
Expand Down
27 changes: 19 additions & 8 deletions src/pow_c.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,16 @@ static long long int loop_cpu(uint64_t *lmid,
uint64_t *hmid,
int m,
int8_t *nonce,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
int n = 0;
long long int i = 0;
uint64_t lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2];

uv_rwlock_rdlock(lock);
for (i = 0; !incr(lmid, hmid) && !*stopPoW; i++) {
uv_rwlock_rdunlock(lock);
memcpy(lcpy, lmid, STATE_TRITS_LENGTH * sizeof(uint64_t));
memcpy(hcpy, hmid, STATE_TRITS_LENGTH * sizeof(uint64_t));
transform64(lcpy, hcpy);
Expand All @@ -120,7 +123,9 @@ static long long int loop_cpu(uint64_t *lmid,
seri(lmid, hmid, n, nonce);
return i * 64;
}
uv_rwlock_rdlock(lock);
}
uv_rwlock_rdunlock(lock);
return -i * 64 - 1;
}

Expand Down Expand Up @@ -157,7 +162,12 @@ static void incrN(int n, uint64_t *mid_low, uint64_t *mid_high)
}
}

static int64_t pwork(int8_t mid[], int mwm, int8_t nonce[], int n, int *stopPoW)
static int64_t pwork(int8_t mid[],
int mwm,
int8_t nonce[],
int n,
int *stopPoW,
uv_rwlock_t *lock)
{
uint64_t lmid[STATE_TRITS_LENGTH] = {0}, hmid[STATE_TRITS_LENGTH] = {0};
para(mid, lmid, hmid);
Expand All @@ -173,22 +183,22 @@ static int64_t pwork(int8_t mid[], int mwm, int8_t nonce[], int n, int *stopPoW)
hmid[offset + 3] = HIGH3;
incrN(n, lmid, hmid);

return loop_cpu(lmid, hmid, mwm, nonce, stopPoW);
return loop_cpu(lmid, hmid, mwm, nonce, stopPoW, lock);
}

static void work_cb(uv_work_t *req)
{
Pwork_struct *pworkInfo = (Pwork_struct *) req->data;
pworkInfo->ret = pwork(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce,
pworkInfo->n, pworkInfo->stopPoW);
pworkInfo->n, pworkInfo->stopPoW, pworkInfo->lock);

pthread_mutex_lock(pworkInfo->lock);
uv_rwlock_wrlock(pworkInfo->lock);
if (pworkInfo->ret >= 0) {
*pworkInfo->stopPoW = 1;
/* This means this thread got the result */
pworkInfo->n = -1;
}
pthread_mutex_unlock(pworkInfo->lock);
uv_rwlock_wrunlock(pworkInfo->lock);
}

static int8_t *tx_to_cstate(Trytes_t *tx)
Expand Down Expand Up @@ -258,7 +268,7 @@ bool PowC(void *pow_ctx)
ctx->stopPoW = 0;
ctx->pow_info.time = 0;
ctx->pow_info.hash_count = 0;
pthread_mutex_init(&ctx->lock, NULL);
uv_rwlock_init(&ctx->lock);
uv_loop_t *loop_ptr = &ctx->loop;
uv_work_t *work_req = ctx->work_req;
Pwork_struct *pitem = ctx->pitem;
Expand Down Expand Up @@ -316,7 +326,8 @@ bool PowC(void *pow_ctx)
nonce_to_result(tx_tryte, nonce_tryte, ctx->output_trytes);

fail:
/* Free memory */
/* Free resource */
uv_rwlock_destroy(&ctx->lock);
free(c_state);
freeTrobject(tx_tryte);
freeTrobject(nonce_trit);
Expand Down
4 changes: 2 additions & 2 deletions src/pow_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct _pwork_struct {
int mwm;
int8_t *nonce;
int n;
pthread_mutex_t *lock;
uv_rwlock_t *lock;
int *stopPoW;
int index;
int64_t ret;
Expand All @@ -26,7 +26,7 @@ typedef struct _pow_c_context PoW_C_Context;

struct _pow_c_context {
/* Resource of computing */
pthread_mutex_t lock;
uv_rwlock_t lock;
/* Data type of libtuv */
uv_loop_t loop;
uv_work_t *work_req;
Expand Down
26 changes: 17 additions & 9 deletions src/pow_sse.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,16 @@ static int64_t loop128(__m128i *lmid,
__m128i *hmid,
int m,
int8_t *nonce,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
int n = 0;
int64_t i = 0;
__m128i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2];

uv_rwlock_rdlock(lock);
for (i = 0; !incr128(lmid, hmid) && !*stopPoW; i++) {
uv_rwlock_rdunlock(lock);
for (int j = 0; j < STATE_TRITS_LENGTH; j++) {
lcpy[j] = lmid[j];
hcpy[j] = hmid[j];
Expand All @@ -134,7 +137,9 @@ static int64_t loop128(__m128i *lmid,
seri128(lmid, hmid, n, nonce);
return i * 128;
}
uv_rwlock_rdlock(lock);
}
uv_rwlock_rdunlock(lock);
return -i * 128 - 1;
}

Expand Down Expand Up @@ -176,7 +181,8 @@ static int64_t pwork128(int8_t mid[],
int mwm,
int8_t nonce[],
int n,
int *stopPoW)
int *stopPoW,
uv_rwlock_t *lock)
{
__m128i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH];
para128(mid, lmid, hmid);
Expand All @@ -194,22 +200,23 @@ static int64_t pwork128(int8_t mid[],
hmid[offset + 4] = _mm_set_epi64x(HIGH40, HIGH41);
incrN128(n, lmid, hmid);

return loop128(lmid, hmid, mwm, nonce, stopPoW);
return loop128(lmid, hmid, mwm, nonce, stopPoW, lock);
}

static void work_cb(uv_work_t *req)
{
Pwork_struct *pworkInfo = (Pwork_struct *) req->data;
pworkInfo->ret = pwork128(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce,
pworkInfo->n, pworkInfo->stopPoW);
pworkInfo->ret =
pwork128(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce, pworkInfo->n,
pworkInfo->stopPoW, pworkInfo->lock);

pthread_mutex_lock(pworkInfo->lock);
uv_rwlock_wrlock(pworkInfo->lock);
if (pworkInfo->ret >= 0) {
*pworkInfo->stopPoW = 1;
/* This means this thread got the result */
pworkInfo->n = -1;
}
pthread_mutex_unlock(pworkInfo->lock);
uv_rwlock_wrunlock(pworkInfo->lock);
}

static int8_t *tx_to_cstate(Trytes_t *tx)
Expand Down Expand Up @@ -279,7 +286,7 @@ static bool PowSSE(void *pow_ctx)
ctx->stopPoW = 0;
ctx->pow_info.time = 0;
ctx->pow_info.hash_count = 0;
pthread_mutex_init(&ctx->lock, NULL);
uv_rwlock_init(&ctx->lock);
uv_loop_t *loop_ptr = &ctx->loop;
uv_work_t *work_req = ctx->work_req;
Pwork_struct *pitem = ctx->pitem;
Expand Down Expand Up @@ -337,7 +344,8 @@ static bool PowSSE(void *pow_ctx)
nonce_to_result(tx_tryte, nonce_tryte, ctx->output_trytes);

fail:
/* Free memory */
/* Free resource */
uv_rwlock_destroy(&ctx->lock);
free(c_state);
freeTrobject(tx_tryte);
freeTrobject(nonce_trit);
Expand Down
4 changes: 2 additions & 2 deletions src/pow_sse.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct _pwork_struct {
int mwm;
int8_t *nonce;
int n;
pthread_mutex_t *lock;
uv_rwlock_t *lock;
int *stopPoW;
int64_t ret;
};
Expand All @@ -25,7 +25,7 @@ typedef struct _pow_sse_context PoW_SSE_Context;

struct _pow_sse_context {
/* Resource of computing */
pthread_mutex_t lock;
uv_rwlock_t lock;
/* Data type of libtuv */
uv_loop_t loop;
uv_work_t *work_req;
Expand Down

0 comments on commit c4547da

Please sign in to comment.