Commit ef8efd6c483ed4ff89da138645bb7609473c7f17

Con Kolivas 2013-10-08T00:01:26

Minimise the time between dropping the read devlock and grabbing the write devlock to avoid tons of logging spam in the interim.

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: