Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

thredsup.c File Reference

#include "ki.h"

Go to the source code of this file.

Defines

#define KiIncrementSwitchCounter(Member)

Functions

VOID KiSuspendNop (IN PKAPC Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2)
PKTHREAD FASTCALL KiFindReadyThread (IN ULONG Processor, IN KPRIORITY LowPriority)
VOID FASTCALL KiReadyThread (IN PRKTHREAD Thread)
PRKTHREAD FASTCALL KiSelectNextThread (IN PRKTHREAD Thread)
VOID FASTCALL KiSetPriorityThread (IN PRKTHREAD Thread, IN KPRIORITY Priority)
VOID KiSuspendThread (IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)


Define Documentation

#define KiIncrementSwitchCounter Member   ) 
 

Definition at line 44 of file thredsup.c.

Referenced by KiFindReadyThread(), KiReadyThread(), and KiSelectNextThread().


Function Documentation

PKTHREAD FASTCALL KiFindReadyThread IN ULONG  Processor,
IN KPRIORITY  LowPriority
 

Definition at line 95 of file thredsup.c.

References _KTHREAD::Affinity, ASSERT, ClearMember, FALSE, FindFirstSetLeftMember, _KTHREAD::IdealProcessor, KiDispatcherReadyListHead, KiIncrementSwitchCounter, KiReadySummary, KiThreadSelectNotifyRoutine, _KTHREAD::NextProcessor, NULL, READY_SKIP_QUANTUM, _KTHREAD::WaitListEntry, and _KTHREAD::WaitTime.

Referenced by KeDelayExecutionThread(), KiAdjustQuantumThread(), KiQuantumEnd(), KiSelectNextThread(), KiSetPriorityThread(), and NtYieldExecution().

