news 2026/5/16 19:55:12

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/5/12 11:23:14

32、实用编程工具:拼写检查器与索引生成器详解

实用编程工具:拼写检查器与索引生成器详解 在编程和文档处理的领域中,有两个非常实用的工具值得我们深入探讨,它们分别是拼写检查器 spellcheck.awk 和索引生成器 masterindex 。这两个工具在不同的场景下都能发挥巨大的作用,帮助我们提高工作效率和文档质量。 拼写检…

作者头像 李华
网站建设 2026/5/16 7:25:09

绵阳口腔医院服务商

绵阳口腔医院的技术探索与科雅口腔的专业实践绵阳口腔医院在发展过程中面临着一些技术挑战&#xff0c;如治疗精度不够、患者体验有待提升等。绵阳科雅口腔门诊部针对这些问题提供了专业解决方案。科雅口腔采用先进的数字化口腔技术&#xff0c;通过口腔扫描仪获取患者口腔的精…

作者头像 李华
网站建设 2026/5/8 20:59:19

Kotaemon如何防止误导性总结?关键细节保留策略

Kotaemon如何防止误导性总结&#xff1f;关键细节保留策略 在智能客服、法律咨询和医疗辅助等高风险场景中&#xff0c;一个看似合理的错误回答可能带来严重后果。比如将“合同有效期至2025年12月31日”概括为“长期有效”&#xff0c;或把“利率下调0.5个百分点”描述成“大幅…

作者头像 李华
网站建设 2026/5/12 4:23:39

Kotaemon支持Docker部署吗?一键启动脚本已开源

Kotaemon支持Docker部署吗&#xff1f;一键启动脚本已开源 在AI应用快速落地的今天&#xff0c;一个棘手的问题始终困扰着开发者&#xff1a;为什么同一个模型代码&#xff0c;在开发机上跑得好好的&#xff0c;一到测试或生产环境就“水土不服”&#xff1f;依赖版本冲突、系统…

作者头像 李华
网站建设 2026/5/12 17:13:12

Win空格预览工具!图片 视频 PSD 秒看设计必备神器

宝子们&#xff01;Windows 党终于不用羡慕 Mac 的空格预览了&#xff5e; 断更近两年的神器 QuickLook 4.0 强势回归&#xff0c;修复 bug 后更流畅&#xff0c;核心功能依旧能打&#xff01;软件下载地址 操作超简单&#xff1a;单击选中文件按空格&#xff0c;图片、音频、…

作者头像 李华
网站建设 2026/5/12 17:13:12

350页pdf!大模型基础教材发布,开源!

大模型技术日新月异&#xff0c;想系统学习却不知从从何入手&#xff1f;面对海量论文、代码和教程&#xff0c;是不是总觉得知识体系零零散散&#xff1f;别慌&#xff01;今天给大家推荐一本由中国人民大学AI Box团队倾力编写的《大语言模型》中文权威教材&#xff0c;帮你一…

作者头像 李华