diff --git a/main.c b/main.c index 139ce466..3f87c341 100644 --- a/main.c +++ b/main.c @@ -1478,7 +1478,16 @@ static void *stage_thread(void *userdata) if (!work->cloned && !work->clone) gettimeofday(&work->tv_staged, NULL); - if (unlikely(!tq_push(getq, work))) { + /* If the work is cloned it has already gone to get_work once + * so it must be used ASAP before it goes stale so put it at + * the head of the list */ + if (work->cloned) { + if (unlikely(!tq_push_head(getq, work))) { + applog(LOG_ERR, "Failed to tq_push work in stage_thread"); + ok = false; + break; + } + } else if (unlikely(!tq_push(getq, work))) { applog(LOG_ERR, "Failed to tq_push work in stage_thread"); ok = false; break; diff --git a/miner.h b/miner.h index 0b6eacb3..53e20696 100644 --- a/miner.h +++ b/miner.h @@ -346,6 +346,7 @@ extern void vapplog(int prio, const char *fmt, va_list ap); extern void applog(int prio, const char *fmt, ...); extern struct thread_q *tq_new(void); extern void tq_free(struct thread_q *tq); +extern bool tq_push_head(struct thread_q *tq, void *data); extern bool tq_push(struct thread_q *tq, void *data); extern void *tq_pop(struct thread_q *tq, const struct timespec *abstime); extern void tq_freeze(struct thread_q *tq); diff --git a/util.c b/util.c index f726b4a4..1b2295ea 100644 --- a/util.c +++ b/util.c @@ -618,6 +618,33 @@ void tq_thaw(struct thread_q *tq) tq_freezethaw(tq, false); } +bool tq_push_head(struct thread_q *tq, void *data) +{ + struct tq_ent *ent; + bool rc = true; + + ent = calloc(1, sizeof(*ent)); + if (!ent) + return false; + + ent->data = data; + INIT_LIST_HEAD(&ent->q_node); + + mutex_lock(&tq->mutex); + + if (!tq->frozen) { + list_add(&ent->q_node, &tq->q); + } else { + free(ent); + rc = false; + } + + pthread_cond_signal(&tq->cond); + mutex_unlock(&tq->mutex); + + return rc; +} + bool tq_push(struct thread_q *tq, void *data) { struct tq_ent *ent;