00102 : 00103 00104 This function searches the dispatcher ready queues from the specified 00105 high priority to the specified low priority in an attempt to find a thread 00106 that can execute on the specified processor. 00107 00108 Arguments: 00109 00110 Processor - Supplies the number of the processor to find a thread for. 00111 00112 LowPriority - Supplies the lowest priority dispatcher ready queue to 00113 examine. 00114 00115 Return Value: 00116 00117 If a thread is located that can execute on the specified processor, then 00118 the address of the thread object is returned. Otherwise a null pointer is 00119 returned. 00120 00121 --*/ 00122 00123 { 00124 00125 ULONG HighPriority; 00126 PRLIST_ENTRY ListHead; 00127 PRLIST_ENTRY NextEntry; 00128 ULONG PrioritySet; 00129 KAFFINITY ProcessorSet; 00130 PRKTHREAD Thread; 00131 PRKTHREAD Thread1; 00132 ULONG TickLow; 00133 ULONG WaitTime; 00134 00135 // 00136 // Compute the set of priority levels that should be scanned in an attempt 00137 // to find a thread that can run on the specified processor. 00138 // 00139 00140 PrioritySet = (~((1 << LowPriority) - 1)) & KiReadySummary; 00141 00142 #if !defined(NT_UP) 00143 00144 ProcessorSet = (KAFFINITY)(1 << Processor); 00145 00146 #endif 00147 00148 FindFirstSetLeftMember(PrioritySet, &HighPriority); 00149 ListHead = &KiDispatcherReadyListHead[HighPriority]; 00150 PrioritySet <<= (31 - HighPriority); 00151 while (PrioritySet != 0) { 00152 00153 // 00154 // If the next bit in the priority set is a one, then examine the 00155 // corresponding dispatcher ready queue. 00156 // 00157 00158 if ((LONG)PrioritySet < 0) { 00159 NextEntry = ListHead->Flink; 00160 00161 ASSERT(NextEntry != ListHead); 00162 00163 #if defined(NT_UP) 00164 00165 Thread = CONTAINING_RECORD(NextEntry, KTHREAD, WaitListEntry); 00166 RemoveEntryList(&Thread->WaitListEntry); 00167 if (IsListEmpty(ListHead)) { 00168 ClearMember(HighPriority, KiReadySummary); 00169 } 00170 00171 return (PKTHREAD)Thread; 00172 00173 #else 00174 00175 // 00176 // Scan the specified dispatcher ready queue for a suitable 00177 // thread to execute. 00178 // 00179 00180 while (NextEntry != ListHead) { 00181 Thread = CONTAINING_RECORD(NextEntry, KTHREAD, WaitListEntry); 00182 NextEntry = NextEntry->Flink; 00183 if (Thread->Affinity & ProcessorSet) { 00184 00185 // 00186 // If the found thread ran on the specified processor 00187 // last, the processor is the ideal processor for the 00188 // thread, the thread has been waiting for longer than 00189 // a quantum, or its priority is greater than low realtime 00190 // plus 8, then the selected thread is returned. Otherwise, 00191 // an attempt is made to find a more appropriate thread. 00192 // 00193 00194 TickLow = KiQueryLowTickCount(); 00195 WaitTime = TickLow - Thread->WaitTime; 00196 if ((KiThreadSelectNotifyRoutine ? 00197 (KiThreadSelectNotifyRoutine(((PETHREAD)Thread)->Cid.UniqueThread) == FALSE) : 00198 (((ULONG)Thread->NextProcessor != Processor) && 00199 ((ULONG)Thread->IdealProcessor != Processor))) && 00200 (WaitTime < (READY_SKIP_QUANTUM + 1)) && 00201 (HighPriority < (LOW_REALTIME_PRIORITY + 9))) { 00202 00203 // 00204 // Search forward in the ready queue until the end 00205 // of the list is reached or a more appropriate 00206 // thread is found. 00207 // 00208 00209 while (NextEntry != ListHead) { 00210 Thread1 = CONTAINING_RECORD(NextEntry, 00211 KTHREAD, 00212 WaitListEntry); 00213 00214 NextEntry = NextEntry->Flink; 00215 if ((Thread1->Affinity & ProcessorSet) && 00216 (KiThreadSelectNotifyRoutine ? 00217 (KiThreadSelectNotifyRoutine(((PETHREAD)Thread)->Cid.UniqueThread) != FALSE) : 00218 (((ULONG)Thread1->NextProcessor == Processor) || 00219 ((ULONG)Thread1->IdealProcessor == Processor)))) { 00220 Thread = Thread1; 00221 break; 00222 } 00223 00224 WaitTime = TickLow - Thread1->WaitTime; 00225 if (WaitTime >= (READY_SKIP_QUANTUM + 1)) { 00226 break; 00227 } 00228 } 00229 } 00230 00231 if (Processor == (ULONG)Thread->IdealProcessor) { 00232 KiIncrementSwitchCounter(FindIdeal); 00233 00234 } else if (Processor == (ULONG)Thread->NextProcessor) { 00235 KiIncrementSwitchCounter(FindLast); 00236 00237 } else { 00238 KiIncrementSwitchCounter(FindAny); 00239 } 00240 00241 Thread->NextProcessor = (CCHAR)Processor; 00242 00243 RemoveEntryList(&Thread->WaitListEntry); 00244 if (IsListEmpty(ListHead)) { 00245 ClearMember(HighPriority, KiReadySummary); 00246 } 00247 00248 return (PKTHREAD)Thread; 00249 } 00250 } 00251 00252 #endif 00253 00254 } 00255 00256 HighPriority -= 1; 00257 ListHead -= 1; 00258 PrioritySet <<= 1; 00259 }; 00260 00261 // 00262 // No thread could be found, return a null pointer. 00263 // 00264 00265 return (PKTHREAD)NULL; 00266 }

VOID FASTCALL KiReadyThread IN PRKTHREAD  Thread  ) 
 

Definition at line 270 of file thredsup.c.

