KiIdleLoop线程分析之优先级为0到调用nt!SwapContext切换到NextThread的一个例子

KiIdleLoop线程分析之优先级为0到调用nt!SwapContext切换到NextThread的一个例子

0: kd> g

Breakpoint 16 hit

eax=00000001 ebx=00000102 ecx=00000002 edx=00000000 esi=f7737120 edi=00000000

eip=804ee4f8 esp=f78aac9c ebp=f78aacc0 iopl=0 nv up ei pl nz na po nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202

hal!HalRequestSoftwareInterrupt:

804ee4f8 643a0d95000000 cmp cl,byte ptr fs:[95h] fs:0030:00000095=00

1: kd> dx -id 0,0,89831250 -r1 ((basesrv!_KPRCB *)0xffdff120)

((basesrv!_KPRCB *)0xffdff120) : 0xffdff120 [Type: _KPRCB *]

+0x000\] MinorVersion : 0x1 \[Type: unsigned short

+0x002\] MajorVersion : 0x1 \[Type: unsigned short

+0x004\] CurrentThread : 0x895f2a78 \[Type: _KTHREAD \*

+0x008\] NextThread : 0x0 \[Type: _KTHREAD \*

+0x00c\] IdleThread : 0x80b200c0 \[Type: _KTHREAD \*

+0x928\] ReadySummary : 0x0 \[Type: unsigned long

+0x92c\] SelectNextLast : 0x0 \[Type: unsigned long

+0x930\] DispatcherReadyListHead \[Type: _LIST_ENTRY \[32\]

+0xa30\] DeferredReadyListHead \[Type: _SINGLE_LIST_ENTRY

1: kd> dt kthread 8952bc18

CSRSRV!KTHREAD

+0x000 Header : _DISPATCHER_HEADER

+0x010 MutantListHead : _LIST_ENTRY [ 0x8952bc28 - 0x8952bc28 ]

+0x018 InitialStack : 0xba583000 Void

+0x01c StackLimit : 0xba580000 Void

+0x020 KernelStack : 0xba582c78 Void

+0x024 ThreadLock : 0

+0x028 ContextSwitches : 0x2d7

+0x02c State : 0x3 ''

+0x02d NpxState : 0xa ''

+0x02e WaitIrql : 0 ''

+0x02f WaitMode : 1 ''

+0x030 Teb : 0x7ffd9000 Void

+0x034 ApcState : _KAPC_STATE

+0x04c ApcQueueLock : 0

+0x050 WaitStatus : 0n258

+0x054 WaitBlockList : 0x8952bd00 _KWAIT_BLOCK

+0x058 Alertable : 0 ''

+0x059 WaitNext : 0 ''

+0x05a WaitReason : 0x4 ''

+0x05b Priority : 8 ''

1: kd> dx -id 0,0,89831250 -r1 ((basesrv!_KPRCB *)0xf7737120)

((basesrv!_KPRCB *)0xf7737120) : 0xf7737120 [Type: _KPRCB *]

+0x000\] MinorVersion : 0x1 \[Type: unsigned short

+0x002\] MajorVersion : 0x1 \[Type: unsigned short

+0x004\] CurrentThread : 0xf7739fa0 \[Type: _KTHREAD \*

+0x008\] NextThread : 0x8952bc18 \[Type: _KTHREAD \*

+0x00c\] IdleThread : 0xf7739fa0 \[Type: _KTHREAD \*

+0x928\] ReadySummary : 0x0 \[Type: unsigned long

+0x92c\] SelectNextLast : 0x0 \[Type: unsigned long

+0x930\] DispatcherReadyListHead \[Type: _LIST_ENTRY \[32\]

+0xa30\] DeferredReadyListHead \[Type: _SINGLE_LIST_ENTRY

1: kd> dx -id 0,0,89831250 -r1 ((basesrv!_KTHREAD *)0xf7739fa0)

((basesrv!_KTHREAD *)0xf7739fa0) : 0xf7739fa0 [Type: _KTHREAD *]

+0x000\] Header \[Type: _DISPATCHER_HEADER

+0x010\] MutantListHead \[Type: _LIST_ENTRY

+0x018\] InitialStack : 0xf78ab000 \[Type: void \*

+0x01c\] StackLimit : 0xf78a8000 \[Type: void \*

+0x020\] KernelStack : 0xf78aad4c \[Type: void \*

+0x024\] ThreadLock : 0x0 \[Type: unsigned long

+0x028\] ContextSwitches : 0x2b9a \[Type: unsigned long

+0x02c\] State : 0x2 \[Type: unsigned char

+0x02d\] NpxState : 0xa \[Type: unsigned char

+0x02e\] WaitIrql : 0x2 \[Type: unsigned char

+0x02f\] WaitMode : 0 \[Type: char

+0x030\] Teb : 0x0 \[Type: void \*

+0x034\] ApcState \[Type: _KAPC_STATE

+0x04c\] ApcQueueLock : 0x0 \[Type: unsigned long

+0x050\] WaitStatus : 0 \[Type: long

+0x054\] WaitBlockList : 0x0 \[Type: _KWAIT_BLOCK \*

+0x058\] Alertable : 0x0 \[Type: unsigned char

+0x059\] WaitNext : 0x0 \[Type: unsigned char

+0x05a\] WaitReason : 0x0 \[Type: unsigned char

+0x05b\] Priority : 0 \[Type: char

+0x113\] Quantum : 114 'r' \[Type: char

1: kd> !thread 0xf7739fa0

THREAD f7739fa0 Cid 0000.0000 Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 1

Not impersonating

Owning Process 80b20320 Image: Idle

Attached Process N/A Image: N/A

Wait Start TickCount 0 Ticks: 274655302 (49:16:04:49.093)

Context Switch Count 11162 IdealProcessor: 0

UserTime 00:00:00.000

KernelTime 00:01:46.234

Stack Init f78ab000 Current f78aad4c Base f78ab000 Limit f78a8000 Call 00000000

Priority 0 BasePriority 0 PriorityDecrement 0 IoPriority 0 PagePriority 0

ChildEBP RetAddr Args to Child

f78aac98 80a3ccf7 bae6aa16 f7737dd0 f78aad50 hal!HalRequestSoftwareInterrupt (FPO: [0,0,0]) [d:\srv03rtm\base\hals\halmps\i386\mpswint.asm @ 84]

f78aaca8 804ed906 f78aacc0 00000000 00000402 nt!KiIpiServiceRoutine+0x6f (FPO: [2,3,0]) [d:\srv03rtm\base\ntos\ke\i386\mpipia.asm @ 152]

f78aaca8 bae6aa16 f78aacc0 00000000 00000402 hal!HalpIpiHandler+0xca (FPO: [0,2] TrapFrame @ f78aacc0) [d:\srv03rtm\base\hals\halmps\i386\mpipi.asm @ 718]

f78aad50 80b00a60 00000000 0000000e 00000000 processr!AcpiC1Idle+0x12 (FPO: [0,2,0]) [d:\srv03rtm\base\hals\processor\lib\i386\cstate.asm @ 134]

f78aad54 00000000 0000000e 00000000 00000000 nt!KiIdleLoop+0xc (FPO: [0,0,0]) [d:\srv03rtm\base\ntos\ke\i386\ctxswap.asm @ 1362]

1: kd> kc 2

00 hal!HalRequestSoftwareInterrupt

01 nt!KiIpiServiceRoutine

1: kd> g

Breakpoint 46 hit

WARNING: Process directory table base 7A00C000 doesn't match CR3 00039000

WARNING: Process directory table base 7A00C000 doesn't match CR3 00039000

eax=00000002 ebx=f7737000 ecx=00000001 edx=0000001b esi=8952bc18 edi=f7739fa0

eip=80b007f0 esp=f78aad54 ebp=80b20320 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!SwapContext:

80b007f0 51 push ecx

windbg> .open -a ffffffff804ee4f8

1: kd> kc 2

00 nt!SwapContext

01 nt!KiIdleLoop

windbg> .open -a ffffffff80b00a60

;++

;

; VOID

; KiIdleLoop(

; VOID

; )

;

; Routine Description:

;

; This routine continuously executes the idle loop and never returns.

;

; Arguments:

;

; ebx - Address of the current processor's PCR.

;

; Return value:

;

; None - routine never returns.

;

;--

cPublicFastCall KiIdleLoop ,0

cPublicFpo 0, 0

if DBG

xor edi, edi ; reset poll breakin counter

endif

jmp short kid20 ; Skip HalIdleProcessor on first iteration

;

; There are no entries in the DPC list and a thread has not been selected

; for execution on this processor. Call the HAL so power managment can be

; performed.

;

; N.B. The HAL is called with interrupts disabled. The HAL will return

; with interrupts enabled.

;

; N.B. Use a call instruction instead of a push-jmp, as the call instruction

; executes faster and won't invalidate the processor's call-return stack

; cache.

;

kid10: lea ecx, [ebx].PcPrcbData.PbPowerState

call dword ptr [ecx].PpIdleFunction ; (ecx) = Arg0

;

; Give the debugger an opportunity to gain control on debug systems.

;

; N.B. On an MP system the lowest numbered idle processor is the only

; processor that polls for a breakin request.

;

kid20:

if DBG

ifndef NT_UP

mov eax, _KiIdleSummary ; get idle summary

mov ecx, [ebx].PcSetMember ; get set member

dec ecx ; compute right bit mask

and eax, ecx ; check if any lower bits set

jnz short CheckDpcList ; if nz, not lowest numbered

endif

dec edi ; decrement poll counter

jg short CheckDpcList ; if g, not time to poll

POLL_DEBUGGER ; check if break in requested

endif

kid30:

if DBG

ifndef NT_UP

mov edi, 20 * 1000 ; set breakin poll interval

else

mov edi, 100 ; UP idle loop has a HLT in it

endif

endif

CheckDpcList0: ;

YIELD

;

; Disable interrupts and check if there is any work in the DPC list of the

; current processor or a target processor.

;

CheckDpcList:

;

; N.B. The following code enables interrupts for a few cycles, then

; disables them again for the subsequent DPC and next thread

; checks.

;

sti ; enable interrupts

nop ;

nop ;

cli ; disable interrupts

;

; Process the deferred procedure call list for the current processor.

;

mov eax, [ebx]+PcPrcbData+PbDpcQueueDepth ; get DPC queue depth

or eax, [ebx]+PcPrcbData+PbTimerRequest ; merge timer request

ifndef NT_UP

or eax, [ebx]+PcPrcbData+PbDeferredReadyListHead ; merge deferred list head

endif

jz short CheckNextThread ; if z, no DPC's or timers to process

mov cl, DISPATCH_LEVEL ; set interrupt level

fstCall HalClearSoftwareInterrupt ; clear software interrupt

lea ecx, [ebx].PcPrcbData ; set current PRCB address

CAPSTART <@KiIdleLoop@0,@KiRetireDpcList@4>

fstCall KiRetireDpcList ; process the current DPC list

CAPEND <@KiIdleLoop@0>

if DBG

xor edi, edi ; clear breakin poll interval

endif

;

; Check if a thread has been selected to run on the current processor.

;

CheckNextThread: ;

cmp dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; thread selected?

ifdef NT_UP

je short kid10 ; if eq, no thread selected

else

je kid40 ; if eq, no thread selected.

endif

;

; Raise IRQL to synchronization level and enable interrupts.

;

ifndef NT_UP

RaiseIrql SYNCH_LEVEL, NoOld ; raise IRQL to synchronizaiton level

endif

sti ; enable interrupts

mov edi, [ebx].PcPrcbData.PbCurrentThread ; get idle thread address

;

; Set context swap busy for idle thread and acquire the PRCB lock.

;

ifndef NT_UP

mov byte ptr [edi].ThSwapBusy, 1 ; set context swap busy

lock bts dword ptr [ebx].PcPrcbData.PbPrcbLock, 0 ; try to acquire PRCB Lock

jnc short kid33 ; if nc, PRCB lock acquired

lea ecx, [ebx].PcPrcbData.PbPrcbLock ; get PRCB lock address

fstCall KefAcquireSpinLockAtDpcLevel ; acquire current PRCB lock

endif

;

; If a thread had been scheduled for this processor but was removed from

; eligibility (e.g., an affinity change), then the new thread could be the

; idle thread.

;

kid33: mov esi, [ebx].PcPrcbData.PbNextThread ; get next thread address

ifndef NT_UP

cmp esi, edi ; check if idle thread

je short kisame ; if e, processor idle again

endif

and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread

mov [ebx].PcPrcbData.PbCurrentThread, esi ; set new thread address

mov byte ptr [esi]+ThState, Running ; set thread state running

;

; Clear idle schedule since a new thread has been selected for execution on

; this processor and release the PRCB lock.

;

ifndef NT_UP

and byte ptr [ebx].PcPrcbData.PbIdleSchedule, 0 ; clear idle schedule

and dword ptr [ebx].PcPrcbData.PbPrcbLock, 0 ; release current PRCB lock

endif

kid35: ;

CAPSTART <@KiIdleLoop@0,SwapContext>

mov ecx, APC_LEVEL ; set APC bypass disable
call SwapContext ; swap context

CAPEND <@KiIdleLoop@0>

ifndef NT_UP

LowerIrql DISPATCH_LEVEL ; lower IRQL to dispatch level

endif

jmp kid30 ;

;

; The new thread is the Idle thread (same as old thread). This can happen

; rarely when a thread scheduled for this processor is made unable to run

; on this processor. As this processor has again been marked idle, other

; processors may unconditionally assign new threads to this processor.

;

ifndef NT_UP

kisame: and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread

and dword ptr [ebx].PcPrcbData.PbPrcbLock, 0 ; release current PRCB lock

and byte ptr [edi].ThSwapBusy, 0 ; set idle thread context swap idle

jmp kid30 ;

;

; Call idle schedule if requested.

;

kid40: cmp byte ptr [ebx].PcPrcbData.PbIdleSchedule, 0 ; check if idle schedule

je kid10 ; if e, idle schedule not requested

sti ; enable interrupts

lea ecx, [ebx].PcPrcbData ; get current PRCB address

fstCall KiIdleSchedule ; attempt to schedule thread

test eax, eax ; test if new thread schedule

mov esi, eax ; set new thread address

mov edi, [ebx].PcPrcbData.PbIdleThread ; get idle thread address

jnz short kid35 ; if nz, new thread scheduled

jmp kid30 ;

endif

fstENDP KiIdleLoop

1: kd> g

Breakpoint 14 hit

eax=00000041 ebx=ba582cc8 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00720 esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt:

80b00720 648b1d1c000000 mov ebx,dword ptr fs:[1Ch] fs:0030:0000001c=f7737000

1: kd> kc 5

00 nt!KiDispatchInterrupt

01 hal!HalpDispatchInterrupt

02 hal!KfLowerIrql

03 nt!KiSwapThread

04 nt!KeDelayExecutionThread

1: kd> dx -id 0,0,89831250 -r1 ((basesrv!_KPRCB *)0xf7737120)

((basesrv!_KPRCB *)0xf7737120) : 0xf7737120 [Type: _KPRCB *]

+0x000\] MinorVersion : 0x1 \[Type: unsigned short

+0x002\] MajorVersion : 0x1 \[Type: unsigned short

+0x004\] CurrentThread : 0x8952bc18 \[Type: _KTHREAD \*

+0x008\] NextThread : 0x0 \[Type: _KTHREAD \*

+0x00c\] IdleThread : 0xf7739fa0 \[Type: _KTHREAD \*

+0x928\] ReadySummary : 0x0 \[Type: unsigned long

1: kd> kc

00 nt!KiDispatchInterrupt

01 hal!HalpDispatchInterrupt

02 hal!KfLowerIrql

03 nt!KiSwapThread

04 nt!KeDelayExecutionThread

05 nt!NtDelayExecution

06 nt!_KiSystemService

07 SharedUserData!SystemCallStub

08 ntdll!ZwDelayExecution

09 KERNEL32!SleepEx

0a KERNEL32!Sleep

WARNING: Frame IP not in any known module. Following frames may be wrong.

0b 0x0

0c 0x0

0d KERNEL32!BaseThreadStart

1: kd> .process

Implicit process is now 89802bf8

1: kd> !process 0 0

**** NT ACTIVE PROCESS DUMP ****

PROCESS 899a2278 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000

DirBase: 0a200000 ObjectTable: e1000e38 HandleCount: 319.

Image: System

PROCESS 89802bf8 SessionId: 0 Cid: 04b4 Peb: 7ffdf000 ParentCid: 01f4

DirBase: 7a00c000 ObjectTable: e164aa80 HandleCount: 165.

Image: msdtc.exe

1: kd> p

eax=00000041 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00727 esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0x7:

80b00727 fa cli

1: kd> p

eax=00000041 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00728 esp=ba582c1c ebp=ba582c20 iopl=0 nv up di pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

nt!KiDispatchInterrupt+0x8:

80b00728 8b838c090000 mov eax,dword ptr [ebx+98Ch] ds:0023:f773798c=00000000

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b0072e esp=ba582c1c ebp=ba582c20 iopl=0 nv up di pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

nt!KiDispatchInterrupt+0xe:

80b0072e 0b83c8090000 or eax,dword ptr [ebx+9C8h] ds:0023:f77379c8=00000000

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00734 esp=ba582c1c ebp=ba582c20 iopl=0 nv up di pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

nt!KiDispatchInterrupt+0x14:

80b00734 0b83500b0000 or eax,dword ptr [ebx+0B50h] ds:0023:f7737b50=00000000

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b0073a esp=ba582c1c ebp=ba582c20 iopl=0 nv up di pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

nt!KiDispatchInterrupt+0x1a:

80b0073a 741e je nt!KiDispatchInterrupt+0x3a (80b0075a) [br=1]

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b0075a esp=ba582c1c ebp=ba582c20 iopl=0 nv up di pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

nt!KiDispatchInterrupt+0x3a:

80b0075a fb sti

1: kd> p

Breakpoint 45 hit

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b0075b esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0x3b:

80b0075b 80bbe109000000 cmp byte ptr [ebx+9E1h],0 ds:0023:f77379e1=00

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00762 esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0x42:

80b00762 7577 jne nt!KiDispatchInterrupt+0xbb (80b007db) [br=0]

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b00764 esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0x44:

80b00764 83bb2801000000 cmp dword ptr [ebx+128h],0 ds:0023:f7737128=00000000

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b0076b esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0x4b:

80b0076b 746d je nt!KiDispatchInterrupt+0xba (80b007da) [br=1]

1: kd> p

eax=00000000 ebx=f7737000 ecx=8952bc18 edx=80010031 esi=00000000 edi=804edc60

eip=80b007da esp=ba582c1c ebp=ba582c20 iopl=0 nv up ei pl zr na pe nc

cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

nt!KiDispatchInterrupt+0xba:

80b007da c3 ret

没有任何任务需要做。

相关推荐
sitelist2 天前
nt!KiSwapThread函数分析之CurrentPrcb->NextThread == NULL的情况下KiSelectReadyThread选出新线程
kiswapthread·nextthread·kiselectready