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

queueobj.c File Reference

#include "ki.h"

Go to the source code of this file.

Defines

#define ASSERT_QUEUE(Q)   ASSERT((Q)->Header.Type == QueueObject);

Functions

VOID KeInitializeQueue (IN PRKQUEUE Queue, IN ULONG Count OPTIONAL)
LONG KeReadStateQueue (IN PRKQUEUE Queue)
LONG KeInsertQueue (IN PRKQUEUE Queue, IN PLIST_ENTRY Entry)
LONG KeInsertHeadQueue (IN PRKQUEUE Queue, IN PLIST_ENTRY Entry)
PLIST_ENTRY KeRemoveQueue (IN PRKQUEUE Queue, IN KPROCESSOR_MODE WaitMode, IN PLARGE_INTEGER Timeout OPTIONAL)
PLIST_ENTRY KeRundownQueue (IN PRKQUEUE Queue)
VOID FASTCALL KiActivateWaiterQueue (IN PRKQUEUE Queue)
LONG FASTCALL KiInsertQueue (IN PRKQUEUE Queue, IN PLIST_ENTRY Entry, IN BOOLEAN Head)


Define Documentation

#define ASSERT_QUEUE Q   )     ASSERT((Q)->Header.Type == QueueObject);
 

Definition at line 33 of file queueobj.c.

Referenced by KeInsertHeadQueue(), KeInsertQueue(), KeReadStateQueue(), KeRemoveQueue(), KeRundownQueue(), and KiInsertQueue().


Function Documentation

VOID KeInitializeQueue IN PRKQUEUE  Queue,
IN ULONG Count  OPTIONAL
 

Definition at line 36 of file queueobj.c.

References Count, KeNumberProcessors, and QueueObject.

Referenced by ExpWorkerInitialization(), FsRtlInitializeWorkerThread(), and NtCreateIoCompletion().

00043 : 00044 00045 This function initializes a kernel queue object. 00046 00047 Arguments: 00048 00049 Queue - Supplies a pointer to a dispatcher object of type event. 00050 00051 Count - Supplies the target maximum number of threads that should 00052 be concurrently active. If this parameter is not specified, 00053 then the number of processors is used. 00054 00055 Return Value: 00056 00057 None. 00058 00059 --*/ 00060 00061 { 00062 00063 // 00064 // Initialize standard dispatcher object header and set initial 00065 // state of queue object. 00066 // 00067 00068 Queue->Header.Type = QueueObject; 00069 Queue->Header.Size = sizeof(KQUEUE) / sizeof(LONG); 00070 Queue->Header.SignalState = 0; 00071 InitializeListHead(&Queue->Header.WaitListHead); 00072 00073 // 00074 // Initialize queue listhead, the thread list head, the current number 00075 // of threads, and the target maximum number of threads. 00076 // 00077 00078 InitializeListHead(&Queue->EntryListHead); 00079 InitializeListHead(&Queue->ThreadListHead); 00080 Queue->CurrentCount = 0; 00081 if (ARGUMENT_PRESENT((PVOID)(ULONG_PTR)Count)) { 00082 Queue->MaximumCount = Count; 00083 00084 } else { 00085 Queue->MaximumCount = KeNumberProcessors; 00086 } 00087 00088 return; 00089 }

LONG KeInsertHeadQueue IN PRKQUEUE  Queue,
IN PLIST_ENTRY  Entry
 

Definition at line 181 of file queueobj.c.

References ASSERT, ASSERT_QUEUE, DISPATCH_LEVEL, KiInsertQueue(), KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), and TRUE.

00188 : 00189 00190 This function inserts the specified entry in the queue object entry 00191 list and attempts to satisfy the wait of a single waiter. 00192 00193 N.B. The wait discipline for Queue object is LIFO. 00194 00195 Arguments: 00196 00197 Queue - Supplies a pointer to a dispatcher object of type Queue. 00198 00199 Entry - Supplies a pointer to a list entry that is inserted in the 00200 queue object entry list. 00201 00202 Return Value: 00203 00204 The previous signal state of the Queue object. 00205 00206 --*/ 00207 00208 { 00209 00210 KIRQL OldIrql; 00211 LONG OldState; 00212 00213 ASSERT_QUEUE(Queue); 00214 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00215 00216 // 00217 // Raise IRQL to dispatcher level and lock dispatcher database. 00218 // 00219 00220 KiLockDispatcherDatabase(&OldIrql); 00221 00222 // 00223 // Insert the specified entry in the queue object entry list. 00224 // 00225 00226 OldState = KiInsertQueue(Queue, Entry, TRUE); 00227 00228 // 00229 // Unlock the dispather database, lower IRQL to the previous level, and 00230 // return signal state of Queue object. 00231 // 00232 00233 KiUnlockDispatcherDatabase(OldIrql); 00234 return OldState; 00235 }

LONG KeInsertQueue IN PRKQUEUE  Queue,
IN PLIST_ENTRY  Entry
 

Definition at line 124 of file queueobj.c.

References ASSERT, ASSERT_QUEUE, DISPATCH_LEVEL, FALSE, KiInsertQueue(), KiLockDispatcherDatabase, and KiUnlockDispatcherDatabase().

Referenced by ExQueueWorkItem(), FsRtlpPostStackOverflow(), IopCompleteRequest(), and IoSetIoCompletion().

00131 : 00132 00133 This function inserts the specified entry in the queue object entry 00134 list and attempts to satisfy the wait of a single waiter. 00135 00136 N.B. The wait discipline for Queue object is LIFO. 00137 00138 Arguments: 00139 00140 Queue - Supplies a pointer to a dispatcher object of type Queue. 00141 00142 Entry - Supplies a pointer to a list entry that is inserted in the 00143 queue object entry list. 00144 00145 Return Value: 00146 00147 The previous signal state of the Queue object. 00148 00149 --*/ 00150 00151 { 00152 00153 KIRQL OldIrql; 00154 LONG OldState; 00155 00156 ASSERT_QUEUE(Queue); 00157 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00158 00159 // 00160 // Raise IRQL to dispatcher level and lock dispatcher database. 00161 // 00162 00163 KiLockDispatcherDatabase(&OldIrql); 00164 00165 // 00166 // Insert the specified entry in the queue object entry list. 00167 // 00168 00169 OldState = KiInsertQueue(Queue, Entry, FALSE); 00170 00171 // 00172 // Unlock the dispather database, lower IRQL to the previous level, and 00173 // return signal state of Queue object. 00174 // 00175 00176 KiUnlockDispatcherDatabase(OldIrql); 00177 return OldState; 00178 }

LONG KeReadStateQueue IN PRKQUEUE  Queue  ) 
 

Definition at line 92 of file queueobj.c.

References ASSERT_QUEUE.

Referenced by ExpDetectWorkerThreadDeadlock(), and NtQueryIoCompletion().

00098 : 00099 00100 This function reads the current signal state of a Queue object. 00101 00102 Arguments: 00103 00104 Queue - Supplies a pointer to a dispatcher object of type Queue. 00105 00106 Return Value: 00107 00108 The current signal state of the Queue object. 00109 00110 --*/ 00111 00112 { 00113 00114 ASSERT_QUEUE(Queue); 00115 00116 // 00117 // Return current signal state of Queue object. 00118 // 00119 00120 return Queue->Header.SignalState; 00121 }

PLIST_ENTRY KeRemoveQueue IN PRKQUEUE  Queue,
IN KPROCESSOR_MODE  WaitMode,
IN PLARGE_INTEGER Timeout  OPTIONAL
 

Definition at line 238 of file queueobj.c.

References _KTHREAD::Alertable, APC_LEVEL, _KTHREAD::ApcState, ASSERT, ASSERT_QUEUE, DISPATCH_LEVEL, _KTIMER::DueTime, ExWorkerQueue, FALSE, _KTIMER::Header, KeBugCheckEx(), KeGetCurrentThread, _KAPC_STATE::KernelApcPending, KernelMode, KiActivateWaiterQueue(), KiComputeWaitInterval(), KiInsertTreeTimer(), KiInsertWaitList, KiLockDispatcherDatabase, KiSwapThread(), KiUnlockDispatcherDatabase(), _KWAIT_BLOCK::NextWaitBlock, NTSTATUS(), NULL, _KWAIT_BLOCK::Object, _KTHREAD::Queue, _KTHREAD::QueueListEntry, _KTHREAD::State, _KWAIT_BLOCK::Thread, _KTHREAD::Timer, TRUE, _KAPC_STATE::UserApcPending, _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, _KWAIT_BLOCK::WaitType, and WrQueue.

Referenced by ExpWorkerThread(), FsRtlWorkerThread(), and NtRemoveIoCompletion().

00246 : 00247 00248 This function removes the next entry from the Queue object entry 00249 list. If no list entry is available, then the calling thread is 00250 put in a wait state. 00251 00252 N.B. The wait discipline for Queue object LIFO. 00253 00254 Arguments: 00255 00256 Queue - Supplies a pointer to a dispatcher object of type Queue. 00257 00258 WaitMode - Supplies the processor mode in which the wait is to occur. 00259 00260 Timeout - Supplies a pointer to an optional absolute of relative time over 00261 which the wait is to occur. 00262 00263 Return Value: 00264 00265 The address of the entry removed from the Queue object entry list or 00266 STATUS_TIMEOUT. 00267 00268 N.B. These values can easily be distinguished by the fact that all 00269 addresses in kernel mode have the high order bit set. 00270 00271 --*/ 00272 00273 { 00274 00275 LARGE_INTEGER DueTime; 00276 PLIST_ENTRY Entry; 00277 PRKTHREAD NextThread; 00278 LARGE_INTEGER NewTime; 00279 KIRQL OldIrql; 00280 PRKQUEUE OldQueue; 00281 PLARGE_INTEGER OriginalTime; 00282 PRKTHREAD Thread; 00283 PRKTIMER Timer; 00284 PRKWAIT_BLOCK WaitBlock; 00285 LONG_PTR WaitStatus; 00286 00287 ASSERT_QUEUE(Queue); 00288 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00289 00290 // 00291 // If the dispatcher database lock is not already held, then set the wait 00292 // IRQL and lock the dispatcher database. Else set boolean wait variable 00293 // to FALSE. 00294 // 00295 00296 Thread = KeGetCurrentThread(); 00297 if (Thread->WaitNext) { 00298 Thread->WaitNext = FALSE; 00299 00300 } else { 00301 KiLockDispatcherDatabase(&OldIrql); 00302 Thread->WaitIrql = OldIrql; 00303 } 00304 00305 // 00306 // Check if the thread is currently processing a queue entry and whether 00307 // the new queue is the same as the old queue. 00308 // 00309 00310 OldQueue = Thread->Queue; 00311 Thread->Queue = Queue; 00312 if (Queue != OldQueue) { 00313 00314 // 00315 // If the thread was previously associated with a queue, then remove 00316 // the thread from the old queue object thread list and attempt to 00317 // activate another thread. 00318 // 00319 00320 Entry = &Thread->QueueListEntry; 00321 if (OldQueue != NULL) { 00322 RemoveEntryList(Entry); 00323 KiActivateWaiterQueue(OldQueue); 00324 } 00325 00326 // 00327 // Insert thread in the thread list of the new queue that the thread 00328 // will be associate with. 00329 // 00330 00331 InsertTailList(&Queue->ThreadListHead, Entry); 00332 00333 } else { 00334 00335 // 00336 // The previous and current queue are the same queue - decrement the 00337 // current number of threads. 00338 // 00339 00340 Queue->CurrentCount -= 1; 00341 } 00342 00343 // 00344 // 00345 // Start of wait loop. 00346 // 00347 // 00348 // Note this loop is repeated if a kernel APC is delivered in the 00349 // middle of the wait or a kernel APC is pending on the first attempt 00350 // through the loop. 00351 // 00352 // If the Queue object entry list is not empty, then remove the next 00353 // entry from the Queue object entry list. Otherwise, wait for an entry 00354 // to be inserted in the queue. 00355 // 00356 00357 OriginalTime = Timeout; 00358 do { 00359 00360 // 00361 // Check if there is a queue entry available and the current 00362 // number of active threads is less than target maximum number 00363 // of threads. 00364 // 00365 00366 Entry = Queue->EntryListHead.Flink; 00367 if ((Entry != &Queue->EntryListHead) && 00368 (Queue->CurrentCount < Queue->MaximumCount)) { 00369 00370 // 00371 // Decrement the number of entires in the Queue object entry list, 00372 // increment the number of active threads, remove the next entry 00373 // rom the list, and set the forward link to NULL. 00374 // 00375 00376 Queue->Header.SignalState -= 1; 00377 Queue->CurrentCount += 1; 00378 if ((Entry->Flink == NULL) || (Entry->Blink == NULL)) { 00379 KeBugCheckEx(INVALID_WORK_QUEUE_ITEM, 00380 (ULONG_PTR)Entry, 00381 (ULONG_PTR)Queue, 00382 (ULONG_PTR)&ExWorkerQueue[0], 00383 (ULONG_PTR)((PWORK_QUEUE_ITEM)Entry)->WorkerRoutine); 00384 } 00385 00386 RemoveEntryList(Entry); 00387 Entry->Flink = NULL; 00388 break; 00389 00390 } else { 00391 00392 // 00393 // Set address of wait block list in thread object. 00394 // 00395 00396 Thread->WaitBlockList = &Thread->WaitBlock[0]; 00397 00398 // 00399 // Test to determine if a kernel APC is pending. 00400 // 00401 // If a kernel APC is pending and the previous IRQL was less than 00402 // APC_LEVEL, then a kernel APC was queued by another processor 00403 // just after IRQL was raised to DISPATCH_LEVEL, but before the 00404 // dispatcher database was locked. 00405 // 00406 // N.B. that this can only happen in a multiprocessor system. 00407 // 00408 00409 if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { 00410 00411 // 00412 // Increment the current thread count, unlock the dispatcher 00413 // database, and lower IRQL to previous value. An APC interrupt 00414 // will immediately occur which will result in the delivery of 00415 // the kernel APC if possible. 00416 // 00417 00418 Queue->CurrentCount += 1; 00419 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00420 00421 } else { 00422 00423 // 00424 // Test if a user APC is pending. 00425 // 00426 00427 if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending)) { 00428 Entry = (PLIST_ENTRY)ULongToPtr(STATUS_USER_APC); 00429 Queue->CurrentCount += 1; 00430 break; 00431 } 00432 00433 // 00434 // Construct a wait block and check to determine if the wait 00435 // is already satisfied. If the wait is satisfied, then perform 00436 // wait completion and return. Else put current thread in a 00437 // wait state if an explicit timeout value of zero is not 00438 // specified. 00439 // 00440 00441 Thread->WaitStatus = (NTSTATUS)0; 00442 WaitBlock = &Thread->WaitBlock[0]; 00443 WaitBlock->Object = (PVOID)Queue; 00444 WaitBlock->WaitKey = (CSHORT)(STATUS_SUCCESS); 00445 WaitBlock->WaitType = WaitAny; 00446 WaitBlock->Thread = Thread; 00447 00448 // 00449 // Check to determine if a timeout value is specified. 00450 // 00451 00452 if (ARGUMENT_PRESENT(Timeout)) { 00453 00454 // 00455 // If the timeout value is zero, then return immediately 00456 // without waiting. 00457 // 00458 00459 if (!(Timeout->LowPart | Timeout->HighPart)) { 00460 Entry = (PLIST_ENTRY)ULongToPtr(STATUS_TIMEOUT); 00461 Queue->CurrentCount += 1; 00462 break; 00463 } 00464 00465 // 00466 // Initialize a wait block for the thread specific timer, 00467 // insert wait block in timer wait list, insert the timer 00468 // in the timer tree. 00469 // 00470 00471 Timer = &Thread->Timer; 00472 WaitBlock->NextWaitBlock = &Thread->WaitBlock[1]; 00473 WaitBlock = &Thread->WaitBlock[1]; 00474 WaitBlock->Object = (PVOID)Timer; 00475 WaitBlock->WaitKey = (CSHORT)(STATUS_TIMEOUT); 00476 WaitBlock->WaitType = WaitAny; 00477 WaitBlock->Thread = Thread; 00478 Timer->Header.WaitListHead.Flink = &WaitBlock->WaitListEntry; 00479 Timer->Header.WaitListHead.Blink = &WaitBlock->WaitListEntry; 00480 WaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead; 00481 WaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead; 00482 if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { 00483 Entry = (PLIST_ENTRY)ULongToPtr(STATUS_TIMEOUT); 00484 Queue->CurrentCount += 1; 00485 break; 00486 } 00487 00488 DueTime.QuadPart = Timer->DueTime.QuadPart; 00489 } 00490 00491 // 00492 // Close up the circular list of wait control blocks. 00493 // 00494 00495 WaitBlock->NextWaitBlock = &Thread->WaitBlock[0]; 00496 00497 // 00498 // Insert wait block in object wait list. 00499 // 00500 00501 WaitBlock = &Thread->WaitBlock[0]; 00502 InsertTailList(&Queue->Header.WaitListHead, &WaitBlock->WaitListEntry); 00503 00504 // 00505 // Set the thread wait parameters, set the thread dispatcher 00506 // state to Waiting, and insert the thread in the wait list. 00507 // 00508 00509 Thread->Alertable = FALSE; 00510 Thread->WaitMode = WaitMode; 00511 Thread->WaitReason = WrQueue; 00512 Thread->WaitTime = KiQueryLowTickCount(); 00513 Thread->State = Waiting; 00514 KiInsertWaitList(WaitMode, Thread); 00515 00516 // 00517 // Switch context to selected thread. 00518 // 00519 // Control is returned at the original IRQL. 00520 // 00521 00522 ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL); 00523 00524 WaitStatus = KiSwapThread(); 00525 00526 // 00527 // If the thread was not awakened to deliver a kernel mode APC, 00528 // then return wait status. 00529 // 00530 00531 Thread->WaitReason = 0; 00532 if (WaitStatus != STATUS_KERNEL_APC) { 00533 return (PLIST_ENTRY)WaitStatus; 00534 } 00535 00536 if (ARGUMENT_PRESENT(Timeout)) { 00537 00538 // 00539 // Reduce the amount of time remaining before timeout occurs. 00540 // 00541 00542 Timeout = KiComputeWaitInterval(OriginalTime, 00543 &DueTime, 00544 &NewTime); 00545 } 00546 } 00547 00548 // 00549 // Raise IRQL to DISPATCH_LEVEL, lock the dispatcher database, 00550 // and decrement the count of active threads. 00551 // 00552 00553 KiLockDispatcherDatabase(&OldIrql); 00554 Thread->WaitIrql = OldIrql; 00555 Queue->CurrentCount -= 1; 00556 } 00557 00558 } while (TRUE); 00559 00560 // 00561 // Unlock the dispatcher database and return the list entry address or a 00562 // status of timeout. 00563 // 00564 00565 KiUnlockDispatcherDatabase(Thread->WaitIrql); 00566 return Entry; 00567 }

PLIST_ENTRY KeRundownQueue IN PRKQUEUE  Queue  ) 
 

Definition at line 570 of file queueobj.c.

References ASSERT, ASSERT_QUEUE, DISPATCH_LEVEL, KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), NULL, and _KTHREAD::Queue.

Referenced by IopDeleteIoCompletion().

00576 : 00577 00578 This function runs down the specified queue by removing the listhead 00579 from the queue list, removing any associated threads from the thread 00580 list, and returning the address of the first entry. 00581 00582 00583 Arguments: 00584 00585 Queue - Supplies a pointer to a dispatcher object of type Queue. 00586 00587 Return Value: 00588 00589 If the queue list is not empty, then the address of the first entry in 00590 the queue is returned as the function value. Otherwise, a value of NULL 00591 is returned. 00592 00593 --*/ 00594 00595 { 00596 00597 PLIST_ENTRY Entry; 00598 PLIST_ENTRY FirstEntry; 00599 KIRQL OldIrql; 00600 PKTHREAD Thread; 00601 00602 ASSERT_QUEUE(Queue); 00603 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00604 00605 // 00606 // Raise IRQL to dispatch level and lock the dispatcher database. 00607 // 00608 00609 KiLockDispatcherDatabase(&OldIrql); 00610 00611 // 00612 // Get the address of the first entry in the queue and check if the 00613 // list is empty or contains entries that should be flushed. If there 00614 // are no entries in the list, then set the return value to NULL. 00615 // Otherwise, set the return value to the address of the first list 00616 // entry and remove the listhead from the list. 00617 // 00618 00619 FirstEntry = Queue->EntryListHead.Flink; 00620 if (FirstEntry == &Queue->EntryListHead) { 00621 FirstEntry = NULL; 00622 00623 } else { 00624 RemoveEntryList(&Queue->EntryListHead); 00625 } 00626 00627 // 00628 // Remove all associated threads from the thread list of the queue. 00629 // 00630 00631 while (Queue->ThreadListHead.Flink != &Queue->ThreadListHead) { 00632 Entry = Queue->ThreadListHead.Flink; 00633 Thread = CONTAINING_RECORD(Entry, KTHREAD, QueueListEntry); 00634 Thread->Queue = NULL; 00635 RemoveEntryList(Entry); 00636 } 00637 00638 // 00639 // Unlock the dispatcher database, lower IRQL to its previous level, 00640 // and return the function value. 00641 // 00642 00643 KiUnlockDispatcherDatabase(OldIrql); 00644 return FirstEntry; 00645 }

VOID FASTCALL KiActivateWaiterQueue IN PRKQUEUE  Queue  ) 
 

Definition at line 649 of file queueobj.c.

References KiUnwaitThread(), NULL, and _KWAIT_BLOCK::Thread.

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

00655 : 00656 00657 This function is called when the current thread is about to enter a 00658 wait state and is currently processing a queue entry. The current 00659 number of threads processign entries for the queue is decrement and 00660 an attempt is made to activate another thread if the current count 00661 is less than the maximum count, there is a waiting thread, and the 00662 queue is not empty. 00663 00664 Arguments: 00665 00666 Queue - Supplies a pointer to a dispatcher object of type event. 00667 00668 Return Value: 00669 00670 None. 00671 00672 --*/ 00673 00674 { 00675 00676 PRLIST_ENTRY Entry; 00677 PRKTHREAD Thread; 00678 PRKWAIT_BLOCK WaitBlock; 00679 PRLIST_ENTRY WaitEntry; 00680 00681 // 00682 // Decrement the current count of active threads and check if another 00683 // thread can be activated. If the current number of active threads is 00684 // less than the target maximum number of threads, there is a entry in 00685 // in the queue, and a thread is waiting, then remove the entry from the 00686 // queue, decrement the number of entries in the queue, and unwait the 00687 // respectiive thread. 00688 // 00689 00690 Queue->CurrentCount -= 1; 00691 if (Queue->CurrentCount < Queue->MaximumCount) { 00692 Entry = Queue->EntryListHead.Flink; 00693 WaitEntry = Queue->Header.WaitListHead.Blink; 00694 if ((Entry != &Queue->EntryListHead) && 00695 (WaitEntry != &Queue->Header.WaitListHead)) { 00696 RemoveEntryList(Entry); 00697 Entry->Flink = NULL; 00698 Queue->Header.SignalState -= 1; 00699 WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry); 00700 Thread = WaitBlock->Thread; 00701 KiUnwaitThread(Thread, (LONG_PTR)Entry, 0); 00702 } 00703 } 00704 00705 return; 00706 }

LONG FASTCALL KiInsertQueue IN PRKQUEUE  Queue,
IN PLIST_ENTRY  Entry,
IN BOOLEAN  Head
 

Definition at line 710 of file queueobj.c.

References ASSERT_QUEUE, FALSE, _KTIMER::Header, _DISPATCHER_HEADER::Inserted, KeGetCurrentThread, KiReadyThread(), KiRemoveTreeTimer, _KTHREAD::Queue, _KWAIT_BLOCK::Thread, _KTHREAD::Timer, TRUE, _KTHREAD::WaitListEntry, _KTHREAD::WaitReason, _KTHREAD::WaitStatus, and WrQueue.

Referenced by KeInsertHeadQueue(), KeInsertQueue(), and KeTerminateThread().

00718 : 00719 00720 This function inserts the specified entry in the queue object entry 00721 list and attempts to satisfy the wait of a single waiter. 00722 00723 N.B. The wait discipline for Queue object is LIFO. 00724 00725 Arguments: 00726 00727 Queue - Supplies a pointer to a dispatcher object of type Queue. 00728 00729 Entry - Supplies a pointer to a list entry that is inserted in the 00730 queue object entry list. 00731 00732 Head - Supplies a boolean value that determines whether the queue 00733 entry is inserted at the head or tail of the queue if it can 00734 not be immediately dispatched. 00735 00736 Return Value: 00737 00738 The previous signal state of the Queue object. 00739 00740 --*/ 00741 00742 { 00743 00744 LONG OldState; 00745 PRKTHREAD Thread; 00746 PKTIMER Timer; 00747 PKWAIT_BLOCK WaitBlock; 00748 PLIST_ENTRY WaitEntry; 00749 00750 ASSERT_QUEUE(Queue); 00751 00752 // 00753 // Capture the current signal state of queue object and check if there 00754 // is a thread waiting on the queue object, the current number of active 00755 // threads is less than the target number of threads, and the wait reason 00756 // of the current thread is not queue wait or the wait queue is not the 00757 // same queue as the insertion queue. If these conditions are satisfied, 00758 // then satisfy the thread wait and pass the thread the address of the 00759 // queue entry as the wait status. Otherwise, set the state of the queue 00760 // object to signaled and insert the specified entry in the queue object 00761 // entry list. 00762 // 00763 00764 OldState = Queue->Header.SignalState; 00765 Thread = KeGetCurrentThread(); 00766 WaitEntry = Queue->Header.WaitListHead.Blink; 00767 if ((WaitEntry != &Queue->Header.WaitListHead) && 00768 (Queue->CurrentCount < Queue->MaximumCount) && 00769 ((Thread->Queue != Queue) || 00770 (Thread->WaitReason != WrQueue))) { 00771 00772 // 00773 // Remove the last wait block from the wait list and get the address 00774 // of the waiting thread object. 00775 // 00776 00777 RemoveEntryList(WaitEntry); 00778 WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry); 00779 Thread = WaitBlock->Thread; 00780 00781 // 00782 // Set the wait completion status, remove the thread from its wait 00783 // list, increment the number of active threads, and clear the wait 00784 // reason. 00785 // 00786 00787 Thread->WaitStatus = (LONG_PTR)Entry; 00788 RemoveEntryList(&Thread->WaitListEntry); 00789 Queue->CurrentCount += 1; 00790 Thread->WaitReason = 0; 00791 00792 // 00793 // If thread timer is still active, then cancel thread timer. 00794 // 00795 00796 Timer = &Thread->Timer; 00797 if (Timer->Header.Inserted == TRUE) { 00798 KiRemoveTreeTimer(Timer); 00799 } 00800 00801 // 00802 // Ready the thread for execution. 00803 // 00804 00805 KiReadyThread(Thread); 00806 00807 } else { 00808 Queue->Header.SignalState += 1; 00809 if (Head != FALSE) { 00810 InsertHeadList(&Queue->EntryListHead, Entry); 00811 00812 } else { 00813 InsertTailList(&Queue->EntryListHead, Entry); 00814 } 00815 } 00816 00817 return OldState; 00818 } }


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