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

wait.c File Reference

#include "ki.h"

Go to the source code of this file.

Defines

#define TestForAlertPending(Alertable)

Functions

VOID KiAdjustQuantumThread (IN PKTHREAD Thread)
NTSTATUS KeDelayExecutionThread (IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval)
NTSTATUS KeWaitForMultipleObjects (IN ULONG Count, IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL, IN PKWAIT_BLOCK WaitBlockArray OPTIONAL)
NTSTATUS KeWaitForSingleObject (IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
NTSTATUS KiSetServerWaitClientEvent (IN PKEVENT ServerEvent, IN PKEVENT ClientEvent, IN ULONG WaitMode)
PLARGE_INTEGER FASTCALL KiComputeWaitInterval (IN PLARGE_INTEGER OriginalTime, IN PLARGE_INTEGER DueTime, IN OUT PLARGE_INTEGER NewTime)


Define Documentation

#define TestForAlertPending Alertable   ) 
 

Value:

if (Alertable) { \ if (Thread->Alerted[WaitMode] != FALSE) { \ Thread->Alerted[WaitMode] = FALSE; \ WaitStatus = STATUS_ALERTED; \ break; \ } else if ((WaitMode != KernelMode) && \ (IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) == FALSE) { \ Thread->ApcState.UserApcPending = TRUE; \ WaitStatus = STATUS_USER_APC; \ break; \ } else if (Thread->Alerted[KernelMode] != FALSE) { \ Thread->Alerted[KernelMode] = FALSE; \ WaitStatus = STATUS_ALERTED; \ break; \ } \ } else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending)) { \ WaitStatus = STATUS_USER_APC; \ break; \ }

Definition at line 57 of file wait.c.

Referenced by KeDelayExecutionThread(), KeWaitForMultipleObjects(), and KeWaitForSingleObject().


Function Documentation

NTSTATUS KeDelayExecutionThread IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER  Interval
 

Definition at line 140 of file wait.c.

References _KTHREAD::Alertable, APC_LEVEL, _KTHREAD::ApcState, ASSERT, _KTHREAD::BasePriority, DelayExecution, DISPATCH_LEVEL, _KTIMER::DueTime, FALSE, _KTIMER::Header, KeGetCurrentPrcb, KeGetCurrentThread, _KAPC_STATE::KernelApcPending, KiActivateWaiterQueue(), KiComputeWaitInterval(), KiFindReadyThread(), KiInsertTreeTimer(), KiInsertWaitList, KiLockDispatcherDatabase, KiReadyThread(), KiSetPriorityThread(), KiSwapThread(), KiUnlockDispatcherDatabase(), _KTHREAD::NextProcessor, _KWAIT_BLOCK::NextWaitBlock, NTSTATUS(), NULL, _KTHREAD::Preempted, _KTHREAD::Priority, _KTHREAD::PriorityDecrement, _KAPC_STATE::Process, _KTHREAD::Quantum, _KTHREAD::Queue, _KTHREAD::State, TestForAlertPending, _KPROCESS::ThreadQuantum, _KTHREAD::Timer, TIMER_WAIT_BLOCK, TRUE, _KTHREAD::WaitBlock, _KTHREAD::WaitBlockList, Waiting, _KTHREAD::WaitIrql, _KWAIT_BLOCK::WaitListEntry, _DISPATCHER_HEADER::WaitListHead, _KTHREAD::WaitMode, _KTHREAD::WaitNext, _KTHREAD::WaitReason, _KTHREAD::WaitStatus, and _KTHREAD::WaitTime.

Referenced by CcPurgeCacheSection(), IoCancelThreadIo(), IopCancelAlertedRequest(), IopStartNetworkForRemoteBoot(), KiInitMachineDependent(), MemPrintFlush(), MemPrintWriteThread(), MiAllocateContiguousMemory(), MiCheckControlAreaStatus(), MiCheckSystemTrimEndCriteria(), MiCleanSection(), MiCloneProcessAddressSpace(), MiDispatchFault(), MiEmptyWorkingSet(), MiFlushAllPages(), MiFlushSectionInternal(), MiMakeOutswappedPageResident(), MiModifiedPageWriter(), MiModifiedPageWriterWorker(), MiPurgeImageSection(), MiRemoveUnusedSegments(), MiResolveProtoPteFault(), MiWriteComplete(), MmAccessFault(), MmCopyToCachedPage(), MmFlushSection(), MmFlushVirtualMemory(), MmGatherMemoryForHibernate(), MmGetSystemRoutineAddress(), MmRemovePhysicalMemory(), MmShutdownSystem(), MmWorkingSetManager(), NtCancelIoFile(), NtCreateSection(), NtDelayExecution(), Reader(), ReaderTurnedWriter(), UserBeep(), UserSleep(), Writer(), and xxxLW_LoadFonts().

