UIO: Fix concurrency issue
PATCH 1/1 UIO: Fix concurrency issue
In a SMP case there was a race condition issue between uio_pdrv_genirq_irqcontrol() running on one CPU and irq handler on another CPU. Fix it by spin_locking shared resources access inside irq handler. Also:
- Change disable_irq to disable_irq_nosync to avoid deadlock, becausedisable_irq waits for the completion of the irq handler;
- Change atomic bit-manipulation routines to their non-atomic counterparts
as we already are guarding the code by spinlock.
--- drivers/uio/uio_pdrv_genirq.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/uio/uio_pdrv_genirq.c +13 -5
@@ -37,6 +37,11 @@ struct uio_pdrv_genirq_platdata {struct platform_device *pdev; }; +/* Bits in uio_pdrv_genirq_platdata.flags */ +enum { +UIO_IRQ_DISABLED =0 , +}; +static int uio_pdrv_genirq_open (struct uio_info *info,struct inode *inode) {struct uio_pdrv_genirq_platdata *priv = info->priv;
@@ -63,8 +68,10 @@ static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info)* remember the state so we can allow user space to enable it later. */ -if (!test_and_set_bit (0 , &priv->flags)) +spin_lock (&priv->lock); +if (!__test_and_set_bit (UIO_IRQ_DISABLED , &priv->flags))disable_irq_nosync (irq); +spin_unlock (&priv->lock);return IRQ_HANDLED ; }
@@ -78,16 +85,17 @@ static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on)* in the interrupt controller, but keep track of the * state to prevent per-irq depth damage. * -* Serialize this operation to support multiple tasks. +* Serialize this operation to support multiple tasks and concurrency +* with irq handler on SMP systems. */ spin_lock_irqsave (&priv->lock, flags);if (irq_on) { -if (test_and_clear_bit (0 , &priv->flags)) +if (__test_and_clear_bit (UIO_IRQ_DISABLED , &priv->flags))enable_irq (dev_info->irq); }else { -if (!test_and_set_bit (0 , &priv->flags)) -disable_irq (dev_info->irq); +if (!__test_and_set_bit (UIO_IRQ_DISABLED , &priv->flags)) +disable_irq_nosync (dev_info->irq); }spin_unlock_irqrestore (&priv->lock, flags);
Signature · 4 lines
1.7.12.4 -- With Best Regards, Vitalii Demianets
Quoted 10 lines · Vitalii Demianets
In a SMP case there was a race condition issue between
uio_pdrv_genirq_irqcontrol()running on one CPU and irq handler on another CPU. Fix it byspin_lockingshared resources access inside irq handler. Also:
- Changedisable_irqtodisable_irq_nosyncto avoid deadlock, becausedisable_irqwaits for the completion of the irq handler;
- Change atomic bit-manipulation routines to their non-atomic counterparts
as we already are guarding the code by spinlock.Signed-off-by Vitalii Demianets <[email protected]>
Sounds good.
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html