news 2026/6/22 20:30:33

nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

align 16
cPublicProc _KiDispatchInterrupt ,0
cPublicFpo 0, 0

mov ebx, PCR[PcSelfPcr] ; get address of PCR


。。。

;
; Check to determine if quantum end is requested.
;
; N.B. If a new thread is selected as a result of processing the quantum
; end request, then the new thread is returned with the dispatcher
; database locked. Otherwise, NULL is returned with the dispatcher
; database unlocked.
;

kdi40: sti ; enable interrupts
cmp byte ptr [ebx].PcPrcbData.PbQuantumEnd, 0 ; quantum end requested
jne kdi90 ; if neq, quantum end request

;
; Check to determine if a new thread has been selected for execution on this
; processor.
;

cmp dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; check if next thread
je kdi70 ; if eq, then no new thread

;
; N.B. The following registers MUST be saved such that ebp is saved last.
; This is done so the debugger can find the saved ebp for a thread
; that is not currently in the running state.
;
sub esp, 3*4
mov [esp+8], esi ; save registers
mov [esp+4], edi ;
mov [esp+0], ebp ;
mov edi, [ebx].PcPrcbData.PbCurrentThread ; get current thread address (as old thread)

;
; Raise IRQL to SYNCH level, set context swap busy for the old thread, and
; acquire the current PRCB lock.
;

ifndef NT_UP

call dword ptr [__imp__KeRaiseIrqlToSynchLevel@0] ; raise IRQL to SYNCH
mov byte ptr [edi].ThSwapBusy, 1 ; set context swap busy
lea ecx, [ebx].PcPrcbData.PbPrcbLock ; get PRCB lock address
lock bts dword ptr [ecx], 0 ; try to acquire PRCB lock
jnc short kdi50 ; if nc, PRCB lock acquired
fstCall KefAcquireSpinLockAtDpcLevel ; acquire current PRCB lock

endif

;
; Get the next thread address, set the thread state to running, queue the old
; running thread, and swap context to the next thread.
;

kdi50: mov esi, [ebx].PcPrcbData.PbNextThread ; get next thread address
and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread address
mov [ebx].PcPrcbData.PbCurrentThread, esi ; set current thread address
mov byte ptr [esi]+ThState, Running ; set thread state to running
mov byte ptr [edi].ThWaitReason, WrDispatchInt ; set wait reason
mov ecx, edi ; set address of curent thread
lea edx, [ebx].PcPrcbData ; set address of PRCB
fstCall KiQueueReadyThread ; ready thread for execution
CAPSTART <_KiDispatchInterrupt,SwapContext>
mov cl, APC_LEVEL ; set APC interrupt bypass disable
call SwapContext ; swap context

。。。

;
; Process quantum end event.
;
; N.B. If the quantum end code returns a NULL value, then no next thread
; has been selected for execution. Otherwise, a next thread has been
; selected and the source thread lock has been acquired.
;

kdi90: mov byte ptr [ebx].PcPrcbData.PbQuantumEnd, 0 ; clear quantum end indicator
CAPSTART <_KiDispatchInterrupt,_KiQuantumEnd@0>
stdCall _KiQuantumEnd ; process quantum end
CAPEND <_KiDispatchInterrupt>
stdRET _KiDispatchInterrupt ; return

第二部分:

VOID
KiQuantumEnd (
VOID
)
Routine Description:

This function is called when a quantum end event occurs on the current
processor. Its function is to determine whether the thread priority should
be decremented and whether a redispatch of the processor should occur.
当当前处理器上发生量子结束事件时,会调用此函数。
它的功能是确定是否应该降低线程优先级,以及是否应该重新分配处理器。

VOID
FASTCALL
KiQueueReadyThread (
IN PKTHREAD Thread,
IN PKPRCB Prcb
)
{

KxQueueReadyThread(Thread, Prcb);
return;
}


FORCEINLINE
VOID
KxQueueReadyThread (
IN PKTHREAD Thread,
IN PKPRCB Prcb
)

{

BOOLEAN Preempted;
KPRIORITY Priority;

ASSERT(Prcb == KeGetCurrentPrcb());
ASSERT(Thread->State == Running);
ASSERT(Thread->NextProcessor == Prcb->Number);

//
// If the thread can run on the specified processor, then insert the
// thread in the appropriate dispatcher ready queue for the specified
// processor and release the specified PRCB lock. Otherwise, release
// the specified PRCB lock and ready the thread for execution.
//

#if !defined(NT_UP)

if ((Thread->Affinity & Prcb->SetMember) != 0) {

#endif

Thread->State = Ready;
Preempted = Thread->Preempted;
Thread->Preempted = FALSE;
Thread->WaitTime = KiQueryLowTickCount();
Priority = Thread->Priority;

ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));

