Date: Sun, 24 Feb 2002 17:37:33 -0800 (PST) From: Matthew Dillon <dillon@apollo.backplane.com> To: Andrew Gallatin <gallatin@cs.duke.edu> Cc: John Baldwin <jhb@FreeBSD.ORG>, dfr@nlsystems.com, current@FreeBSD.ORG Subject: Re: Patch for critical_enter()/critical_exit() & interrupt assembly revamp, please review! Message-ID: <200202250137.g1P1bXq27219@apollo.backplane.com> References: <20020224131027.I31343-100000@gamplex.bde.org> <200202241912.g1OJCMx95238@apollo.backplane.com> <15481.36444.52026.935742@grasshopper.cs.duke.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
:I think you're making critical_enter()/critical_exit() cheaper by not
:actually messing with the interrupt hardware when they're called.
:Very much like what we do in 4-stable.
:
:Instead, you set/clear a per-cpu flag (or incr/decr a counter). If an
:interrupt comes in when you're inside a critical section, you make
:note of it & mask interrupts on that cpu. In critical_exit(),
:you run the interrupt handler if there's a pending interrupt, and
:unmask interrupts. If there's not a pending interrupt, you just clear
:the flag (or devrement a counter).
:
:Is that basically it?
Right. And it turns out to be a whole lot easier to do in -current
because we do not have the _cpl baggage.
Basically critical_enter() devolves down into:
++td->td_critnest
And critical_exit() devolves down into:
if (--td->td_critnest == 0 && PCPU_GET(int_pending))
_deal_with_interupts_marked_pending()
As we found with the lazy spl()s in -stable, this is a
huge win-win situation because no interrupts typically
occur while one is in short-lived critical sections. On
-current, critical sections are for spin locks (i.e. mainly
the sched_lock) and in a few other tiny pieces of code and
that is pretty much it. It is a far better situation then
the massive use of spl*()'s we see in -stable and once Giant
is gone it is going to be pretty awesome.
:If so, I'm wondering if this is even possible on alpha, where we don't
:have direct access to the hardware. However, according to the psuedo
:code for rti in the Brown book, munging with the saved PSL in
:trapframe to set the IPL should work. Hmm..
:
:Drew
Well, on IA32 there are effectively two types of interrupts (edge
and level triggered), and three interrupt masks (the processor
interrupt disable, a master bit mask, and then the per-device
masks), and two ways of handling interrupts (as a scheduled
interrupt thread or as a 'fast' interrupt).
Note that the masking requirement is already part and parcel in
-current because most interrupts are now scheduled. The hardware
interrupt routine must schedule the interrupt thread and then
mask the interrupt since it is not dealing with it right then
and there and must be able to return to whatever was running before.
The interrupt thread will unmask the interrupt when it is through
processing it.
But *which* mask one is able to use determines how efficiently
one can write critical_enter() and critical_exit(). On IA32 we
can use the master bit mask instead of the processor interrupt
disable which allows the optimization you see in this patch set.
--
On alpha if you are only able to use the process interrupt disable
you can still optimizatize critical_enter() and critical_exit(). That
is, you can do this:
critical_enter():
++td->td_critnest;
critical_exit()
if (--td->td_critnest == 0 && PCPU_GET(int_pending)) {
PCPU_SET(int_pending, 0);
if (PCPU_GET(ipending))
deal_with_pending_edge_triggered_ints();
enable_hardware_interrupts();
(level triggered ints will immediately cause an
interrupt which, since critnest is 0, can now be
taken)
}
hard interrupt vector code:
if (curthread->td_critnest) {
Save any edge triggered interrupts to a bitmap
somewhere (i.e. ipending |= 1 << irq_that_was_taken).
adjust return frame such that the restored PSL
has interrupts disabled so it does not immediately
re-enter the hardware interrupt vector code.
}
As you can see, it should be possible to make critical_enter()
and critical_exit() streamlined even on architectures where you
may not have direct access to interrupt masks. In fact, I
considered doing exactly this for the I386 but decided that it
was cleaner to mask level interrupts and throw everything into
the same ipending hopper.
-Matt
Matthew Dillon
<dillon@backplane.com>
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200202250137.g1P1bXq27219>