References BALANCE_INCREMENT, ClearMember, FALSE, FASTCALL, FindFirstSetLeftMember, _KEVENT::Header, IPI_DPC, KeGetCurrentPrcb, KiDispatcherReadyListHead, KiIdleSummary, KiIncrementSwitchCounter, KiIpiSend(), KiProcessInSwapListHead, KiProcessorBlock, KiReadySummary, KiRequestDispatchInterrupt, KiStackInSwapListHead, KiSwapEvent, KiWaitTest(), NULL, PoSleepingSummary, _KTHREAD::Preempted, _KTHREAD::Priority, ProcessInMemory, ProcessInTransition, ProcessOutOfMemory, Ready, _KPROCESS::ReadyListHead, SetMember, _DISPATCHER_HEADER::SignalState, _KPROCESS::StackCount, Standby, _KPROCESS::State, _KPROCESS::SwapListEntry, Transition, TRUE, and _DISPATCHER_HEADER::WaitListHead.

Referenced by KeDelayExecutionThread(), KeReadyThread(), KeSetAffinityThread(), KiAttachProcess(), KiInsertQueue(), KiInSwapKernelStacks(), KiInSwapProcesses(), KiOutSwapProcesses(), KiScanReadyQueues(), KiSetPriorityThread(), KiUnwaitThread(), NtReplyWaitSendChannel(), and NtSendWaitReplyChannel().

