Minimise the time between dropping the read devlock and grabbing the write devlock to avoid tons of logging spam in the interim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
diff --git a/miner.h b/miner.h
index 30b6cd7..23eb9d8 100644
--- a/miner.h
+++ b/miner.h
@@ -881,6 +881,14 @@ static inline void cg_runlock(cglock_t *lock)
rd_unlock(&lock->rwlock);
}
+/* This drops the read lock and grabs a write lock. It does NOT protect data
+ * between the two locks! */
+static inline void cg_ruwlock(cglock_t *lock)
+{
+ rd_unlock_noyield(&lock->rwlock);
+ cg_wlock(lock);
+}
+
static inline void cg_wunlock(cglock_t *lock)
{
wr_unlock_noyield(&lock->rwlock);
diff --git a/usbutils.c b/usbutils.c
index e6e2c98..41c4ef4 100644
--- a/usbutils.c
+++ b/usbutils.c
@@ -1300,12 +1300,11 @@ static void release_cgpu(struct cgpu_info *cgpu)
{
struct cg_usb_device *cgusb = cgpu->usbdev;
struct cgpu_info *lookcgpu;
- int i, pstate;
+ int i;
- DEVWLOCK(cgpu, pstate);
// It has already been done
if (cgpu->usbinfo.nodev)
- goto out_unlock;
+ return;
applog(LOG_DEBUG, "USB release %s%i",
cgpu->drv->name, cgpu->device_id);
@@ -1335,8 +1334,6 @@ static void release_cgpu(struct cgpu_info *cgpu)
_usb_uninit(cgpu);
cgminer_usb_unlock_bd(cgpu->drv, cgpu->usbinfo.bus_number, cgpu->usbinfo.device_address);
-out_unlock:
- DEVWUNLOCK(cgpu, pstate);
}
/*
@@ -2602,10 +2599,14 @@ out_unlock:
err = LIBUSB_ERROR_OTHER;
}
out_noerrmsg:
+ if (NODEV(err)) {
+ cg_ruwlock(&cgpu->usbinfo.devlock);
+ release_cgpu(cgpu);
+ cg_dwlock(&cgpu->usbinfo.devlock);
+ }
+
DEVRUNLOCK(cgpu, pstate);
- if (NODEV(err))
- release_cgpu(cgpu);
return err;
}
@@ -2700,10 +2701,13 @@ int _usb_write(struct cgpu_info *cgpu, int intinfo, int epinfo, char *buf, size_
err = LIBUSB_ERROR_OTHER;
}
out_noerrmsg:
- DEVRUNLOCK(cgpu, pstate);
-
- if (NODEV(err))
+ if (NODEV(err)) {
+ cg_ruwlock(&cgpu->usbinfo.devlock);
release_cgpu(cgpu);
+ cg_dwlock(&cgpu->usbinfo.devlock);
+ }
+
+ DEVRUNLOCK(cgpu, pstate);
return err;
}
@@ -2790,10 +2794,13 @@ int _usb_transfer(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRequest
err = __usb_transfer(cgpu, request_type, bRequest, wValue, wIndex, data, siz, timeout, cmd);
- DEVRUNLOCK(cgpu, pstate);
-
- if (NOCONTROLDEV(err))
+ if (NOCONTROLDEV(err)) {
+ cg_ruwlock(&cgpu->usbinfo.devlock);
release_cgpu(cgpu);
+ cg_dwlock(&cgpu->usbinfo.devlock);
+ }
+
+ DEVRUNLOCK(cgpu, pstate);
return err;
}
@@ -2863,10 +2870,13 @@ int _usb_transfer_read(struct cgpu_info *cgpu, uint8_t request_type, uint8_t bRe
libusb_error_name(err));
}
out_noerrmsg:
- DEVRUNLOCK(cgpu, pstate);
-
- if (NOCONTROLDEV(err))
+ if (NOCONTROLDEV(err)) {
+ cg_ruwlock(&cgpu->usbinfo.devlock);
release_cgpu(cgpu);
+ cg_dwlock(&cgpu->usbinfo.devlock);
+ }
+
+ DEVRUNLOCK(cgpu, pstate);
return err;
}
@@ -3132,7 +3142,7 @@ void usb_set_dev_start(struct cgpu_info *cgpu)
void usb_cleanup(void)
{
struct cgpu_info *cgpu;
- int count;
+ int count, pstate;
int i;
hotplug_time = 0;
@@ -3150,7 +3160,9 @@ void usb_cleanup(void)
case DRIVER_icarus:
case DRIVER_avalon:
case DRIVER_klondike:
+ DEVWLOCK(cgpu, pstate);
release_cgpu(cgpu);
+ DEVWUNLOCK(cgpu, pstate);
count++;
break;
default: