summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2011-05-13 03:33:03 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2011-05-13 03:33:03 +0000
commitf5f95ed259c2ef2ddf3894347fb708384b2f40cb (patch)
treea53f64a1ba873f31272eef1c93d7f1e3604f4e7d
parent9912ce76d0e44edc762051ef54cef83b7cc20611 (diff)
Fix possibly deadlock condition
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@3601 7fd9a85b-ad96-42d3-883c-3090e2eb8679
-rwxr-xr-xmisc/drivers/rtl8187x/rtl8187x.c39
-rw-r--r--nuttx/drivers/usbhost/usbhost_storage.c37
2 files changed, 41 insertions, 35 deletions
diff --git a/misc/drivers/rtl8187x/rtl8187x.c b/misc/drivers/rtl8187x/rtl8187x.c
index e84a982830..4c626e84a8 100755
--- a/misc/drivers/rtl8187x/rtl8187x.c
+++ b/misc/drivers/rtl8187x/rtl8187x.c
@@ -986,36 +986,33 @@ static inline int rtl8187x_devinit(FAR struct rtl8187x_state_s *priv)
{
rtl8187x_takesem(&priv->exclsem);
+ /* Decrement the reference count */
+
+ priv->crefs--;
+
/* Handle a corner case where (1) open() has been called so the
- * reference count is > 2, but the device has been disconnected.
+ * reference count was > 2, but the device has been disconnected.
* In this case, the class instance needs to persist until close()
* is called.
*/
- if (priv->crefs <= 2 && priv->disconnected)
+ if (priv->crefs <= 1 && priv->disconnected)
{
- /* We don't have to give the semaphore because it will be
- * destroyed when usb_destroy is called.
+ /* The will cause the enumeration logic to disconnect
+ * the class driver.
*/
-
- ret = -ENODEV;
- }
- else
- {
- /* Ready for normal operation as a network device */
- uvdbg("Successfully initialized\n");
- priv->crefs--;
- rtl8187x_givesem(&priv->exclsem);
+ ret = -ENODEV;
}
- }
- /* Disconnect on any errors detected during volume initialization */
+ /* Release the semaphore... there is a race condition here.
+ * Decrementing the reference count and releasing the semaphore
+ * allows usbhost_destroy() to execute (on the worker thread);
+ * the class driver instance could get destoryed before we are
+ * ready to handle it!
+ */
- if (ret != OK)
- {
- udbg("ERROR! Aborting: %d\n", ret);
- rtl8187x_destroy(priv);
+ rtl8187x_givesem(&priv->exclsem);
}
return ret;
@@ -1375,6 +1372,10 @@ errout:
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
+ * NOTE that the class instance remains valid upon return with a failure. It is
+ * the responsibility of the higher level enumeration logic to call
+ * CLASS_DISCONNECTED to free up the class driver resources.
+ *
* Assumptions:
* - This function will *not* be called from an interrupt handler.
* - If this function returns an error, the USB host controller driver
diff --git a/nuttx/drivers/usbhost/usbhost_storage.c b/nuttx/drivers/usbhost/usbhost_storage.c
index 7a41cde657..b2a6d85439 100644
--- a/nuttx/drivers/usbhost/usbhost_storage.c
+++ b/nuttx/drivers/usbhost/usbhost_storage.c
@@ -937,10 +937,6 @@ static void usbhost_destroy(FAR void *arg)
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
- * NOTE that the class instance remains valid upon return with a failure. It is
- * the responsibility of the higher level enumeration logic to call
- * CLASS_DISCONNECTED to free up the class driver resources.
- *
* Assumptions:
* This function will *not* be called from an interrupt handler.
*
@@ -1288,28 +1284,33 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
usbhost_takesem(&priv->exclsem);
DEBUGASSERT(priv->crefs >= 2);
+ /* Decrement the reference count */
+
+ priv->crefs--;
+
/* Handle a corner case where (1) open() has been called so the
- * reference count is > 2, but the device has been disconnected.
+ * reference count was > 2, but the device has been disconnected.
* In this case, the class instance needs to persist until close()
* is called.
*/
- if (priv->crefs <= 2 && priv->disconnected)
+ if (priv->crefs <= 1 && priv->disconnected)
{
- /* We don't have to give the semaphore because it will be
- * destroyed when usb_destroy is called.
+ /* The will cause the enumeration logic to disconnect
+ * the class driver.
*/
-
+
ret = -ENODEV;
}
- else
- {
- /* Ready for normal operation as a block device driver */
- uvdbg("Successfully initialized\n");
- priv->crefs--;
- usbhost_givesem(&priv->exclsem);
- }
+ /* Release the semaphore... there is a race condition here.
+ * Decrementing the reference count and releasing the semaphore
+ * allows usbhost_destroy() to execute (on the worker thread);
+ * the class driver instance could get destoryed before we are
+ * ready to handle it!
+ */
+
+ usbhost_givesem(&priv->exclsem);
}
return ret;
@@ -1671,6 +1672,10 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d
* On success, zero (OK) is returned. On a failure, a negated errno value is
* returned indicating the nature of the failure
*
+ * NOTE that the class instance remains valid upon return with a failure. It is
+ * the responsibility of the higher level enumeration logic to call
+ * CLASS_DISCONNECTED to free up the class driver resources.
+ *
* Assumptions:
* - This function will *not* be called from an interrupt handler.
* - If this function returns an error, the USB host controller driver