00148 : 00149 00150 This function delays the execution of the current thread for the specified 00151 interval of time. 00152 00153 Arguments: 00154 00155 WaitMode - Supplies the processor mode in which the delay is to occur. 00156 00157 Alertable - Supplies a boolean value that specifies whether the delay 00158 is alertable. 00159 00160 Interval - Supplies a pointer to the absolute or relative time over which 00161 the delay is to occur. 00162 00163 Return Value: 00164 00165 The wait completion status. A value of STATUS_SUCCESS is returned if 00166 the delay occurred. A value of STATUS_ALERTED is returned if the wait 00167 was aborted to deliver an alert to the current thread. A value of 00168 STATUS_USER_APC is returned if the wait was aborted to deliver a user 00169 APC to the current thread. 00170 00171 --*/ 00172 00173 { 00174 00175 LARGE_INTEGER DueTime; 00176 LARGE_INTEGER NewTime; 00177 PLARGE_INTEGER OriginalTime; 00178 PKPRCB Prcb; 00179 KPRIORITY Priority; 00180 PRKQUEUE Queue; 00181 PRKTHREAD Thread; 00182 PRKTIMER Timer; 00183 PKWAIT_BLOCK WaitBlock; 00184 NTSTATUS WaitStatus; 00185 00186 // 00187 // If the dispatcher database lock is not already held, then set the wait 00188 // IRQL and lock the dispatcher database. Else set boolean wait variable 00189 // to FALSE. 00190 // 00191 00192 Thread = KeGetCurrentThread(); 00193 if (Thread->WaitNext) { 00194 Thread->WaitNext = FALSE; 00195 00196 } else { 00197 KiLockDispatcherDatabase(&Thread->WaitIrql); 00198 } 00199 00200 // 00201 // Start of delay loop. 00202 // 00203 // Note this loop is repeated if a kernel APC is delivered in the middle 00204 // of the delay or a kernel APC is pending on the first attempt through 00205 // the loop. 00206 // 00207 00208 OriginalTime = Interval; 00209 WaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK]; 00210 do { 00211 00212 // 00213 // Test to determine if a kernel APC is pending. 00214 // 00215 // If a kernel APC is pending and the previous IRQL was less than 00216 // APC_LEVEL, then a kernel APC was queued by another processor just 00217 // after IRQL was raised to DISPATCH_LEVEL, but before the dispatcher 00218 // database was locked. 00219 // 00220 // N.B. that this can only happen in a multiprocessor system. 00221 // 00222 00223 if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { 00224 00225 // 00226 // Unlock the dispatcher database and lower IRQL to its previous 00227 // value. An APC interrupt will immediately occur which will result 00228 // in the delivery of the kernel APC if possible. 00229 // 00230 00231 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00232 00233 } else { 00234 00235 // 00236 // Test for alert pending. 00237 // 00238 00239 TestForAlertPending(Alertable); 00240 00241 // 00242 // Initialize wait block, insert wait block in timer wait list, 00243 // insert timer in timer queue, put thread in wait state, select 00244 // next thread to execute, and context switch to next thread. 00245 // 00246 // N.B. The timer wait block is initialized when the respective 00247 // thread is initialized. Thus the constant fields are not 00248 // reinitialized. These include the wait object, wait key, 00249 // wait type, and the wait list entry link pointers. 00250 // 00251 00252 Thread->WaitBlockList = WaitBlock; 00253 Thread->WaitStatus = (NTSTATUS)0; 00254 Timer = &Thread->Timer; 00255 WaitBlock->NextWaitBlock = WaitBlock; 00256 Timer->Header.WaitListHead.Flink = &WaitBlock->WaitListEntry; 00257 Timer->Header.WaitListHead.Blink = &WaitBlock->WaitListEntry; 00258 00259 // 00260 // If the timer is inserted in the timer tree, then place the 00261 // current thread in a wait state. Otherwise, attempt to force 00262 // the current thread to yield the processor to another thread. 00263 // 00264 00265 if (KiInsertTreeTimer(Timer, *Interval) == FALSE) { 00266 00267 // 00268 // If the thread is not a realtime thread, then drop the 00269 // thread priority to the base priority. 00270 // 00271 00272 Prcb = KeGetCurrentPrcb(); 00273 Priority = Thread->Priority; 00274 if (Priority < LOW_REALTIME_PRIORITY) { 00275 if (Priority != Thread->BasePriority) { 00276 Thread->PriorityDecrement = 0; 00277 KiSetPriorityThread(Thread, Thread->BasePriority); 00278 } 00279 } 00280 00281 // 00282 // If a new thread has not been selected, the attempt to round 00283 // robin the thread with other threads at the same priority. 00284 // 00285 00286 if (Prcb->NextThread == NULL) { 00287 Prcb->NextThread = KiFindReadyThread(Thread->NextProcessor, 00288 Thread->Priority); 00289 } 00290 00291 // 00292 // If a new thread has been selected for execution, then 00293 // switch immediately to the selected thread. 00294 // 00295 00296 if (Prcb->NextThread != NULL) { 00297 00298 // 00299 // Give the current thread a new qunatum and switch 00300 // context to selected thread. 00301 // 00302 // N.B. Control is returned at the original IRQL. 00303 // 00304 00305 Thread->Preempted = FALSE; 00306 Thread->Quantum = Thread->ApcState.Process->ThreadQuantum; 00307 00308 ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL); 00309 00310 KiReadyThread(Thread); 00311 WaitStatus = (NTSTATUS)KiSwapThread(); 00312 goto WaitComplete; 00313 00314 } else { 00315 WaitStatus = (NTSTATUS)STATUS_SUCCESS; 00316 break; 00317 } 00318 } 00319 00320 DueTime.QuadPart = Timer->DueTime.QuadPart; 00321 00322 // 00323 // If the current thread is processing a queue entry, then attempt 00324 // to activate another thread that is blocked on the queue object. 00325 // 00326 00327 Queue = Thread->Queue; 00328 if (Queue != NULL) { 00329 KiActivateWaiterQueue(Queue); 00330 } 00331 00332 // 00333 // Set the thread wait parameters, set the thread dispatcher state 00334 // to Waiting, and insert the thread in the wait list. 00335 // 00336 00337 Thread->Alertable = Alertable; 00338 Thread->WaitMode = WaitMode; 00339 Thread->WaitReason = DelayExecution; 00340 Thread->WaitTime= KiQueryLowTickCount(); 00341 Thread->State = Waiting; 00342 KiInsertWaitList(WaitMode, Thread); 00343 00344 // 00345 // Switch context to selected thread. 00346 // 00347 // N.B. Control is returned at the original IRQL. 00348 // 00349 00350 ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL); 00351 00352 WaitStatus = (NTSTATUS)KiSwapThread(); 00353 00354 // 00355 // If the thread was not awakened to deliver a kernel mode APC, 00356 // then return the wait status. 00357 // 00358 00359 WaitComplete: 00360 if (WaitStatus != STATUS_KERNEL_APC) { 00361 if (WaitStatus == STATUS_TIMEOUT) { 00362 WaitStatus = STATUS_SUCCESS; 00363 } 00364 00365 return WaitStatus; 00366 } 00367 00368 // 00369 // Reduce the time remaining before the time delay expires. 00370 // 00371 00372 Interval = KiComputeWaitInterval(OriginalTime, 00373 &DueTime, 00374 &NewTime); 00375 } 00376 00377 // 00378 // Raise IRQL to DISPATCH_LEVEL and lock the dispatcher database. 00379 // 00380 00381 KiLockDispatcherDatabase(&Thread->WaitIrql); 00382 } while (TRUE); 00383 00384 // 00385 // The thread is alerted or a user APC should be delivered. Unlock the 00386 // dispatcher database, lower IRQL to its previous value, and return the 00387 // wait status. 00388 // 00389 00390 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00391 return WaitStatus; 00392 }

NTSTATUS KeWaitForMultipleObjects IN ULONG  Count,
IN PVOID  Object[],
IN WAIT_TYPE  WaitType,
IN KWAIT_REASON  WaitReason,
IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER Timeout  OPTIONAL,
IN PKWAIT_BLOCK WaitBlockArray  OPTIONAL
 

Definition at line 395 of file wait.c.

References _KTHREAD::Alertable, APC_LEVEL, _KTHREAD::ApcState, ASSERT, Count, DISPATCH_LEVEL, _KTIMER::DueTime, ExRaiseStatus(), FALSE, _KTIMER::Header, _KMUTANT::Header, Index, KeBugCheck(), KeGetCurrentThread, _KAPC_STATE::KernelApcPending, KiActivateWaiterQueue(), KiAdjustQuantumThread(), KiComputeWaitInterval(), KiInsertTreeTimer(), KiInsertWaitList, KiLockDispatcherDatabase, KiSwapThread(), KiUnlockDispatcherDatabase(), KiWaitSatisfyAll(), KiWaitSatisfyMutant, KiWaitSatisfyOther, KWAIT_REASON, MutantObject, _KWAIT_BLOCK::NextWaitBlock, NTSTATUS(), NULL, _KWAIT_BLOCK::Object, _KMUTANT::OwnerThread, _KTHREAD::Queue, QueueObject, _DISPATCHER_HEADER::SignalState, _KTHREAD::State, TestForAlertPending, _KWAIT_BLOCK::Thread, THREAD_WAIT_OBJECTS, _KTHREAD::Timer, TIMER_WAIT_BLOCK, TRUE, _DISPATCHER_HEADER::Type, USHORT, _KTHREAD::WaitBlock, _KTHREAD::WaitBlockList, Waiting, _KTHREAD::WaitIrql, _KWAIT_BLOCK::WaitKey, _KWAIT_BLOCK::WaitListEntry, _DISPATCHER_HEADER::WaitListHead, _KTHREAD::WaitMode, _KTHREAD::WaitNext, _KTHREAD::WaitReason, _KTHREAD::WaitStatus, _KTHREAD::WaitTime, and _KWAIT_BLOCK::WaitType.

Referenced by CmpFileWrite(), ExpWorkerThreadBalanceManager(), InitiateWin32kCleanup(), KeBalanceSetManager(), MemPrintWriteThread(), MiDereferenceSegmentThread(), MiModifiedPageWriterWorker(), MmZeroPageThread(), NtWaitForMultipleObjects(), RawInputThread(), SmbTraceThreadEntry(), xxxMsgWaitForMultipleObjects(), xxxPollAndWaitForSingleObject(), and xxxSleepTask().

00408 : 00409 00410 This function waits until the specified objects attain a state of 00411 Signaled. The wait can be specified to wait until all of the objects 00412 attain a state of Signaled or until one of the objects attains a state 00413 of Signaled. An optional timeout can also be specified. If a timeout 00414 is not specified, then the wait will not be satisfied until the objects 00415 attain a state of Signaled. If a timeout is specified, and the objects 00416 have not attained a state of Signaled when the timeout expires, then 00417 the wait is automatically satisfied. If an explicit timeout value of 00418 zero is specified, then no wait will occur if the wait cannot be satisfied 00419 immediately. The wait can also be specified as alertable. 00420 00421 Arguments: 00422 00423 Count - Supplies a count of the number of objects that are to be waited 00424 on. 00425 00426 Object[] - Supplies an array of pointers to dispatcher objects. 00427 00428 WaitType - Supplies the type of wait to perform (WaitAll, WaitAny). 00429 00430 WaitReason - Supplies the reason for the wait. 00431 00432 WaitMode - Supplies the processor mode in which the wait is to occur. 00433 00434 Alertable - Supplies a boolean value that specifies whether the wait is 00435 alertable. 00436 00437 Timeout - Supplies a pointer to an optional absolute of relative time over 00438 which the wait is to occur. 00439 00440 WaitBlockArray - Supplies an optional pointer to an array of wait blocks 00441 that are to used to describe the wait operation. 00442 00443 Return Value: 00444 00445 The wait completion status. A value of STATUS_TIMEOUT is returned if a 00446 timeout occurred. The index of the object (zero based) in the object 00447 pointer array is returned if an object satisfied the wait. A value of 00448 STATUS_ALERTED is returned if the wait was aborted to deliver an alert 00449 to the current thread. A value of STATUS_USER_APC is returned if the 00450 wait was aborted to deliver a user APC to the current thread. 00451 00452 --*/ 00453 00454 { 00455 00456 LARGE_INTEGER DueTime; 00457 ULONG Index; 00458 LARGE_INTEGER NewTime; 00459 PRKTHREAD NextThread; 00460 PKMUTANT Objectx; 00461 PLARGE_INTEGER OriginalTime; 00462 PRKQUEUE Queue; 00463 PRKTHREAD Thread; 00464 PRKTIMER Timer; 00465 PRKWAIT_BLOCK WaitBlock; 00466 BOOLEAN WaitSatisfied; 00467 NTSTATUS WaitStatus; 00468 PKWAIT_BLOCK WaitTimer; 00469 00470 // 00471 // If the dispatcher database lock is not already held, then set the wait 00472 // IRQL and lock the dispatcher database. Else set boolean wait variable 00473 // to FALSE. 00474 // 00475 00476 Thread = KeGetCurrentThread(); 00477 if (Thread->WaitNext) { 00478 Thread->WaitNext = FALSE; 00479 00480 } else { 00481 KiLockDispatcherDatabase(&Thread->WaitIrql); 00482 } 00483 00484 // 00485 // If a wait block array has been specified, then the maximum number of 00486 // objects that can be waited on is specified by MAXIMUM_WAIT_OBJECTS. 00487 // Otherwise the builtin wait blocks in the thread object are used and 00488 // the maximum number of objects that can be waited on is specified by 00489 // THREAD_WAIT_OBJECTS. If the specified number of objects is not within 00490 // limits, then bug check. 00491 // 00492 00493 if (ARGUMENT_PRESENT(WaitBlockArray)) { 00494 if (Count > MAXIMUM_WAIT_OBJECTS) { 00495 KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED); 00496 } 00497 00498 } else { 00499 if (Count > THREAD_WAIT_OBJECTS) { 00500 KeBugCheck(MAXIMUM_WAIT_OBJECTS_EXCEEDED); 00501 } 00502 00503 WaitBlockArray = &Thread->WaitBlock[0]; 00504 } 00505 00506 // 00507 // Start of wait loop. 00508 // 00509 // Note this loop is repeated if a kernel APC is delivered in the middle 00510 // of the wait or a kernel APC is pending on the first attempt through 00511 // the loop. 00512 // 00513 00514 OriginalTime = Timeout; 00515 do { 00516 00517 // 00518 // Set address of wait block list in thread object. 00519 // 00520 00521 Thread->WaitBlockList = WaitBlockArray; 00522 00523 // 00524 // Test to determine if a kernel APC is pending. 00525 // 00526 // If a kernel APC is pending and the previous IRQL was less than 00527 // APC_LEVEL, then a kernel APC was queued by another processor just 00528 // after IRQL was raised to DISPATCH_LEVEL, but before the dispatcher 00529 // database was locked. 00530 // 00531 // N.B. that this can only happen in a multiprocessor system. 00532 // 00533 00534 if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { 00535 00536 // 00537 // Unlock the dispatcher database and lower IRQL to its previous 00538 // value. An APC interrupt will immediately occur which will result 00539 // in the delivery of the kernel APC if possible. 00540 // 00541 00542 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00543 00544 } else { 00545 00546 // 00547 // Construct wait blocks and check to determine if the wait is 00548 // already satisfied. If the wait is satisfied, then perform 00549 // wait completion and return. Else put current thread in a wait 00550 // state if an explicit timeout value of zero is not specified. 00551 // 00552 00553 Thread->WaitStatus = (NTSTATUS)0; 00554 WaitSatisfied = TRUE; 00555 for (Index = 0; Index < Count; Index += 1) { 00556 00557 // 00558 // Test if wait can be satisfied immediately. 00559 // 00560 00561 Objectx = (PKMUTANT)Object[Index]; 00562 00563 ASSERT(Objectx->Header.Type != QueueObject); 00564 00565 if (WaitType == WaitAny) { 00566 00567 // 00568 // If the object is a mutant object and the mutant object 00569 // has been recursively acquired MINLONG times, then raise 00570 // an exception. Otherwise if the signal state of the mutant 00571 // object is greater than zero, or the current thread is 00572 // the owner of the mutant object, then satisfy the wait. 00573 // 00574 00575 if (Objectx->Header.Type == MutantObject) { 00576 if ((Objectx->Header.SignalState > 0) || 00577 (Thread == Objectx->OwnerThread)) { 00578 if (Objectx->Header.SignalState != MINLONG) { 00579 KiWaitSatisfyMutant(Objectx, Thread); 00580 WaitStatus = (NTSTATUS)(Index | Thread->WaitStatus); 00581 goto NoWait; 00582 00583 } else { 00584 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00585 ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED); 00586 } 00587 } 00588 00589 // 00590 // If the signal state is greater than zero, then satisfy 00591 // the wait. 00592 // 00593 00594 } else if (Objectx->Header.SignalState > 0) { 00595 KiWaitSatisfyOther(Objectx); 00596 WaitStatus = (NTSTATUS)(Index); 00597 goto NoWait; 00598 } 00599 00600 } else { 00601 00602 // 00603 // If the object is a mutant object and the mutant object 00604 // has been recursively acquired MAXLONG times, then raise 00605 // an exception. Otherwise if the signal state of the mutant 00606 // object is less than or equal to zero and the current 00607 // thread is not the owner of the mutant object, then the 00608 // wait cannot be satisfied. 00609 // 00610 00611 if (Objectx->Header.Type == MutantObject) { 00612 if ((Thread == Objectx->OwnerThread) && 00613 (Objectx->Header.SignalState == MINLONG)) { 00614 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00615 ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED); 00616 00617 } else if ((Objectx->Header.SignalState <= 0) && 00618 (Thread != Objectx->OwnerThread)) { 00619 WaitSatisfied = FALSE; 00620 } 00621 00622 // 00623 // If the signal state is less than or equal to zero, then 00624 // the wait cannot be satisfied. 00625 // 00626 00627 } else if (Objectx->Header.SignalState <= 0) { 00628 WaitSatisfied = FALSE; 00629 } 00630 } 00631 00632 // 00633 // Construct wait block for the current object. 00634 // 00635 00636 WaitBlock = &WaitBlockArray[Index]; 00637 WaitBlock->Object = (PVOID)Objectx; 00638 WaitBlock->WaitKey = (CSHORT)(Index); 00639 WaitBlock->WaitType = (USHORT)WaitType; 00640 WaitBlock->Thread = Thread; 00641 WaitBlock->NextWaitBlock = &WaitBlockArray[Index + 1]; 00642 } 00643 00644 // 00645 // If the wait type is wait all, then check to determine if the 00646 // wait can be satisfied immediately. 00647 // 00648 00649 if ((WaitType == WaitAll) && (WaitSatisfied)) { 00650 WaitBlock->NextWaitBlock = &WaitBlockArray[0]; 00651 KiWaitSatisfyAll(WaitBlock); 00652 WaitStatus = (NTSTATUS)Thread->WaitStatus; 00653 goto NoWait; 00654 } 00655 00656 // 00657 // Test for alert pending. 00658 // 00659 00660 TestForAlertPending(Alertable); 00661 00662 // 00663 // The wait cannot be satisifed immediately. Check to determine if 00664 // a timeout value is specified. 00665 // 00666 00667 if (ARGUMENT_PRESENT(Timeout)) { 00668 00669 // 00670 // If the timeout value is zero, then return immediately without 00671 // waiting. 00672 // 00673 00674 if (!(Timeout->LowPart | Timeout->HighPart)) { 00675 WaitStatus = (NTSTATUS)(STATUS_TIMEOUT); 00676 goto NoWait; 00677 } 00678 00679 // 00680 // Initialize a wait block for the thread specific timer, 00681 // initialize timer wait list head, insert the timer in the 00682 // timer tree, and increment the number of wait objects. 00683 // 00684 // N.B. The timer wait block is initialized when the respective 00685 // thread is initialized. Thus the constant fields are not 00686 // reinitialized. These include the wait object, wait key, 00687 // wait type, and the wait list entry link pointers. 00688 // 00689 00690 WaitTimer = &Thread->WaitBlock[TIMER_WAIT_BLOCK]; 00691 WaitBlock->NextWaitBlock = WaitTimer; 00692 WaitBlock = WaitTimer; 00693 Timer = &Thread->Timer; 00694 InitializeListHead(&Timer->Header.WaitListHead); 00695 if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { 00696 WaitStatus = (NTSTATUS)STATUS_TIMEOUT; 00697 goto NoWait; 00698 } 00699 00700 DueTime.QuadPart = Timer->DueTime.QuadPart; 00701 } 00702 00703 // 00704 // Close up the circular list of wait control blocks. 00705 // 00706 00707 WaitBlock->NextWaitBlock = &WaitBlockArray[0]; 00708 00709 // 00710 // Insert wait blocks in object wait lists. 00711 // 00712 00713 WaitBlock = &WaitBlockArray[0]; 00714 do { 00715 Objectx = (PKMUTANT)WaitBlock->Object; 00716 InsertTailList(&Objectx->Header.WaitListHead, &WaitBlock->WaitListEntry); 00717 WaitBlock = WaitBlock->NextWaitBlock; 00718 } while (WaitBlock != &WaitBlockArray[0]); 00719 00720 // 00721 // If the current thread is processing a queue entry, then attempt 00722 // to activate another thread that is blocked on the queue object. 00723 // 00724 00725 Queue = Thread->Queue; 00726 if (Queue != NULL) { 00727 KiActivateWaiterQueue(Queue); 00728 } 00729 00730 // 00731 // Set the thread wait parameters, set the thread dispatcher state 00732 // to Waiting, and insert the thread in the wait list. 00733 // 00734 00735 Thread->Alertable = Alertable; 00736 Thread->WaitMode = WaitMode; 00737 Thread->WaitReason = (UCHAR)WaitReason; 00738 Thread->WaitTime= KiQueryLowTickCount(); 00739 Thread->State = Waiting; 00740 KiInsertWaitList(WaitMode, Thread); 00741 00742 // 00743 // Switch context to selected thread. 00744 // 00745 // Control is returned at the original IRQL. 00746 // 00747 00748 ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL); 00749 00750 WaitStatus = (NTSTATUS)KiSwapThread(); 00751 00752 // 00753 // If the thread was not awakened to deliver a kernel mode APC, 00754 // then the wait status. 00755 // 00756 00757 if (WaitStatus != STATUS_KERNEL_APC) { 00758 return WaitStatus; 00759 } 00760 00761 if (ARGUMENT_PRESENT(Timeout)) { 00762 00763 // 00764 // Reduce the amount of time remaining before timeout occurs. 00765 // 00766 00767 Timeout = KiComputeWaitInterval(OriginalTime, 00768 &DueTime, 00769 &NewTime); 00770 } 00771 } 00772 00773 // 00774 // Raise IRQL to DISPATCH_LEVEL and lock the dispatcher database. 00775 // 00776 00777 KiLockDispatcherDatabase(&Thread->WaitIrql); 00778 } while (TRUE); 00779 00780 // 00781 // The thread is alerted or a user APC should be delivered. Unlock the 00782 // dispatcher database, lower IRQL to its previous value, and return 00783 // the wait status. 00784 // 00785 00786 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00787 return WaitStatus; 00788 00789 // 00790 // The wait has been satisfied without actually waiting. 00791 // 00792 // If the thread priority that is less than time critical, then reduce 00793 // the thread quantum. If a quantum end occurs, then reduce the thread 00794 // priority. 00795 // 00796 00797 NoWait: 00798 KiAdjustQuantumThread(Thread); 00799 00800 // 00801 // Unlock the dispatcher database, lower IRQL to its previous value, and 00802 // return the wait status. 00803 // 00804 00805 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00806 return WaitStatus; 00807 }

NTSTATUS KeWaitForSingleObject IN PVOID  Object,
IN KWAIT_REASON  WaitReason,
IN KPROCESSOR_MODE  WaitMode,
IN BOOLEAN  Alertable,
IN PLARGE_INTEGER Timeout  OPTIONAL
 

Definition at line 810 of file wait.c.

References _KTHREAD::Alertable, APC_LEVEL, _KTHREAD::ApcState, ASSERT, DISPATCH_LEVEL, _KTIMER::DueTime, ExRaiseStatus(), FALSE, _KTIMER::Header, _KMUTANT::Header, KeGetCurrentThread, _KAPC_STATE::KernelApcPending, KiActivateWaiterQueue(), KiAdjustQuantumThread(), KiComputeWaitInterval(), KiInsertTreeTimer(), KiInsertWaitList, KiLockDispatcherDatabase, KiSwapThread(), KiUnlockDispatcherDatabase(), KiWaitSatisfyMutant, KiWaitSatisfyOther, KiWaitSingleCallData, KWAIT_REASON, MutantObject, _KWAIT_BLOCK::NextWaitBlock, NTSTATUS(), NULL, _KWAIT_BLOCK::Object, _KMUTANT::OwnerThread, _KTHREAD::Queue, QueueObject, RECORD_CALL_DATA, _DISPATCHER_HEADER::SignalState, _KTHREAD::State, TestForAlertPending, _KTHREAD::Timer, TIMER_WAIT_BLOCK, TRUE, _DISPATCHER_HEADER::Type, _KTHREAD::WaitBlock, _KTHREAD::WaitBlockList, Waiting, _KTHREAD::WaitIrql, _KWAIT_BLOCK::WaitKey, _KWAIT_BLOCK::WaitListEntry, _DISPATCHER_HEADER::WaitListHead, _KTHREAD::WaitMode, _KTHREAD::WaitNext, _KTHREAD::WaitReason, _KTHREAD::WaitStatus, _KTHREAD::WaitTime, and _KWAIT_BLOCK::WaitType.

Referenced by CcCanIWrite(), CcInitializeCacheMap(), CcSetValidData(), CcWaitForCurrentLazyWriterActivity(), CcWaitOnActiveCount(), CcZeroData(), CmpFileRead(), CmpOpenHiveFiles(), DoResourceTest(), ExAllocatePool(), ExFreePool(), ExLockHandleTableEntry(), ExLockPool(), ExpGetProcessInformation(), ExpWaitForResource(), ExpWaitForResourceDdk(), ExUnregisterCallback(), FsRecGetDeviceSectors(), FsRecGetDeviceSectorSize(), FsRecLoadFileSystem(), FsRecReadBlock(), FsRtlBalanceReads(), FsRtlDeregisterUncProvider(), FsRtlGetFileSize(), FsRtlRegisterUncProvider(), FsRtlSetFileSize(), FsRtlSyncVolumes(), FsRtlWaitOnIrp(), GetDeviceChangeInfo(), HalpEnableAutomaticDriveLetterAssignment(), HalpGetFullGeometry(), HalpIsOldStyleFloppy(), HalpNextMountLetter(), HalpQueryDriveLayout(), HalpQueryPartitionType(), HalpSetMountLetter(), InitiateWin32kCleanup(), IoCancelFileOpen(), IoFreeDumpStack(), IoGetBootDiskInformation(), IoGetDmaAdapter(), IopAcquireFileObjectLock(), IopAllocateBootResources(), IopAllocateResources(), IopCancelAlertedRequest(), IopCloseFile(), IopCompleteDumpInitialization(), IopCompleteUnloadOrDelete(), IopCreateArcNames(), IopDeleteFile(), IopFilterResourceRequirementsCall(), IopGetDumpStack(), IopGetFileName(), IopGetSetObjectId(), IopGetSetSecurityObject(), IopGetVolumeId(), IopHardErrorThread(), IopHardwareProfileBeginTransition(), IopInvalidateVolumesForDevice(), IopLegacyResourceAllocation(), IopLoadFileSystemDriver(), IopLockMountedDeviceForRemove(), IopMountVolume(), IoPnPDeliverServicePowerNotification(), IopParseDevice(), IopProcessStartDevices(), IopProcessStartDevicesWorker(), IopQueryConflictList(), IopQueryRebalanceWorker(), IopQueryXxxInformation(), IopReallocateResources(), IopRebalance(), IopRequestHwProfileChangeNotification(), IopSendMessageToTrackService(), IopSetRemoteLink(), IopSynchronousApiServiceTail(), IopSynchronousCall(), IopSynchronousServiceTail(), IopUnlockMountedDeviceForRemove(), IopWaitForBootDevicesDeleted(), IopWaitForBootDevicesStarted(), IopWarmEjectDevice(), IoReleaseRemoveLockAndWaitEx(), IoReportTargetDeviceChange(), IoSetInformation(), IoShutdownSystem(), IoSynchronousInvalidateDeviceRelations(), IoVerifyVolume(), IovpInternalCompleteAfterWait(), IovpThrowBogusSynchronousIrp(), KeSetAutoAlignmentThread(), KeSwapProcessOrStack(), KiSetServerWaitClientEvent(), KiSuspendThread(), LfsCloseLogFile(), LfsFlushLbcb(), LfsWriteLogRecordIntoLogPage(), LpcpExtendPortZone(), LpcRequestWaitReplyPort(), MiCheckControlAreaStatus(), MiCheckForCrashDump(), MiCheckPageFilePath(), MiCheckPurgeAndUpMapCount(), MiCleanSection(), MiCreateImageFileMap(), MiDereferenceSession(), MiEmptyAllWorkingSets(), MiEnsureAvailablePageOrWait(), MiFlushSectionInternal(), MiGatherPagefilePages(), MiIssuePageExtendRequest(), MiLoadSystemImage(), MiLookupPsLoadedModule(), MiMakeOutswappedPageResident(), MiMapImageHeaderInHyperSpace(), MiMappedPageWriter(), MiModifiedPageWriterWorker(), MiWaitForInPageComplete(), MmAddVerifierThunks(), MmCleanProcessAddressSpace(), MmCreateSection(), MmGetVerifierInformation(), MmLockPagableSectionByHandle(), MmPurgeSection(), MmSetVerifierInformation(), MmShutdownSystem(), MmUnloadSystemImage(), NtDuplicateObject(), NtGetContextThread(), NtLoadDriver(), NtNotifyChangeMultipleKeys(), NtQueryInformationFile(), NtQueryInformationProcess(), NtReplyWaitReceivePort(), NtReplyWaitReceivePortEx(), NtReplyWaitReplyPort(), NtRequestWaitReplyPort(), NtSecureConnectPort(), NtSetContextThread(), NtSetInformationFile(), NtSetLdtEntries(), NtSignalAndWaitForSingleObject(), NtStartProfile(), NtStopProfile(), NtUnloadDriver(), NtWaitForSingleObject(), ObFindHandleForObject(), ObInitProcess(), ObKillProcess(), ObWaitForSingleObject(), PsLockProcess(), PspQueryDescriptorThread(), PspQueryLdtInformation(), PspSetLdtInformation(), PspSetLdtSize(), QueuePowerRequest(), RawInputThread(), RequestDeviceChange(), RtlReleaseRemoveLockAndWait(), RtlVolumeDeviceToDosName(), SmbTraceCompleteRdr(), SmbTraceCompleteSrv(), SmbTraceStart(), SmbTraceStop(), UdfAddVmcbMapping(), UdfPerformDevIoCtrl(), UdfPnpQueryRemove(), UdfPnpRemove(), UdfPnpSurpriseRemove(), UdfReadSectors(), UdfRemoveVmcbMapping(), UdfVmcbLbnToVbn(), UdfVmcbVbnToLbn(), UdfWaitSync(), VdmDispatchStringIoToHandler(), VdmQueryDirectoryFile(), xHalExamineMBR(), xHalGetPartialGeometry(), xHalIoClearPartitionTable(), xHalIoReadPartitionTable(), xHalIoSetPartitionInformation(), xHalIoWritePartitionTable(), xxxDesktopThread(), xxxInitInput(), xxxInitTerminal(), xxxRemoteDisconnect(), and xxxSleepThread().

00820 : 00821 00822 This function waits until the specified object attains a state of 00823 Signaled. An optional timeout can also be specified. If a timeout 00824 is not specified, then the wait will not be satisfied until the object 00825 attains a state of Signaled. If a timeout is specified, and the object 00826 has not attained a state of Signaled when the timeout expires, then 00827 the wait is automatically satisfied. If an explicit timeout value of 00828 zero is specified, then no wait will occur if the wait cannot be satisfied 00829 immediately. The wait can also be specified as alertable. 00830 00831 Arguments: 00832 00833 Object - Supplies a pointer to a dispatcher object. 00834 00835 WaitReason - Supplies the reason for the wait. 00836 00837 WaitMode - Supplies the processor mode in which the wait is to occur. 00838 00839 Alertable - Supplies a boolean value that specifies whether the wait is 00840 alertable. 00841 00842 Timeout - Supplies a pointer to an optional absolute of relative time over 00843 which the wait is to occur. 00844 00845 Return Value: 00846 00847 The wait completion status. A value of STATUS_TIMEOUT is returned if a 00848 timeout occurred. A value of STATUS_SUCCESS is returned if the specified 00849 object satisfied the wait. A value of STATUS_ALERTED is returned if the 00850 wait was aborted to deliver an alert to the current thread. A value of 00851 STATUS_USER_APC is returned if the wait was aborted to deliver a user 00852 APC to the current thread. 00853 00854 --*/ 00855 00856 { 00857 00858 LARGE_INTEGER DueTime; 00859 LARGE_INTEGER NewTime; 00860 PRKTHREAD NextThread; 00861 PKMUTANT Objectx; 00862 PLARGE_INTEGER OriginalTime; 00863 PRKQUEUE Queue; 00864 PRKTHREAD Thread; 00865 PRKTIMER Timer; 00866 PKWAIT_BLOCK WaitBlock; 00867 NTSTATUS WaitStatus; 00868 PKWAIT_BLOCK WaitTimer; 00869 00870 // 00871 // Collect call data. 00872 // 00873 00874 #if defined(_COLLECT_WAIT_SINGLE_CALLDATA_) 00875 00876 RECORD_CALL_DATA(&KiWaitSingleCallData); 00877 00878 #endif 00879 00880 // 00881 // If the dispatcher database lock is not already held, then set the wait 00882 // IRQL and lock the dispatcher database. Else set boolean wait variable 00883 // to FALSE. 00884 // 00885 00886 Thread = KeGetCurrentThread(); 00887 if (Thread->WaitNext) { 00888 Thread->WaitNext = FALSE; 00889 00890 } else { 00891 KiLockDispatcherDatabase(&Thread->WaitIrql); 00892 } 00893 00894 // 00895 // Start of wait loop. 00896 // 00897 // Note this loop is repeated if a kernel APC is delivered in the middle 00898 // of the wait or a kernel APC is pending on the first attempt through 00899 // the loop. 00900 // 00901 00902 OriginalTime = Timeout; 00903 WaitBlock = &Thread->WaitBlock[0]; 00904 do { 00905 00906 // 00907 // Test to determine if a kernel APC is pending. 00908 // 00909 // If a kernel APC is pending and the previous IRQL was less than 00910 // APC_LEVEL, then a kernel APC was queued by another processor just 00911 // after IRQL was raised to DISPATCH_LEVEL, but before the dispatcher 00912 // database was locked. 00913 // 00914 // N.B. that this can only happen in a multiprocessor system. 00915 // 00916 00917 if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { 00918 00919 // 00920 // Unlock the dispatcher database and lower IRQL to its previous 00921 // value. An APC interrupt will immediately occur which will result 00922 // in the delivery of the kernel APC if possible. 00923 // 00924 00925 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00926 00927 } else { 00928 00929 // 00930 // Test if the wait can be immediately satisfied. 00931 // 00932 00933 Objectx = (PKMUTANT)Object; 00934 Thread->WaitStatus = (NTSTATUS)0; 00935 00936 ASSERT(Objectx->Header.Type != QueueObject); 00937 00938 // 00939 // If the object is a mutant object and the mutant object has been 00940 // recursively acquired MINLONG times, then raise an exception. 00941 // Otherwise if the signal state of the mutant object is greater 00942 // than zero, or the current thread is the owner of the mutant 00943 // object, then satisfy the wait. 00944 // 00945 00946 if (Objectx->Header.Type == MutantObject) { 00947 if ((Objectx->Header.SignalState > 0) || 00948 (Thread == Objectx->OwnerThread)) { 00949 if (Objectx->Header.SignalState != MINLONG) { 00950 KiWaitSatisfyMutant(Objectx, Thread); 00951 WaitStatus = (NTSTATUS)(Thread->WaitStatus); 00952 goto NoWait; 00953 00954 } else { 00955 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00956 ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED); 00957 } 00958 } 00959 00960 // 00961 // If the signal state is greater than zero, then satisfy the wait. 00962 // 00963 00964 } else if (Objectx->Header.SignalState > 0) { 00965 KiWaitSatisfyOther(Objectx); 00966 WaitStatus = (NTSTATUS)(0); 00967 goto NoWait; 00968 } 00969 00970 // 00971 // Construct a wait block for the object. 00972 // 00973 00974 Thread->WaitBlockList = WaitBlock; 00975 WaitBlock->Object = Object; 00976 WaitBlock->WaitKey = (CSHORT)(STATUS_SUCCESS); 00977 WaitBlock->WaitType = WaitAny; 00978 00979 // 00980 // Test for alert pending. 00981 // 00982 00983 TestForAlertPending(Alertable); 00984 00985 // 00986 // The wait cannot be satisifed immediately. Check to determine if 00987 // a timeout value is specified. 00988 // 00989 00990 if (ARGUMENT_PRESENT(Timeout)) { 00991 00992 // 00993 // If the timeout value is zero, then return immediately without 00994 // waiting. 00995 // 00996 00997 if (!(Timeout->LowPart | Timeout->HighPart)) { 00998 WaitStatus = (NTSTATUS)(STATUS_TIMEOUT); 00999 goto NoWait; 01000 } 01001 01002 // 01003 // Initialize a wait block for the thread specific timer, insert 01004 // wait block in timer wait list, insert the timer in the timer 01005 // tree. 01006 // 01007 // N.B. The timer wait block is initialized when the respective 01008 // thread is initialized. Thus the constant fields are not 01009 // reinitialized. These include the wait object, wait key, 01010 // wait type, and the wait list entry link pointers. 01011 // 01012 01013 Timer = &Thread->Timer; 01014 WaitTimer = &Thread->WaitBlock[TIMER_WAIT_BLOCK]; 01015 WaitBlock->NextWaitBlock = WaitTimer; 01016 Timer->Header.WaitListHead.Flink = &WaitTimer->WaitListEntry; 01017 Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry; 01018 WaitTimer->NextWaitBlock = WaitBlock; 01019 if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { 01020 WaitStatus = (NTSTATUS)STATUS_TIMEOUT; 01021 goto NoWait; 01022 } 01023 01024 DueTime.QuadPart = Timer->DueTime.QuadPart; 01025 01026 } else { 01027 WaitBlock->NextWaitBlock = WaitBlock; 01028 } 01029 01030 // 01031 // Insert wait block in object wait list. 01032 // 01033 01034 InsertTailList(&Objectx->Header.WaitListHead, &WaitBlock->WaitListEntry); 01035 01036 // 01037 // If the current thread is processing a queue entry, then attempt 01038 // to activate another thread that is blocked on the queue object. 01039 // 01040 01041 Queue = Thread->Queue; 01042 if (Queue != NULL) { 01043 KiActivateWaiterQueue(Queue); 01044 } 01045 01046 // 01047 // Set the thread wait parameters, set the thread dispatcher state 01048 // to Waiting, and insert the thread in the wait list. 01049 // 01050 01051 Thread->Alertable = Alertable; 01052 Thread->WaitMode = WaitMode; 01053 Thread->WaitReason = (UCHAR)WaitReason; 01054 Thread->WaitTime= KiQueryLowTickCount(); 01055 Thread->State = Waiting; 01056 KiInsertWaitList(WaitMode, Thread); 01057 01058 // 01059 // Switch context to selected thread. 01060 // 01061 // Control is returned at the original IRQL. 01062 // 01063 01064 ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL); 01065 01066 WaitStatus = (NTSTATUS)KiSwapThread(); 01067 01068 // 01069 // If the thread was not awakened to deliver a kernel mode APC, 01070 // then return wait status. 01071 // 01072 01073 if (WaitStatus != STATUS_KERNEL_APC) { 01074 return WaitStatus; 01075 } 01076 01077 if (ARGUMENT_PRESENT(Timeout)) { 01078 01079 // 01080 // Reduce the amount of time remaining before timeout occurs. 01081 // 01082 01083 Timeout = KiComputeWaitInterval(OriginalTime, 01084 &DueTime, 01085 &NewTime); 01086 } 01087 } 01088 01089 // 01090 // Raise IRQL to DISPATCH_LEVEL and lock the dispatcher database. 01091 // 01092 01093 KiLockDispatcherDatabase(&Thread->WaitIrql); 01094 } while (TRUE); 01095 01096 // 01097 // The thread is alerted or a user APC should be delivered. Unlock the 01098 // dispatcher database, lower IRQL to its previous value, and return 01099 // the wait status. 01100 // 01101 01102 KiUnlockDispatcherDatabase(Thread->WaitIrql); 01103 return WaitStatus; 01104 01105 // 01106 // The wait has been satisfied without actually waiting. 01107 // 01108 // If the thread priority that is less than time critical, then reduce 01109 // the thread quantum. If a quantum end occurs, then reduce the thread 01110 // priority. 01111 // 01112 01113 NoWait: 01114 KiAdjustQuantumThread(Thread); 01115 01116 // 01117 // Unlock the dispatcher database, lower IRQL to its previous value, and 01118 // return the wait status. 01119 // 01120 01121 KiUnlockDispatcherDatabase(Thread->WaitIrql); 01122 return WaitStatus; 01123 }

VOID KiAdjustQuantumThread IN PKTHREAD  Thread  ) 
 

Definition at line 79 of file wait.c.

References KeGetCurrentPrcb, KiFindReadyThread(), KiSetPriorityThread(), NULL, Standby, _KTHREAD::State, _KPROCESS::ThreadQuantum, TIME_CRITICAL_PRIORITY_BOUND, and WAIT_QUANTUM_DECREMENT.

Referenced by KeWaitForMultipleObjects(), and KeWaitForSingleObject().

00085 : 00086 00087 If the current thread is not a time critical or realtime thread, then 00088 adjust its quantum in accordance with the adjustment that would have 00089 occured if the thread had actually waited. 00090 00091 Arguments: 00092 00093 Thread - Supplies a pointer to the current thread. 00094 00095 Return Value: 00096 00097 None. 00098 00099 --*/ 00100 00101 { 00102 PKPRCB Prcb; 00103 PKPROCESS Process; 00104 PKTHREAD NewThread; 00105 SCHAR ThreadPriority; 00106 00107 if ((Thread->Priority < LOW_REALTIME_PRIORITY) && 00108 (Thread->BasePriority < TIME_CRITICAL_PRIORITY_BOUND)) { 00109 Thread->Quantum -= WAIT_QUANTUM_DECREMENT; 00110 if (Thread->Quantum <= 0) { 00111 Process = Thread->ApcState.Process; 00112 Thread->Quantum = Process->ThreadQuantum; 00113 ThreadPriority = Thread->Priority - (Thread->PriorityDecrement + 1); 00114 if (ThreadPriority < Thread->BasePriority) { 00115 ThreadPriority = Thread->BasePriority; 00116 } 00117 00118 Thread->PriorityDecrement = 0; 00119 if (ThreadPriority != Thread->Priority) { 00120 KiSetPriorityThread(Thread, ThreadPriority); 00121 00122 } else { 00123 Prcb = KeGetCurrentPrcb(); 00124 if (Prcb->NextThread == NULL) { 00125 NewThread = KiFindReadyThread(Thread->NextProcessor, 00126 ThreadPriority); 00127 if (NewThread != NULL) { 00128 Prcb->NextThread = NewThread; 00129 NewThread->State = Standby; 00130 } 00131 } 00132 } 00133 } 00134 } 00135 00136 return; 00137 }

PLARGE_INTEGER FASTCALL KiComputeWaitInterval IN PLARGE_INTEGER  OriginalTime,
IN PLARGE_INTEGER  DueTime,
IN OUT PLARGE_INTEGER  NewTime
 

Definition at line 1175 of file wait.c.

Referenced by KeDelayExecutionThread(), KeRemoveQueue(), KeWaitForMultipleObjects(), and KeWaitForSingleObject().

01183 : 01184 01185 This function recomputes the wait interval after a thread has been 01186 awakened to deliver a kernel APC. 01187 01188 Arguments: 01189 01190 OriginalTime - Supplies a pointer to the original timeout value. 01191 01192 DueTime - Supplies a pointer to the previous due time. 01193 01194 NewTime - Supplies a pointer to a variable that receives the 01195 recomputed wait interval. 01196 01197 Return Value: 01198 01199 A pointer to the new time is returned as the function value. 01200 01201 --*/ 01202 01203 { 01204 01205 // 01206 // If the original wait time was absolute, then return the same 01207 // absolute time. Otherwise, reduce the wait time remaining before 01208 // the time delay expires. 01209 // 01210 01211 if (OriginalTime->QuadPart >= 0) { 01212 return OriginalTime; 01213 01214 } else { 01215 KiQueryInterruptTime(NewTime); 01216 NewTime->QuadPart -= DueTime->QuadPart; 01217 return NewTime; 01218 } 01219 } }

NTSTATUS KiSetServerWaitClientEvent IN PKEVENT  ServerEvent,
IN PKEVENT  ClientEvent,
IN ULONG  WaitMode
 

Definition at line 1126 of file wait.c.

References EVENT_INCREMENT, FALSE, KeSetEvent(), KeWaitForSingleObject(), KPROCESSOR_MODE, NULL, TRUE, and WrEventPair.

01134 : 01135 01136 This function sets the specified server event and waits on specified 01137 client event. The wait is performed such that an optimal switch to 01138 the waiting thread occurs if possible. No timeout is associated with 01139 the wait, and thus, the issuing thread will wait until the client event 01140 is signaled or an APC is delivered. 01141 01142 Arguments: 01143 01144 ServerEvent - Supplies a pointer to a dispatcher object of type event. 01145 01146 ClientEvent - Supplies a pointer to a dispatcher object of type event. 01147 01148 WaitMode - Supplies the processor mode in which the wait is to occur. 01149 01150 Return Value: 01151 01152 The wait completion status. A value of STATUS_SUCCESS is returned if 01153 the specified object satisfied the wait. A value of STATUS_USER_APC is 01154 returned if the wait was aborted to deliver a user APC to the current 01155 thread. 01156 01157 --*/ 01158 01159 { 01160 01161 // 01162 // Set sever event and wait on client event atomically. 01163 // 01164 01165 KeSetEvent(ServerEvent, EVENT_INCREMENT, TRUE); 01166 return KeWaitForSingleObject(ClientEvent, 01167 WrEventPair, 01168 (KPROCESSOR_MODE)WaitMode, 01169 FALSE, 01170 NULL); 01171 }


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