On 07/31/07 13:39, Frank Hofmann wrote:

> Running the interrupt handler on the stack of whatever kernel thread was 
> active at that point gains performance - no cycles wasted on switching 
> stacks, no TLB miss for the new stackpage. That's also why high-level 
> interrupts never passivate.

For low PIL interrupts we *do* switch stacks in intr_thread:

         !
         ! Push interrupted thread onto list from new thread.
         ! Set the new thread as the current one.
         ! Set interrupted thread's T_SP because if it is the idle thread,
         ! resume may use that stack between threads.
         !
         stn     %o7, [THREAD_REG + T_PC]        ! mark pc for resume
         stn     %sp, [THREAD_REG + T_SP]        ! mark stack for resume
         stn     THREAD_REG, [%o3 + T_INTR]      ! push old thread
         stn     %o3, [%o2 + CPU_THREAD]         ! set new thread
         mov     %o3, THREAD_REG                 ! set global curthread register
         ldn     [%o3 + T_STACK], %o4            ! interrupt stack pointer
         sub     %o4, STACK_BIAS, %sp

For each cpu and PIL 1 to 10 (or maybe 9 - 10 is for the clock and
might be a special case) we create a dedicated interrupt thread
with associated stack.  In intr_thread above we switch to using
the stack of the corresponding interrupt thread, and update
CPU->cpu_thread to point to the interrupt thread (the latter necessary
not just for accounting but for determining things like if a mutex
owner is on cpu).  What we don't do, unless we passivate, is to
preempt the thread we have "pinned" - we leave it momentarily
in a pinned state, meaning it is the dispatched thread for that
cpu (CPU->cpu_disp_thread) but not the on-proc thread (CPU->cpu_thread).
If the interrupt thread passivates or if we appear to be pinning the
innocent victim thread for an extended period (*) then the interrupt
thread becomes a fully schedulable thread like any other - goes onto
a sleep queue somewhere, wakes up onto a dispatch queue etc.

(*) This is possible because more than one interrupt may be serviced during
a single actual level interrupt (aka PIL interrupt).  Level interrupts
are queued on per-PIL queues for a processor, and there may be more than
one queued at the time the level interrupt is taken.  Furthermore,
additional interrupts for the current level may be queued even as
we service those already queued - that's because they are mostly
queued from vec_interrupt at traplevel 1 which is a higher-priority
trap and so can be taken even while we're in a level interrupt trap.

High level interrupts do not have an associated thread of their own -
no pool of dedicated per-PIL interrupt threads.  There *is*, however,
a dedicated high-PIL interrupt stack to which we switch in
current_thread processing (we need this to guard against
stack overflow).  Since the high level interrupts do not have
a thread of their own they do not change CPU->cpu_thread
and they cannot block because there is no thread object to
throw onto sleep queues, schedule on wakeup etc.  Since high PIL
interrupts "squat" on the thread structure of the innocent
victim they have interrupted they must not change or make
any assumptions about the kthread_t pointed to by cpu_thread.

Cheers

Gavin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3249 bytes
Desc: S/MIME Cryptographic Signature
URL: 
<http://mail.opensolaris.org/pipermail/mdb-discuss/attachments/20070801/9204ed38/attachment.bin>

Reply via email to