From: Sergey Vlasov <vsu@altlinux.ru>
To: "Luong Ngo" <luong.ngo@gmail.com>
Cc: "linux-os (Dick Johnson)" <linux-os@analogic.com>,
"Linux kernel" <linux-kernel@vger.kernel.org>
Subject: Re: Sleeping thread not receive signal until it wakes up
Date: Fri, 9 Mar 2007 17:58:52 +0300 [thread overview]
Message-ID: <20070309175852.581a6162.vsu@altlinux.ru> (raw)
In-Reply-To: <1b2aacd80703081452s2fff09b7lea97245e337b1d2b@mail.gmail.com>
On Thu, 8 Mar 2007 14:52:07 -0800 Luong Ngo wrote:
[...]
> static irqreturn board_isr(int irq, void *dev_id, struct pt_regs* regs)
> {
> spin_lock(&dev->lock);
> if (dev->irqMask & (1 << irqBit)) {
> // Set the interrupt event mask
> dev->irqEvent |= (1 << irqBit);
>
> // Disable this irq, it will be reenabled after processed by board task
> disable_irq(irq);
I assume that your device does not support shared interrupts? If it
does (and a PCI device is required to support them), you cannot use
disable_irq() here (and you need to check a register in the device to
find out if it really did generate an IRQ)...
> // Wake up Board thread that calling IOCTL
> wake_up(&(dev->boardIRQWaitQueue));
> }
> spin_unlock(&dev->lock);
>
> return IRQ_HANDLED;
...and return IRQ_NONE here if the IRQ is not from your device.
>
> }
>
> static int ats89_ioctl(struct inode *inode, struct file *file, u_int
> cmd, u_long arg)
> {
>
> switch(cmd){
> case GET_IRQ_CMD: {
> u32 regMask32;
>
> spin_lock_irq(dev->lock);
> while ((dev->irqMask & dev->irqEvent) == 0) {
> // Sleep until board interrupt happens
> spin_unlock_irq(dev->lock);
> interruptible_sleep_on(&(dev->boardIRQWaitQueue));
> if (uncond_wakeup) {
> /* don't go back to loop */
> break;
> }
> spin_lock_irq(dev->lock);
> }
>
> uncond_wakeup = 0;
>
> // Board interrupt happened
> regMask32 = dev->irqMask & dev->irqEvent;
> if(copy_to_user(&(((ATS89_IOCTL_S *)arg)->mask32),
> ®Mask32, sizeof(u32))) {
> spin_unlock_irq(dev->lock);
> return -EAGAIN;
> }
>
> // Clear the event mask
> dev->irqEvent = 0;
> spin_unlock_irq(dev->lock);
> }
> break;
>
>
> }
> }
And this code is full of bugs:
1) As you have been told already, interruptible_sleep_on() and
sleep_on() functions are broken and should not be used (they are
left in the kernel only to support some obsolete code). Either
use wait_event_interruptible() or work with wait queues directly
(prepare_to_wait(), finish_wait(), ...).
2) The code to handle pending signals is missing - you need to have
this after wait_event_interruptible():
if (signal_pending(current))
return -ERESTARTSYS;
(but be careful - you might need to clean up something before
returning).
This is what causes your problem - interruptible_sleep_on()
returns if a signal is pending, but your code does not check for
signals and therefore invokes interruptible_sleep_on() again; but
if a signal is pending, interruptible_sleep_on() returns
immediately, causing your driver to eat 100% CPU looping in kernel
mode until some device event finally happens.
3) If uncond_wakeup is set, you break out of the loop with dev->lock
unlocked; however, if dev->irqEvent gets set, you exit the loop
with dev->lock locked. The subsequent code always unlocks
dev->lock, so in the uncond_wakeup case you have double unlock.
4) You are doing copy_to_user() while holding a spinlock - this is
prohibited (as any other form of sleep inside a spinlock).
5) The return code for the copy_to_user() failure is wrong - it
should be -EFAULT (this is not a fatal bug, but an annoyance for
users of your driver, who might get such nonstandard error codes
while debugging their programs and wonder what is going on).
next prev parent reply other threads:[~2007-03-09 14:58 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-03-07 5:31 Sleeping thread not receive signal until it wakes up Luong Ngo
2007-03-07 13:19 ` linux-os (Dick Johnson)
2007-03-07 19:28 ` Luong Ngo
2007-03-07 20:08 ` linux-os (Dick Johnson)
2007-03-07 21:03 ` Lee Revell
2007-03-08 0:40 ` Luong Ngo
2007-03-08 0:28 ` Luong Ngo
2007-03-08 13:01 ` linux-os (Dick Johnson)
2007-03-08 13:53 ` Thomas Gleixner
2007-03-08 22:52 ` Luong Ngo
2007-03-09 14:58 ` Sergey Vlasov [this message]
2007-03-09 19:50 ` Luong Ngo
2007-03-07 20:20 ` Jan Engelhardt
2007-03-07 18:09 ` Sergey Vlasov
[not found] <fa.kb3wuhac4W+1DqK61+sKe9uZwto@ifi.uio.no>
[not found] ` <fa.cyXmbtXvYymKHdI0rEXZCxyk+KE@ifi.uio.no>
[not found] ` <fa.zPDT1vfJF5MjVXXQH/l+YSaLl84@ifi.uio.no>
[not found] ` <fa.HmQN7RhZNBRsiJYADMOsY8DL67k@ifi.uio.no>
[not found] ` <fa.PDmHwxZ3arhmED5SLuEONyxUlz4@ifi.uio.no>
[not found] ` <fa.ygLhZcCLgDxnwAYYVse/Xshr9IE@ifi.uio.no>
2007-03-09 1:10 ` Robert Hancock
2007-03-09 3:24 ` Luong Ngo
2007-03-09 3:45 ` Parav K Pandit
2007-03-10 0:10 ` Luong Ngo
2007-03-10 8:22 ` Sergey Vlasov
2007-03-10 10:54 ` Luong Ngo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070309175852.581a6162.vsu@altlinux.ru \
--to=vsu@altlinux.ru \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-os@analogic.com \
--cc=luong.ngo@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.