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>