Yes. Catch point marked in code snippet at the end of this message. Note that it survived the spinlock. And this specific code piece remains intact as of 2.6.0-test4.Trace; d0ee7f7f <[i810_audio]drain_dac+8f/140> Trace; d0eea0d1 <[i810_audio]i810_release+21/b0>But this is relevant probably. Looks like for some reason, drain_dac() is not finishing properly. We even know at which point it's possibly stuck.
This little discussion still hasn't answered my first, and most interesting question: How can a process be running, and yet not killable. I mean, as of 2.4, if it's stuck in the middle of a system call, within the kernel, I would expect the system to freeeze (with no oops). But if context is switched every now and then, I would expect the OS to check for signals. After all, it's not the process that volunteers to kill itself. It's the system that kills it.
Obviously, I got something wrong here. Who will correct me?
Another thing that makes me wonder, is that according to the source, there's a recurring check for pending signals. But since this code is run under the graces of kernel_lock() (in i810_release(), which calls the drain_dac), I wonder if this is not related to the problem.
Eli
(Code snippet from i810_audio.c follows)
for (;;) {
spin_lock_irqsave(&state->card->lock, flags);
i810_update_ptr(state); <----------------- This is where it was caught! ---------------
count = dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
if (count <= 0)
break;
/*
* This will make sure that our LVI is correct, that our
* pointer is updated, and that the DAC is running. We
* have to force the setting of dmabuf->trigger to avoid
* any possible deadlocks.
*/
if(!dmabuf->enable) {
dmabuf->trigger = PCM_ENABLE_OUTPUT;
i810_update_lvi(state,0);
}
if (signal_pending(current) && signals_allowed) {
break;
}
/* It seems that we have to set the current state to
* TASK_INTERRUPTIBLE every time to make the process
* really go to sleep. This also has to be *after* the
* update_ptr() call because update_ptr is likely to
* do a wake_up() which will unset this before we ever
* try to sleep, resuling in a tight loop in this code
* instead of actually sleeping and waiting for an
* interrupt to wake us up!
*/
set_current_state(TASK_INTERRUPTIBLE);
/*
* set the timeout to significantly longer than it *should*
* take for the DAC to drain the DMA buffer
*/
tmo = (count * HZ) / (dmabuf->rate);
if (!schedule_timeout(tmo >= 2 ? tmo : 2)){
printk(KERN_ERR "i810_audio: drain_dac, dma timeout?\n");
count = 0;
break;
}
}
-- Web: http://www.billauer.co.il