KiSelectReadyThread函数分析之nt!KiPriorityMask数组和nt!KiFindFirstSetLeft数组的关系

KiSelectReadyThread函数分析之nt!KiPriorityMask数组和nt!KiFindFirstSetLeft数组的关系

第0部分:

VOID

KiQuantumEnd (

VOID

)

{

} else {

Thread->Quantum = Process->ThreadQuantum;

//

// Compute the new thread priority and attempt to reschedule the

// current processor.

//

// N.B. The new priority will never be greater than the previous

// priority.

//

Thread->Priority = KiComputeNewPriority(Thread, 1);

if (Prcb->NextThread == NULL) {

if ((NewThread = KiSelectReadyThread(Thread->Priority, Prcb)) != NULL) {

第1部分:

FORCEINLINE

PKTHREAD

KiSelectReadyThread (

IN KPRIORITY LowPriority,

IN PKPRCB Prcb

)

{

ULONG HighPriority;

PRLIST_ENTRY ListEntry;

ULONG PrioritySet;

PKTHREAD Thread;

//

// Compute the set of priority levels that should be scanned in an attempt

// to find a thread that can run on the current processor.

//

PrioritySet =**KiPriorityMask[**LowPriority] & Prcb->ReadySummary;

Thread = NULL;

if (PrioritySet != 0) {

KeFindFirstSetLeftMember(PrioritySet, &HighPriority);

第2部分:

0: kd> x nt!KiPriorityMask

80a05f30 nt!KiPriorityMask = unsigned long []

80a05f30 nt!KiPriorityMask = unsigned long [32]

80a05f30 nt!KiPriorityMask = unsigned long []

0: kd> dx -r1 (*((ntkrnlmp!unsigned long (*)[32])0x80a05f30))

(*((ntkrnlmp!unsigned long (*)[32])0x80a05f30)) [Type: unsigned long [32]]

0\] : 0xffffffff \[Type: unsigned long

1\] : 0xfffffffe \[Type: unsigned long

2\] : 0xfffffffc \[Type: unsigned long

3\] : 0xfffffff8 \[Type: unsigned long

4\] : 0xfffffff0 \[Type: unsigned long

5\] : 0xffffffe0 \[Type: unsigned long

6\] : 0xffffffc0 \[Type: unsigned long

7\] : 0xffffff80 \[Type: unsigned long

8\] : 0xffffff00 \[Type: unsigned long

9\] : 0xfffffe00 \[Type: unsigned long

10\] : 0xfffffc00 \[Type: unsigned long

11\] : 0xfffff800 \[Type: unsigned long

12\] : 0xfffff000 \[Type: unsigned long

13\] : 0xffffe000 \[Type: unsigned long

14\] : 0xffffc000 \[Type: unsigned long

15\] : 0xffff8000 \[Type: unsigned long

16\] : 0xffff0000 \[Type: unsigned long

17\] : 0xfffe0000 \[Type: unsigned long

18\] : 0xfffc0000 \[Type: unsigned long

19\] : 0xfff80000 \[Type: unsigned long

20\] : 0xfff00000 \[Type: unsigned long

21\] : 0xffe00000 \[Type: unsigned long

22\] : 0xffc00000 \[Type: unsigned long

23\] : 0xff800000 \[Type: unsigned long

24\] : 0xff000000 \[Type: unsigned long

25\] : 0xfe000000 \[Type: unsigned long

26\] : 0xfc000000 \[Type: unsigned long

27\] : 0xf8000000 \[Type: unsigned long

28\] : 0xf0000000 \[Type: unsigned long

29\] : 0xe0000000 \[Type: unsigned long

30\] : 0xc0000000 \[Type: unsigned long

31\] : 0x80000000 \[Type: unsigned long

0: kd> dt kTHREAD 8999e620

CSRSRV!KTHREAD

+0x05b Priority : 13 '' 当前线程的优先级为13

13\] : 0xffffe000 \[Type: unsigned long

1111 1111 1111 1111 1110 0000 0000 0000 正好13个0。

从第13位到31位的,都可以选到。优先级为13到优先级31的线程都能被选到。

第3部分:找到一个32位整数的第一个为1的位的位置索引。

KeFindFirstSetLeftMember

#define KeFindFirstSetLeftMember(Set, Member) { \

ULONG _Mask; \

ULONG _Offset = 16; \

if ((_Mask = Set >> 16) == 0) { \

_Offset = 0; \

_Mask = Set; \

} \

if (_Mask >> 8) { \

_Offset += 8; \

} \

*(Member) = KiFindFirstSetLeft[Set >> _Offset] + _Offset; \

}

例子:0x10 00 00 00

0001 0000 0000 0000 0000 0000 0000 0000

第一步判断在高16位还是低16位,右移16位为0说明在低16位,_offset应该设置为0,否则在高16位,不用变化_offset。

if ((_Mask = Set >> 16) == 0) { \ 表示Set变量右移16为赋值给_Mask变量,[Set变量不会有变化]。

_Offset = 0; \

_Mask = Set; \

}

不符合条件,说明在高16位,_Offset = 16,不变。

_Mask=0x10 00

第一步判断选出来的mask中在高8位还是低8位

if (_Mask >> 8) { \

_Offset += 8; \

}

_Mask >> 8后为0x10,_offset=24

0x10

0001 0000

KiFindFirstSetLeft[0x10]=04 0001 0000最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x11]=04 0001 0001最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x12]=04 0001 0010最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x13]=04 0001 0011最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x14]=04 0001 0100最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x15]=04 0001 0101最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x16]=04 0001 0110最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x17]=04 0001 0111最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x18]=04 0001 1000最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x19]=04 0001 1001最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1a]=04 0001 1010最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1b]=04 0001 1011最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1c]=04 0001 1100最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1d]=04 0001 1101最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1e]=04 0001 1110最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x1f]=04 0001 1111最左边第一个为1的位是第四位。

KiFindFirstSetLeft[0x20]=05

0: kd> x nt!KiFindFirstSetLeft

80a05db0 nt!KiFindFirstSetLeft = char [256] ""

0: kd> dx -r1 (*((ntkrnlmp!char (*)[256])0x80a05db0))

(*((ntkrnlmp!char (*)[256])0x80a05db0)) : "" [Type: char [256]]

0: kd> db 80a05db0

80a05db0 00 00 01 01 02 02 02 02-03 03 03 03 03 03 03 03 ................

80a05dc0 04 04 04 04 04 04 04 04-04 04 04 04 04 04 04 04 ................

80a05dd0 05 05 05 05 05 05 05 05-05 05 05 05 05 05 05 05 ................

80a05de0 05 05 05 05 05 05 05 05-05 05 05 05 05 05 05 05 ................

80a05df0 06 06 06 06 06 06 06 06-06 06 06 06 06 06 06 06 ................

80a05e00 06 06 06 06 06 06 06 06-06 06 06 06 06 06 06 06 ................

80a05e10 06 06 06 06 06 06 06 06-06 06 06 06 06 06 06 06 ................

80a05e20 06 06 06 06 06 06 06 06-06 06 06 06 06 06 06 06 ................

0: kd> db 80a05db0+80

80a05e30 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e40 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e50 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e60 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e70 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e80 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05e90 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

80a05ea0 07 07 07 07 07 07 07 07-07 07 07 07 07 07 07 07 ................

2个 2个 4个 8个 16个 32个 64个 128个
0 1 2 3 4 5 6 7

最终结果是24+4=28位,正确。

0 0 0 1 0 0 0 0

31位 30位 29位 28位