Browse Source

Do get_work in fill_queue without holding other locks.

nfactor-troky
Con Kolivas 11 years ago
parent
commit
c030439d0b
  1. 26
      cgminer.c

26
cgminer.c

@ -6503,10 +6503,28 @@ static void hash_sole_work(struct thr_info *mythr)
static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct device_drv *drv, const int thr_id) static void fill_queue(struct thr_info *mythr, struct cgpu_info *cgpu, struct device_drv *drv, const int thr_id)
{ {
do { do {
wr_lock(&cgpu->qlock); bool need_work;
if (!cgpu->unqueued_work)
cgpu->unqueued_work = get_work(mythr, thr_id); /* Do this lockless just to know if we need more unqueued work. */
wr_unlock(&cgpu->qlock); need_work = (!cgpu->unqueued_work);
/* get_work is a blocking function so do it outside of lock
* to prevent deadlocks with other locks. */
if (need_work) {
struct work *work = get_work(mythr, thr_id);
wr_lock(&cgpu->qlock);
/* Check we haven't grabbed work somehow between
* checking and picking up the lock. */
if (likely(!cgpu->unqueued_work))
cgpu->unqueued_work = work;
else
need_work = false;
wr_unlock(&cgpu->qlock);
if (unlikely(!need_work))
discard_work(work);
}
/* The queue_full function should be used by the driver to /* The queue_full function should be used by the driver to
* actually place work items on the physical device if it * actually place work items on the physical device if it
* does have a queue. */ * does have a queue. */

Loading…
Cancel
Save