Subject: The death of splimp()
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@zembu.com>
List: tech-kern
Date: 04/12/2001 17:32:08
Folks...
Shortly, I will be making a commit that will spell the end of
`splimp()'.
Some historical context...
spl stands for "set priority level". It is used to protect critical
sections of code from interrupts. So, for example, when manipulating
a disk I/O job queue, you might do:
s = splbio(); /* block "block I/O" (disk controller) interrupts */
BUFQ_REMOVE(&sc->sc_queue, bp);
splx(s); /* allow "block I/O" interrupts again */
Now, splimp, a long time ago, blocked interrupts from the IMP device,
that thing that connected big clunky computers to that funky new network
that DARPA built. Network protocol processing was deferred to a software
interrupt that was blocked using splnet(). Over the years, as things like
Ethernet came along, splimp() was used to block interrupts from those
devices, too (since, logically, they performed the same function as the IMP,
so why not use the same call?).
Now, it just so happened that splimp() was used to protect the data
structures of the memory allocation routines that the IMP driver used.
So, as the memory allocators in BSD evolved, splimp() came to be used
to block interrupt from "any device that might call the kernel memory
allocator".
Now, some years ago, NetBSD changed a bit... splimp() retained the
"protect the memory allocator" semantics, splnet() was changed to
block interrupts from "network devices", and splsoftnet() was introduced
to block the software interrupt used for network protocol processing.
Unfortunately, some things had come to rely on the fact that splimp()
blocked interrupts from any device that might allocate memory. This
meant that it blocked "bio", "net", and "tty" interrupts. Things like
the SLIP abused this to have a "network" device that used "tty" interrupts.
So, the use of splimp() in the network code had to stay.
In the mean time, NetBSD introduced splvm(), which took over the job
of "block interrupts from devices that perform memory allocation".
You must admit, splvm() is a better name for that function than splimp() :-)
Now, this meant that the only uses of splimp() were abuses of its
semantics. Over the past N months, I've been slowing purging the
(ab)use of splimp(). This will accomplish a couple of things:
(1) By manipulating network queues at splnet() rather
than spltty(), we won't unnecessarily block tty
interrupts. This could lead to better serial
performance with some platform/device combinations.
(2) Mixing of interrupt levels like splimp() "allows" makes
writing MP-safe interrupt code Very Hard (if not outright
impossible -- interrupt mixing leads only to pain).
By getting rid of the abuse of splimp() (and thus getting
rid of splimp() altogether), we force programmers to
write correct code (which avoids interrupt level mixing
through the use of software interrupts).
I have completed the purge in a local tree. And, wow, this is something
I've wanted to fix for just over a year -- see kern/9587 :-)
So, if there are no objections, I'd like to commit this soon (like,
tomorrow would be nice, but I guess I can wait a little longer if
I have to :-)
--
-- Jason R. Thorpe <thorpej@zembu.com>