if (Preempted != FALSE) {
InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry);

} else {
InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry);
}

Prcb->ReadySummary |= PRIORITY_MASK(Priority);

ASSERT(Priority == Thread->Priority);

KiReleasePrcbLock(Prcb);

#if !defined(NT_UP)

} else {
Thread->State = DeferredReady;
Thread->DeferredProcessor = Prcb->Number;
KiReleasePrcbLock(Prcb);
KiDeferredReadyThread(Thread);
}

#endif

return;
}

第三部分:

如果[ebx].PcPrcbData.PbNextThread=0则跳转到
kdi70: stdRET _KiDispatchInterrupt ; return
结束了,如果不为0则进行线程切换,
所以PcPrcbData.PbNextThread得真正含义是等待当前线程时间片用完就切换到NextThread

要切换到NextThread,需要两个条件,第一个是时间片用完,第二个是NextThread已经被选出来了。

;
; Check to determine if a new thread has been selected for execution on this
; processor.
;

cmp dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; check if next thread
je kdi70 ; if eq, then no new thread

;
; N.B. The following registers MUST be saved such that ebp is saved last.
; This is done so the debugger can find the saved ebp for a thread
; that is not currently in the running state.
;

.fpo (0, 0, 0, 3, 1, 0)

sub esp, 3*4
mov [esp+8], esi ; save registers
mov [esp+4], edi ;
mov [esp+0], ebp ;
mov edi, [ebx].PcPrcbData.PbCurrentThread ; get current thread address (as old thread)

;
; Raise IRQL to SYNCH level, set context swap busy for the old thread, and
; acquire the current PRCB lock.
;

ifndef NT_UP

call dword ptr [__imp__KeRaiseIrqlToSynchLevel@0] ; raise IRQL to SYNCH
mov byte ptr [edi].ThSwapBusy, 1 ; set context swap busy
lea ecx, [ebx].PcPrcbData.PbPrcbLock ; get PRCB lock address
lock bts dword ptr [ecx], 0 ; try to acquire PRCB lock
jnc short kdi50 ; if nc, PRCB lock acquired
fstCall KefAcquireSpinLockAtDpcLevel ; acquire current PRCB lock

endif

;
; Get the next thread address, set the thread state to running, queue the old
; running thread, and swap context to the next thread.
;

kdi50: mov esi, [ebx].PcPrcbData.PbNextThread ; get next thread address
and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread address
mov [ebx].PcPrcbData.PbCurrentThread, esi ; set current thread address
mov byte ptr [esi]+ThState, Running ; set thread state to running
mov byte ptr [edi].ThWaitReason, WrDispatchInt ; set wait reason
mov ecx, edi ; set address of curent thread
lea edx, [ebx].PcPrcbData ; set address of PRCB
fstCall KiQueueReadyThread ; ready thread for execution
CAPSTART <_KiDispatchInterrupt,SwapContext>
mov cl, APC_LEVEL ; set APC interrupt bypass disable
call SwapContext ; swap context
CAPEND <_KiDispatchInterrupt>
mov ebp, [esp+0] ; restore registers
mov edi, [esp+4] ;
mov esi, [esp+8] ;
add esp, 3*4
kdi70: stdRET _KiDispatchInterrupt ; return

第四部分:

