news 2026/3/25 21:39:53

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/3/22 22:02:01

30、脚本杂谈:转置、宏处理器与sed命令速览

脚本杂谈:转置、宏处理器与sed命令速览 在编程的世界里,有许多实用的脚本和工具能帮助我们更高效地处理数据和完成任务。本文将介绍几个有趣的脚本,包括转置脚本、m1宏处理器以及sed命令的相关内容。 转置脚本 首先来看一个简单而有趣的转置脚本示例: $ transpose tes…

作者头像 李华
网站建设 2026/3/14 13:21:30

单价30元,月入百万!药食同源如何打造中老年睡眠经济新爆品?

一颗酸枣仁的药食同源生意作者 | AgeClub任子勋前言“想睡却睡不着&#xff0c;闭上眼在床上翻来覆去一整夜。”不少银发族在生活中面临类似处境。中国睡眠研究会发布的《2025年中国睡眠健康调查报告》显示&#xff0c;随着年龄增长&#xff0c;人们的睡眠困扰显著提升。65岁以…

作者头像 李华
网站建设 2026/3/23 7:27:41

法律咨询助手开发手记:Kotaemon是如何赋能专业领域的?

法律咨询助手开发手记&#xff1a;Kotaemon是如何赋能专业领域的&#xff1f; 在律师事务所的咨询台前&#xff0c;一位当事人反复询问&#xff1a;“我这种情况能赔多少&#xff1f;”而律师却不得不花半小时翻查判例、核对法条。这样的场景每天都在上演——法律服务的需求高度…

作者头像 李华
网站建设 2026/3/24 12:48:10

Kotaemon支持会话导出为报告,适用于审计场景

Kotaemon支持会话导出为报告&#xff0c;适用于审计场景 在银行客服回访一起贷款咨询时&#xff0c;合规部门突然提出要求&#xff1a;不仅要查看聊天记录&#xff0c;还要证明系统给出的利率信息确实来自最新版政策文件。这类场景如今已不再罕见——随着AI在金融、医疗、法务等…

作者头像 李华
网站建设 2026/3/24 22:21:10

Kotaemon装修设计方案建议:风格匹配与预算控制

Kotaemon&#xff1a;构建可信智能对话系统的核心实践 在企业智能化转型的浪潮中&#xff0c;客户对服务响应速度、准确性和个性化体验的要求正以前所未有的速度攀升。传统的聊天机器人往往止步于关键词匹配或固定流程应答&#xff0c;面对复杂业务场景时显得力不从心——答案不…

作者头像 李华