阅读:1570回复:2
有谁知道KiSwapThread()函数在ntos的那个原文件中??
如标题
thx !!!!!! |
|
沙发#
发布于:2004-02-23 09:02
;++
; ; VOID ; KiSwapThread ( ; VOID ; ) ; ; Routine Description: ; ; This routine is called to select the next thread to run on the ; current processor and to perform a context switch to the thread. ; ; Arguments: ; ; None. ; ; Return Value: ; ; Wait completion status (eax). ; ;-- cPublicFastCall KiSwapThread, 0 .fpo (0, 0, 0, 4, 1, 0) ; ; 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, 4*4 mov [esp+12], ebx ; save registers mov [esp+8], esi ; mov [esp+4], edi ; mov [esp+0], ebp ; mov ebx, PCR[PcSelfPcr] ; get address of PCR mov edx, [ebx].PcPrcbData.PbNextThread ; get next thread address or edx, edx ; check if next thread selected jnz Swt140 ; if nz, next thread selected ; ; Find the highest nibble in the ready summary that contains a set bit ; and left justify so the nibble is in bits <31:28> ; mov ecx, 16 ; set base bit number mov edi, _KiReadySummary ; get ready summary mov esi, edi ; copy ready summary shr esi, 16 ; isolate bits <31:16> of summary jnz short Swt10 ; if nz, bits <31:16> are nonzero xor ecx, ecx ; set base bit number mov esi, edi ; set bits <15:0> of summary Swt10: shr esi, 8 ; isolate bits <15:8> of low bits jz short Swt20 ; if z, bits <15:8> are zero add ecx, 8 ; add offset to nonzero byte Swt20: mov esi, edi ; isolate highest nonzero byte shr esi, cl ; add ecx, 3 ; adjust to high bit of nibble cmp esi, 10h ; check if high nibble nonzero jb short Swt30 ; if b, then high nibble is zero add ecx, 4 ; compute ready queue priority Swt30: mov esi, ecx ; left justify ready summary nibble not ecx ; shl edi, cl ; or edi, edi ; ; ; If the next bit is set in the ready summary, then scan the corresponding ; dispatcher ready queue. ; Swt40: js short Swt60 ; if s, queue contains an entry Swt50: sub esi, 1 ; decrement ready queue priority shl edi, 1 ; position next ready summary bit jnz short Swt40 ; if nz, more queues to scan ; ; All ready queues were scanned without finding a runnable thread so ; default to the idle thread and set the appropriate bit in idle summary. ; ifdef _COLLECT_SWITCH_DATA_ inc _KeThreadSwitchCounters + TwSwitchToIdle ; increment counter endif ifdef NT_UP mov _KiIdleSummary, 1 ; set idle summary bit else mov eax, [ebx].PcPrcbData.PbSetMember ; get processor set member or _KiIdleSummary, eax ; set idle summary bit endif mov edx, [ebx].PcPrcbData.PbIdleThread ; set idle thread address jmp Swt140 ; ; ; If the thread can execute on the current processor, then remove it from ; the dispatcher ready queue. ; align 4 swt60: lea ebp, [esi*8] + _KiDispatcherReadyListHead ; get ready queue address mov ecx, [ebp].LsFlink ; get address of first queue entry Swt70: mov edx, ecx ; compute address of thread object sub edx, ThWaitListEntry ; ifndef NT_UP mov eax, [edx].ThAffinity ; get thread affinity test eax, [ebx].PcPrcbData.PbSetMember ; test if compatible affinity jnz short Swt80 ; if nz, thread affinity compatible mov ecx, [ecx].LsFlink ; get address of next entry cmp ebp, ecx ; check if end of list jnz short Swt70 ; if nz, not end of list jmp short Swt50 ; ; ; If the thread last ran on the current processor, has been waiting for ; longer than a quantum, or its priority is greater than low realtime ; plus 9, then select the thread. Otherwise, an attempt is made to find ; a more appropriate candidate. ; align 4 Swt80: cmp _KiThreadSelectNotifyRoutine, 0 ; check for callout routine je short Swt85 ; if eq, no callout routine registered push edx ; save volatile registers push ecx ; mov ecx, [edx].EtCid.CidUniqueThread ; set trial thread unique id call [_KiThreadSelectNotifyRoutine] ; notify callout routine pop ecx ; restore volatile registers pop edx ; or eax, eax ; check if trial thread selectable jnz Swt120 ; if nz, trial thread selectable jmp Swt87 ; align 4 Swt85: mov al, [edx].ThNextProcessor ; get last processor number cmp al, [ebx].PcPrcbData.PbNumber ; check if current processor jz Swt120 ; if z, same as current processor mov al, [edx].ThIdealProcessor ; get ideal processor number cmp al, [ebx].PcPrcbData.PbNumber ; check if current processor jz short Swt120 ; if z, same as current processor Swt87: cmp esi, LOW_REALTIME_PRIORITY + 9 ; check if priority in range jae short Swt120 ; if ae, priority not in range mov edi, _KeTickCount + 0 ; get low part of tick count sub edi, [edx].ThWaitTime ; compute length of wait cmp edi, READY_SKIP_QUANTUM + 1 ; check if wait time exceeded jae short Swt120 ; if ae, wait time exceeded mov edi, edx ; set address of thread ; ; Search forward in the ready queue until the end of the list is reached ; or a more appropriate thread is found. ; Swt90: mov edi, [edi].ThWaitListEntry ; get address of next entry cmp ebp, edi ; check if end of list jz short Swt120 ; if z, end of list sub edi, ThWaitListEntry ; compute address of thread mov eax, [edi].ThAffinity ; get thread affinity test eax, [ebx].PcPrcbData.PbSetMember ; test if compatible infinity jz short Swt100 ; if z, thread affinity not compatible cmp _KiThreadSelectNotifyRoutine, 0 ; check for callout routine je short Swt95 ; if eq, no callout routine registered push edx ; save volatile registers push ecx ; mov ecx, [edi].EtCid.CidUniqueThread ; set trial thread unique id call [_KiThreadSelectNotifyRoutine] ; notify callout routine pop ecx ; restore volatile registers pop edx ; or eax, eax ; check if trial thread selectable jnz short Swt110 ; if nz, trial thread selectable jmp short Swt100 ; align 4 Swt95: mov al, [edi].ThNextProcessor ; get last processor number cmp al, [ebx].PcPrcbData.PbNumber ; check if current processor jz short Swt110 ; if z, same as current processor mov al, [edi].ThIdealProcessor ; get ideal processor number cmp al, [ebx].PcPrcbData.PbNumber ; check if current processor jz short Swt110 ; if z, same as current processor Swt100: mov eax, _KeTickCount + 0 ; get low part of tick count sub eax, [edi].ThWaitTime ; compute length of wait cmp eax, READY_SKIP_QUANTUM + 1 ; check if wait time exceeded jb short Swt90 ; if b, wait time not exceeded jmp short Swt120 ; align 4 Swt110: mov edx, edi ; set address of thread mov ecx, edi ; compute address of list entry add ecx, ThWaitListEntry ; Swt120: mov al, [ebx].PcPrcbData.PbNumber ; get current processor number ifdef _COLLECT_SWITCH_DATA_ lea ebp, _KeThreadSwitchCounters + TwFindIdeal ; get counter address cmp al, [edx].ThIdealProcessor ; check if same as ideal processor jz short Swt130 ; if z, same as ideal processor add ebp, TwFindLast - TwFindIdeal ; compute address of last counter cmp al, [edx].ThNextProcessor ; check if same as last processor jz short Swt130 ; if z, same as last processor add ebp,TwFindAny - TwFindLast ; compute address of correct counter Swt130: inc dword ptr [ebp] ; increment appropriate switch counter endif mov [edx].ThNextProcessor, al ; set next processor number endif ; ; Remove the selected thread from the ready queue. ; mov eax, [ecx].LsFlink ; get list entry forward link mov ebp, [ecx].LsBlink ; get list entry backward link mov [ebp].LsFlink, eax ; set forward link in previous entry mov [eax].LsBlink, ebp ; set backward link in next entry cmp eax, ebp ; check if list is empty jnz short Swt140 ; if nz, list is not empty mov ebp, 1 ; clear ready summary bit mov ecx, esi ; shl ebp, cl ; xor _KiReadySummary, ebp ; ; ; Swap context to the next thread. ; Swt140: mov esi, edx ; set address of next thread mov edi, [ebx].PcPrcbData.PbCurrentThread ; set current thread address mov dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread address mov [ebx].PcPrcbData.PbCurrentThread, esi ; set current thread address mov cl, [edi].ThWaitIrql ; set APC interrupt bypass disable call SwapContext ; swap context or al, al ; check if kernel APC pending mov edi, [esi].ThWaitStatus ; save wait completion status mov cl, [esi].ThWaitIrql ; get wait IRQL jnz short Swt160 ; if nz, kernel APC pending Swt150: fstCall KfLowerIrql ; lower IRQL to previous value mov eax, edi ; set wait completion status mov ebp, [esp+0] ; restore registers mov edi, [esp+4] ; mov esi, [esp+8] ; mov ebx, [esp+12] ; add esp, 4*4 ; fstRET KiSwapThread ; Swt160: mov cl, APC_LEVEL ; lower IRQL to APC level fstCall KfLowerIrql ; xor eax, eax ; set previous mode to kernel stdCall _KiDeliverApc, <eax, eax, eax> ; deliver kernel mode APC inc dword ptr [ebx].PcPrcbData.PbApcBypassCount ; increment count xor ecx, ecx ; set original wait IRQL jmp short Swt150 fstENDP KiSwapThread |
|
|
板凳#
发布于:2004-02-28 17:01
非常感谢!!!,其实用source insight 收一下就可以了
该函数在windows_2000_source_code\\win2k\\private\\ntos\\ke\\i386\\ctxswap.asm文件中。 [编辑 - 2/28/04 by robin12] |
|