Calling tsleep(9) with interrupts disabled
John Baldwin
jhb at freebsd.org
Tue May 15 15:35:22 UTC 2012
On Tuesday, May 08, 2012 12:07:12 pm Ian Lepore wrote:
> I just realized that I've accidentally coded a sequence similar to this
> in a driver:
>
> s = intr_disable();
> // do stuff here
> tsleep(sc, 0, "twird", hz / 4);
> // more stuff
> intr_restore(s);
>
> Much to my surpise this works, including waking up due to wakeup(sc)
> being called from an interrupt handler. So apparently tsleep() results
> in interrupts being re-enabled during the sleep, although nothing in the
> manpage says that will happen.
>
> Can I safely rely on this behavior, or is it working by accident?
>
> (Please no lectures on the evils of disabling interrupts... This is not
> a multi-GHz multi-core Xeon, it's a 180mhz embedded SoC with buggy
> builtin devices that will drop or corrupt data if an interrupt happens
> during the "do stuff here" part of the code.)
This happens to work because spinlock_enter/spinlock_exit also disable
interrupts (so the new thread will re-enable interrupts when it resumes).
However, if we switched spinlock_enter/exit to do something else in the
future (e.g. to raise TPR as I have patches to do), then this would break.
One option is to use spinlock_enter/exit instead of intr_disable/restore.
However, you should probably just use a spin lock instead and use
msleep_spin() instead of tsleep(). You can then use the spin lock in your
filter interrupt handler around wakeup to prevent lost wakeups. Note that in
a kernel without the SMP option, spin locks just devolve to
spinlock_enter/exit anyway.
--
John Baldwin
More information about the freebsd-hackers
mailing list