7 messages in org.opensolaris.mdb-discuss[mdb-discuss] how to analyse the stac...
FromSent OnAttachments
liujunJul 31, 2007 4:45 am 
Gavin MaltbyJul 31, 2007 5:28 am 
Frank HofmannJul 31, 2007 5:39 am 
liujunJul 31, 2007 9:59 am 
Gavin MaltbyAug 1, 2007 2:15 am 
Oliver YangAug 11, 2007 9:14 pm 
Gavin MaltbyAug 20, 2007 3:26 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:[mdb-discuss] how to analyse the stack infoActions...
From:Oliver Yang (Oliv@Sun.COM)
Date:Aug 11, 2007 9:14:28 pm
List:org.opensolaris.mdb-discuss

Hi Gavin,

It seems the cpu->cpu_intr_stack is only used for high level interrupt right?

For low level interrupt, we use interrupt thread's stack instead of cpu->cpu_intr_stack.

The assembler code you showed below is about the context switch for loading a new low level interrupt thread, and the T_STACK must refer to the stack pointer register for SPARC CPU right?

Sorry, I'm not familiar with SPARC platform. I just want to make sure my understanding is right. Thanks.

Gavin Maltby wrote:

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