From 0d90dae98e56d2b15fbd065cb9e8c060102b6073 Mon Sep 17 00:00:00 2001 From: patacongo Date: Fri, 13 May 2011 03:33:03 +0000 Subject: Fix possibly deadlock condition git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3601 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/drivers/usbhost/usbhost_storage.c | 37 +++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 16 deletions(-) (limited to 'nuttx/drivers') diff --git a/nuttx/drivers/usbhost/usbhost_storage.c b/nuttx/drivers/usbhost/usbhost_storage.c index 7a41cde65..b2a6d8543 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 -- cgit v1.2.3