: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:


    And critical_exit() devolves down into:

        if (--td->td_critnest == 0 && PCPU_GET(int_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..

    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:


        if (--td->td_critnest == 0 && PCPU_GET(int_pending)) {
                PCPU_SET(int_pending, 0);
                if (PCPU_GET(ipending))
                (level triggered ints will immediately cause an
                interrupt which, since critnest is 0, can now be

    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.

                                        Matthew Dillon 
                                        <[EMAIL PROTECTED]>

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to