00276 : 00277 00278 This function readies a thread for execution and attempts to immediately 00279 dispatch the thread for execution by preempting another lower priority 00280 thread. If a thread can be preempted, then the specified thread enters 00281 the standby state and the target processor is requested to dispatch. If 00282 another thread cannot be preempted, then the specified thread is inserted 00283 either at the head or tail of the dispatcher ready selected by its priority 00284 acccording to whether it was preempted or not. 00285 00286 Arguments: 00287 00288 Thread - Supplies a pointer to a dispatcher object of type thread. 00289 00290 Return Value: 00291 00292 None. 00293 00294 --*/ 00295 00296 { 00297 00298 PRKPRCB Prcb; 00299 BOOLEAN Preempted; 00300 KPRIORITY Priority; 00301 PRKPROCESS Process; 00302 ULONG Processor; 00303 KPRIORITY ThreadPriority; 00304 PRKTHREAD Thread1; 00305 KAFFINITY IdleSet; 00306 00307 // 00308 // Save value of thread's preempted flag, set thread preempted FALSE, 00309 // capture the thread priority, and set clear the read wait time. 00310 // 00311 00312 Preempted = Thread->Preempted; 00313 Thread->Preempted = FALSE; 00314 ThreadPriority = Thread->Priority; 00315 Thread->WaitTime = KiQueryLowTickCount(); 00316 00317 // 00318 // If the thread's process is not in memory, then insert the thread in 00319 // the process ready queue and inswap the process. 00320 // 00321 00322 Process = Thread->ApcState.Process; 00323 if (Process->State != ProcessInMemory) { 00324 Thread->State = Ready; 00325 Thread->ProcessReadyQueue = TRUE; 00326 InsertTailList(&Process->ReadyListHead, &Thread->WaitListEntry); 00327 if (Process->State == ProcessOutOfMemory) { 00328 Process->State = ProcessInTransition; 00329 InsertTailList(&KiProcessInSwapListHead, &Process->SwapListEntry); 00330 KiSwapEvent.Header.SignalState = 1; 00331 if (IsListEmpty(&KiSwapEvent.Header.WaitListHead) == FALSE) { 00332 KiWaitTest(&KiSwapEvent, BALANCE_INCREMENT); 00333 } 00334 } 00335 00336 return; 00337 00338 } else if (Thread->KernelStackResident == FALSE) { 00339 00340 // 00341 // The thread's kernel stack is not resident. Increment the process 00342 // stack count, set the state of the thread to transition, insert 00343 // the thread in the kernel stack inswap list, and set the kernel 00344 // stack inswap event. 00345 // 00346 00347 Process->StackCount += 1; 00348 Thread->State = Transition; 00349 InsertTailList(&KiStackInSwapListHead, &Thread->WaitListEntry); 00350 KiSwapEvent.Header.SignalState = 1; 00351 if (IsListEmpty(&KiSwapEvent.Header.WaitListHead) == FALSE) { 00352 KiWaitTest(&KiSwapEvent, BALANCE_INCREMENT); 00353 } 00354 00355 return; 00356 00357 } else { 00358 00359 // 00360 // If there is an idle processor, then schedule the thread on an 00361 // idle processor giving preference to the processor the thread 00362 // last ran on. Otherwise, try to preempt either a thread in the 00363 // standby or running state. 00364 // 00365 00366 #if defined(NT_UP) 00367 00368 Prcb = KiProcessorBlock[0]; 00369 if (KiIdleSummary != 0) { 00370 KiIdleSummary = 0; 00371 KiIncrementSwitchCounter(IdleLast); 00372 Prcb->NextThread = Thread; 00373 Thread->State = Standby; 00374 00375 #else 00376 00377 IdleSet = KiIdleSummary & Thread->Affinity; 00378 if (IdleSet != 0) { 00379 Prcb = KeGetCurrentPrcb(); 00380 Processor = Thread->IdealProcessor; 00381 if ((IdleSet & (1 << Processor)) == 0) { 00382 Processor = Thread->NextProcessor; 00383 if ((IdleSet & (1 << Processor)) == 0) { 00384 if ((IdleSet & Prcb->SetMember) == 0) { 00385 FindFirstSetLeftMember(IdleSet, &Processor); 00386 KiIncrementSwitchCounter(IdleAny); 00387 00388 } else { 00389 Processor = Prcb->Number; 00390 KiIncrementSwitchCounter(IdleCurrent); 00391 } 00392 00393 } else { 00394 KiIncrementSwitchCounter(IdleLast); 00395 } 00396 00397 } else { 00398 KiIncrementSwitchCounter(IdleIdeal); 00399 } 00400 00401 Thread->NextProcessor = (CCHAR)Processor; 00402 ClearMember(Processor, KiIdleSummary); 00403 KiProcessorBlock[Processor]->NextThread = Thread; 00404 Thread->State = Standby; 00405 00406 if ((PoSleepingSummary & (1 << Processor)) && 00407 Processor != (ULONG) Prcb->Number) { 00408 KiIpiSend(1 << Processor, IPI_DPC); 00409 } 00410 #endif 00411 00412 return; 00413 00414 } else { 00415 00416 #if !defined(NT_UP) 00417 00418 Processor = Thread->IdealProcessor; 00419 if ((Thread->Affinity & (1 << Processor)) == 0) { 00420 Processor = Thread->NextProcessor; 00421 if ((Thread->Affinity & (1 << Processor)) == 0) { 00422 FindFirstSetLeftMember(Thread->Affinity, &Processor); 00423 } 00424 } 00425 00426 Thread->NextProcessor = (CCHAR)Processor; 00427 Prcb = KiProcessorBlock[Processor]; 00428 00429 #endif 00430 00431 if (Prcb->NextThread != NULL) { 00432 Thread1 = Prcb->NextThread; 00433 if (ThreadPriority > Thread1->Priority) { 00434 Thread1->Preempted = TRUE; 00435 Prcb->NextThread = Thread; 00436 Thread->State = Standby; 00437 KiReadyThread(Thread1); 00438 KiIncrementSwitchCounter(PreemptLast); 00439 return; 00440 } 00441 00442 } else { 00443 Thread1 = Prcb->CurrentThread; 00444 if (ThreadPriority > Thread1->Priority) { 00445 Thread1->Preempted = TRUE; 00446 Prcb->NextThread = Thread; 00447 Thread->State = Standby; 00448 KiRequestDispatchInterrupt(Thread->NextProcessor); 00449 KiIncrementSwitchCounter(PreemptLast); 00450 return; 00451 } 00452 } 00453 } 00454 } 00455 00456 // 00457 // No thread can be preempted. Insert the thread in the dispatcher 00458 // queue selected by its priority. If the thread was preempted and 00459 // runs at a realtime priority level, then insert the thread at the 00460 // front of the queue. Else insert the thread at the tail of the queue. 00461 // 00462 00463 Thread->State = Ready; 00464 if (Preempted != FALSE) { 00465 InsertHeadList(&KiDispatcherReadyListHead[ThreadPriority], 00466 &Thread->WaitListEntry); 00467 00468 } else { 00469 InsertTailList(&KiDispatcherReadyListHead[ThreadPriority], 00470 &Thread->WaitListEntry); 00471 } 00472 00473 SetMember(ThreadPriority, KiReadySummary); 00474 return; 00475 }

PRKTHREAD FASTCALL KiSelectNextThread IN PRKTHREAD  Thread  ) 
 