1: kd> g
Breakpoint 14 hit
eax=00000041 ebx=f78e6d48 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00720 esp=f78e6c9c ebp=f78e6ca0 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> x nt!KiQueueReadyThread
80a4412e nt!KiQueueReadyThread (struct _KTHREAD *, struct _KPRCB *)
1: kd> bp nt!KiQueueReadyThread
breakpoint 38 redefined
1: kd> dx -id 0,0,8954e020 -r1 ((ntkrnlmp!_KPRCB *)0xf7737120)
((ntkrnlmp!_KPRCB *)0xf7737120) : 0xf7737120 [Type: _KPRCB *]
[+0x000] MinorVersion : 0x1 [Type: unsigned short]
[+0x002] MajorVersion : 0x1 [Type: unsigned short]
[+0x004] CurrentThread : 0x8999d620 [Type: _KTHREAD *]
[+0x008] NextThread : 0x0 [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,8954e020 -r1 (*((ntkrnlmp!_KDPC_DATA (*)[2])0xf7737980))
(*((ntkrnlmp!_KDPC_DATA (*)[2])0xf7737980)) [Type: _KDPC_DATA [2]]
[0] [Type: _KDPC_DATA]
[1] [Type: _KDPC_DATA]
1: kd> dx -id 0,0,8954e020 -r1 (*((ntkrnlmp!_KDPC_DATA *)0xf7737980))
(*((ntkrnlmp!_KDPC_DATA *)0xf7737980)) [Type: _KDPC_DATA]
[+0x000] DpcListHead [Type: _LIST_ENTRY]
[+0x008] DpcLock : 0x0 [Type: unsigned long]
[+0x00c] DpcQueueDepth : 0x0 [Type: unsigned long]
[+0x010] DpcCount : 0xbb6 [Type: unsigned long]
1: kd> dx -id 0,0,8954e020 -r1 (*((ntkrnlmp!_SINGLE_LIST_ENTRY *)0xf7737b50))
(*((ntkrnlmp!_SINGLE_LIST_ENTRY *)0xf7737b50)) [Type: _SINGLE_LIST_ENTRY]
[+0x000] Next : 0x0 [Type: _SINGLE_LIST_ENTRY *]

1: kd> p
eax=00000041 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00727 esp=f78e6c9c ebp=f78e6ca0 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> !irql
Debugger saved IRQL for processor 0x1 -- 2 (DISPATCH_LEVEL)
1: kd> p
eax=00000041 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00728 esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0072e esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00734 esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0073a esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0075a esp=f78e6c9c ebp=f78e6ca0 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
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0075b esp=f78e6c9c ebp=f78e6ca0 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> bp 80b0075b
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00762 esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00764 esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0076b esp=f78e6c9c ebp=f78e6ca0 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=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b007da esp=f78e6c9c ebp=f78e6ca0 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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/13 11:59:58

31、Awk脚本语言快速参考指南

Awk脚本语言快速参考指南 1. 命令行语法 调用awk有两种基本形式: - awk [-v var=value] [-F re] [--] ’pattern { action }’ var=value datafile(s) - awk [-v var=value] [-F re] -f scriptfile [--] var=value datafile(s) awk命令行由命令、脚本和输入文件名组成…

作者头像 李华
网站建设 2026/6/22 0:03:52

Kotaemon如何平衡速度与精度?检索-重排协同机制

Kotaemon如何平衡速度与精度&#xff1f;检索-重排协同机制 在构建企业级智能问答系统时&#xff0c;我们常面临一个棘手的权衡&#xff1a;用户希望答案来得快&#xff0c;又要求内容足够准确。尤其在金融、医疗等高敏感领域&#xff0c;哪怕0.5秒的延迟或一次轻微的事实偏差&…

作者头像 李华
网站建设 2026/6/23 19:31:12

为什么越来越多开发者选择Kotaemon做知识问答系统?

为什么越来越多开发者选择Kotaemon做知识问答系统&#xff1f; 在企业智能化浪潮中&#xff0c;一个看似简单却长期困扰技术团队的问题正变得愈发紧迫&#xff1a;如何让AI真正“懂”自家的知识&#xff1f;不是靠泛泛而谈的通用模型生成似是而非的答案&#xff0c;而是精准、可…

作者头像 李华
网站建设 2026/6/22 14:47:25

Kotaemon能否用于专利检索?知识产权领域新应用

Kotaemon能否用于专利检索&#xff1f;知识产权领域新应用 在知识产权的世界里&#xff0c;时间就是竞争力。一家科技公司正准备推出新一代固态电池产品&#xff0c;法务团队却面临紧迫任务&#xff1a;必须在两周内完成全球相关专利的排查&#xff0c;避免侵权风险。传统方式下…

作者头像 李华
网站建设 2026/6/23 14:22:03

Kotaemon如何实现多模态输入?图文混合处理展望

Kotaemon如何实现多模态输入&#xff1f;图文混合处理展望 在企业级智能系统日益复杂的今天&#xff0c;用户的问题早已不再局限于纯文字。一张设备故障的照片、一份合同的扫描件、甚至是一段带图示的操作手册截图——这些“图文并茂”的输入正成为现实场景中的常态。传统的文本…

作者头像 李华
网站建设 2026/6/21 20:01:06

18、Web开发技术综合指南

Web开发技术综合指南 1. FastTemplate类详解 FastTemplate是一个在PHP开发中非常实用的模板类,它能帮助开发者更高效地处理模板文件。以下是对其详细的介绍: - 类的定义与属性 : class FastTemplate {var $FILELIST = array(); // 存储文件句柄数组var $DYNAMIC = ar…

作者头像 李华