Subject: Interrupts as threads
To: None <tech-kern@netbsd.org>
From: Andrew Doran <ad@netbsd.org>
List: tech-kern
Date: 12/01/2006 23:31:19
Hi,
I have been thinking about the lock ordering problem with the kernel big
lock quite a bit and what it will take to lock the MI kernel down, and have
made some observations.
o There is no easy solution to the lock order problem with the kernel_lock
when using spin locks.
o Using spin locks we will have to keep the SPL above IPL_NONE for longer
that before, or accept (in non-trivial cases) the undesirable cost of
having both interrupt and process context locks around some objects.
o Raising and lowering the SPL is expensive, especially on machines that
need to talk with the hardware on SPL operation. The spin lock path also
has more test+branch pairs / conditional moves and memory references
involved than process locks. For a process context lock, the minimum we
can get away with on entry and exit is one test+branch and two cache line
references.
o Every spin lock / unlock pair denotes a critical section where threads
running in the kernel can not be preempted. That's not currently an issue
but if we move to support real time threads it could become one; I'm not
sure.
o We are doing too much work from interrupt context.
The cleanest way to deal with these issues that I can see is to use
lightweight threads to handle interrupts. My initial thought is to have one
thread per level, per CPU. These would be able to preempt already running
threads, and would hold preempted threads in-situ until the interrupt thread
returns or switches away. In most cases, SPL operations would be replaced by
locks. Blocking would no longer be prohibited, but strongly discouraged - so
doing something like pool_get(foo, PR_WAITOK) should likely trigger an
assertion.
On something like an x86 or MIPS CPU, we wouldn't need to do a full context
switch for interrupts, just switch onto another stack. For things that are
time critical like clock or audio ISRs I think the current scheme of
deferring the interrupts might be better. Although it should not be common,
the delay involved in switching away when trying to acquire a lock seems
undesirable in these cases. (As an aisde, I have been meaning to do some
profiling to see just how often the SPL operations serve their purpose in a
variety of cases but haven't gotten around to it yet.)
Assuming you subscribe to handling interrupts with threads, it raises the
question: where to draw the line between threaded and 'traditional'. It
certianly makes sense to run soft interrupts this way, and I would draw the
line at higher priority ISRs like network, audio, serial and clock.
Thoughts?
Cheers,
Andrew