Definition at line 479 of file thredsup.c.

References KiFindReadyThread(), KiIdleSummary, KiIncrementSwitchCounter, KiProcessorBlock, _KTHREAD::NextProcessor, NULL, and SetMember.

Referenced by KeRevertToUserAffinityThread(), KeSetAffinityThread(), and KeSetSystemAffinityThread().

00485 : 00486 00487 This function selects the next thread to run on the processor that the 00488 specified thread is running on. If a thread cannot be found, then the 00489 idle thread is selected. 00490 00491 Arguments: 00492 00493 Thread - Supplies a pointer to a dispatcher object of type thread. 00494 00495 Return Value: 00496 00497 The address of the selected thread object. 00498 00499 --*/ 00500 00501 { 00502 00503 PRKPRCB Prcb; 00504 ULONG Processor; 00505 PRKTHREAD Thread1; 00506 00507 // 00508 // Get the processor number and the address of the processor control block. 00509 // 00510 00511 #if !defined(NT_UP) 00512 00513 Processor = Thread->NextProcessor; 00514 Prcb = KiProcessorBlock[Processor]; 00515 00516 #else 00517 00518 Prcb = KiProcessorBlock[0]; 00519 00520 #endif 00521 00522 // 00523 // If a thread has already been selected to run on the specified processor, 00524 // then return that thread as the selected thread. 00525 // 00526 00527 if ((Thread1 = Prcb->NextThread) != NULL) { 00528 Prcb->NextThread = (PKTHREAD)NULL; 00529 00530 } else { 00531 00532 // 00533 // Attempt to find a ready thread to run. 00534 // 00535 00536 #if !defined(NT_UP) 00537 00538 Thread1 = KiFindReadyThread(Processor, 0); 00539 00540 #else 00541 00542 Thread1 = KiFindReadyThread(0, 0); 00543 00544 #endif 00545 00546 // 00547 // If a thread was not found, then select the idle thread and 00548 // set the processor member in the idle summary. 00549 // 00550 00551 if (Thread1 == NULL) { 00552 KiIncrementSwitchCounter(SwitchToIdle); 00553 Thread1 = Prcb->IdleThread; 00554 00555 #if !defined(NT_UP) 00556 00557 SetMember(Processor, KiIdleSummary); 00558 00559 #else 00560 KiIdleSummary = 1; 00561 00562 #endif 00563 00564 } 00565 } 00566 00567 // 00568 // Return address of selected thread object. 00569 // 00570 00571 return Thread1; 00572 }

VOID FASTCALL KiSetPriorityThread IN PRKTHREAD  Thread,
IN KPRIORITY  Priority
 

Definition at line 576 of file thredsup.c.

References ASSERT, ClearMember, FALSE, KiDispatcherReadyListHead, KiFindReadyThread(), KiProcessorBlock, KiReadySummary, KiReadyThread(), KiRequestDispatchInterrupt, NULL, Ready, Running, SetMember, Standby, and _KTHREAD::State.

Referenced by ExpBoostOwnerThread(), KeDelayExecutionThread(), KeSetBasePriorityThread(), KeSetPriorityProcess(), KeSetPriorityThread(), KiAdjustQuantumThread(), and KiQuantumEnd().

00583 : 00584 00585 This function set the priority of the specified thread to the specified 00586 value. If the thread is in the standby or running state, then the processor 00587 may be redispatched. If the thread is in the ready state, then some other 00588 thread may be preempted. 00589 00590 Arguments: 00591 00592 Thread - Supplies a pointer to a dispatcher object of type thread. 00593 00594 Priority - Supplies the new thread priority value. 00595 00596 Return Value: 00597 00598 None. 00599 00600 --*/ 00601 00602 { 00603 00604 PRKPRCB Prcb; 00605 ULONG Processor; 00606 KPRIORITY ThreadPriority; 00607 PRKTHREAD Thread1; 00608 00609 ASSERT(Priority <= HIGH_PRIORITY); 00610 00611 // 00612 // Capture the current priority of the specified thread. 00613 // 00614 00615 ThreadPriority = Thread->Priority; 00616 00617 // 00618 // If the new priority is not equal to the old priority, then set the 00619 // new priority of the thread and redispatch a processor if necessary. 00620 // 00621 00622 if (Priority != ThreadPriority) { 00623 Thread->Priority = (SCHAR)Priority; 00624 00625 // 00626 // Case on the thread state. 00627 // 00628 00629 switch (Thread->State) { 00630 00631 // 00632 // Ready case - If the thread is not in the process ready queue, 00633 // then remove it from its current dispatcher ready queue. If the 00634 // new priority is less than the old priority, then insert the 00635 // thread at the tail of the dispatcher ready queue selected by 00636 // the new priority. Else reready the thread for execution. 00637 // 00638 00639 case Ready: 00640 if (Thread->ProcessReadyQueue == FALSE) { 00641 RemoveEntryList(&Thread->WaitListEntry); 00642 if (IsListEmpty(&KiDispatcherReadyListHead[ThreadPriority])) { 00643 ClearMember(ThreadPriority, KiReadySummary); 00644 } 00645 00646 if (Priority < ThreadPriority) { 00647 InsertTailList(&KiDispatcherReadyListHead[Priority], 00648 &Thread->WaitListEntry); 00649 SetMember(Priority, KiReadySummary); 00650 00651 } else { 00652 KiReadyThread(Thread); 00653 } 00654 } 00655 00656 break; 00657 00658 // 00659 // Standby case - If the thread's priority is being lowered, then 00660 // attempt to find another thread to execute. If a new thread is 00661 // found, then put the new thread in the standby state, and reready 00662 // the old thread. 00663 // 00664 00665 case Standby: 00666 00667 #if !defined(NT_UP) 00668 00669 Processor = Thread->NextProcessor; 00670 00671 #endif 00672 00673 if (Priority < ThreadPriority) { 00674 00675 #if !defined(NT_UP) 00676 00677 Thread1 = KiFindReadyThread(Processor, Priority); 00678 00679 #else 00680 00681 Thread1 = KiFindReadyThread(0, Priority); 00682 00683 #endif 00684 00685 if (Thread1 != NULL) { 00686 00687 #if !defined(NT_UP) 00688 00689 Prcb = KiProcessorBlock[Processor]; 00690 00691 #else 00692 00693 Prcb = KiProcessorBlock[0]; 00694 00695 #endif 00696 00697 Thread1->State = Standby; 00698 Prcb->NextThread = Thread1; 00699 KiReadyThread(Thread); 00700 } 00701 } 00702 00703 break; 00704 00705 // 00706 // Running case - If there is not a thread in the standby state 00707 // on the thread's processor and the thread's priority is being 00708 // lowered, then attempt to find another thread to execute. If 00709 // a new thread is found, then put the new thread in the standby 00710 // state, and request a redispatch on the thread's processor. 00711 // 00712 00713 case Running: 00714 00715 #if !defined(NT_UP) 00716 00717 Processor = Thread->NextProcessor; 00718 Prcb = KiProcessorBlock[Processor]; 00719 00720 #else 00721 00722 Prcb = KiProcessorBlock[0]; 00723 00724 #endif 00725 00726 if (Prcb->NextThread == NULL) { 00727 if (Priority < ThreadPriority) { 00728 00729 #if !defined(NT_UP) 00730 00731 Thread1 = KiFindReadyThread(Processor, Priority); 00732 00733 #else 00734 00735 Thread1 = KiFindReadyThread(0, Priority); 00736 00737 #endif 00738 00739 if (Thread1 != NULL) { 00740 Thread1->State = Standby; 00741 Prcb->NextThread = Thread1; 00742 00743 #if !defined(NT_UP) 00744 00745 KiRequestDispatchInterrupt(Processor); 00746 00747 #endif 00748 00749 } 00750 } 00751 } 00752 00753 break; 00754 00755 // 00756 // Initialized, Terminated, Waiting, Transition case - For 00757 // these states it is sufficient to just set the new thread 00758 // priority. 00759 // 00760 00761 default: 00762 break; 00763 } 00764 } 00765 00766 return; 00767 }

VOID KiSuspendNop IN PKAPC  Apc,
IN OUT PKNORMAL_ROUTINE NormalRoutine,
IN OUT PVOID *  NormalContext,
IN OUT PVOID *  SystemArgument1,
IN OUT PVOID *  SystemArgument2
 

Definition at line 49 of file thredsup.c.

00059 : 00060 00061 This function is the kernel routine for the builtin suspend APC for a 00062 thread. It is executed in kernel mode as the result of queuing the 00063 builtin suspend APC and performs no operation. It is called just prior 00064 to calling the normal routine and simply returns. 00065 00066 Arguments: 00067 00068 Apc - Supplies a pointer to a control object of type APC. 00069 00070 NormalRoutine - not used 00071 00072 NormalContext - not used 00073 00074 SystemArgument1 - not used 00075 00076 SystemArgument2 - not used 00077 00078 Return Value: 00079 00080 None. 00081 00082 --*/ 00083 00084 { 00085 00086 // 00087 // No operation is performed by this routine. 00088 // 00089 00090 return; 00091 }

VOID KiSuspendThread IN PVOID  NormalContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2
 

Definition at line 770 of file thredsup.c.

References _KAPC_STATE::ApcListHead, _KTHREAD::ApcState, FALSE, KeGetCurrentThread, KernelMode, _KAPC::KernelRoutine, KeWaitForSingleObject(), NULL, PsExitSpecialApc(), Suspended, _KTHREAD::SuspendSemaphore, _KAPC_STATE::UserApcPending, and UserMode.

Referenced by KeInitializeThread().

00778 : 00779 00780 This function is the kernel routine for the builtin suspend APC of a 00781 thread. It is executed in kernel mode as the result of queuing the builtin 00782 suspend APC and suspends thread execution by Waiting nonalerable on the 00783 thread's builtin suspend semaphore. When the thread is resumed, execution 00784 of thread is continued by simply returning. 00785 00786 Arguments: 00787 00788 Apc - Supplies a pointer to a control object of type APC. 00789 00790 Return Value: 00791 00792 None. 00793 00794 --*/ 00795 00796 { 00797 00798 PRKTHREAD Thread; 00799 PKAPC Apc; 00800 00801 // 00802 // Get the address of the current thread object and Wait nonalertable on 00803 // the thread's builtin suspend semaphore. 00804 // 00805 00806 Thread = KeGetCurrentThread(); 00807 00808 // 00809 // See if the thread is exiting. If the thread has the user-mode exit 00810 // APC in it's queue, KeForceResumeThread has been called, but it might 00811 // have been called just before KeSuspendThread. Account for the race here 00812 // by testing for the exit APC. During exit, we queue the user-mode exit APC 00813 // and set UserApcPending from the kernel-mode exit APC, then we call 00814 // KeForceResumeThread. 00815 // 00816 00817 if ( Thread->ApcState.UserApcPending ) { 00818 Apc = CONTAINING_RECORD((Thread->ApcState.ApcListHead[UserMode].Flink), KAPC, ApcListEntry); 00819 if ( Apc->KernelRoutine == PsExitSpecialApc ) { 00820 return; 00821 } 00822 } 00823 KeWaitForSingleObject(&Thread->SuspendSemaphore, 00824 Suspended, 00825 KernelMode, 00826 FALSE, 00827 (PLARGE_INTEGER)NULL); 00828 00829 } #if 0


Generated on Sat May 15 19:45:46 2004 for test by doxygen 1.3.7