forked from nuttx/nuttx-update
Fix possibly deadlock condition
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3601 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
3e1e4f6876
commit
1c99e6b36b
1 changed files with 21 additions and 16 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue