test: waitsup.c File Reference

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

# waitsup.c File Reference

`#include "ki.h"`

Go to the source code of this file.

## Functions

VOID FASTCALL | KiUnwaitThread (IN PRKTHREAD Thread, IN LONG_PTR WaitStatus, IN KPRIORITY Increment)
VOID | KeBoostCurrentThread (VOID)
VOID FASTCALL | KiWaitSatisfyAll (IN PRKWAIT_BLOCK WaitBlock)
VOID FASTCALL | KiWaitTest (IN PVOID Object, IN KPRIORITY Increment)

## Function Documentation

VOID KeBoostCurrentThread | ( | VOID |  | ) |

Definition at line 154 of file waitsup.c.

References _KTHREAD::ApcState, _KTHREAD::BasePriority, _KTHREAD::DecrementCount, KeGetCurrentThread, KeSetPriorityThread(), KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), _KTHREAD::Priority, _KTHREAD::PriorityDecrement, _KAPC_STATE::Process, _KTHREAD::Quantum, ROUND_TRIP_DECREMENT_COUNT, and _KPROCESS::ThreadQuantum.

    00160                    :
    00161
    00162     This function boosts the priority of the current thread for one quantum,
    00163     then reduce the thread priority to the base priority of the thread.
    00164
    00165 Arguments:
    00166
    00167     None.
    00168
    00169 Return Value:
    00170
    00171     None.
    00172
    00173 --*/
    00174
    00175 {
    00176
    00177     KIRQL OldIrql;
    00178     PKTHREAD Thread;
    00179
    00180     //
    00181     // Get current thread address, raise IRQL to synchronization level, and
    00182     // lock the dispatcher database
    00183     //
    00184
    00185     Thread = KeGetCurrentThread();
    00186
    00187 redoboost:
    00188     KiLockDispatcherDatabase(&OldIrql);
    00189
    00190     //
    00191     // If a priority boost is not already active for the current thread
    00192     // and the thread priority is less than 14, then boost the thread
    00193     // priority to 14 and give the thread a large quantum. Otherwise,
    00194     // if a priority boost is active, then decrement the round trip
    00195     // count. If the count goes to zero, then release the dispatcher
    00196     // database lock, lower the thread priority to the base priority,
    00197     // and then attempt to boost the priority again. This will give
    00198     // other threads a chance to run. If the count does not reach zero,
    00199     // then give the thread another large qunatum.
    00200     //
    00201     // If the thread priority is above 14, then no boost is applied.
    00202     //
    00203
    00204     if ((Thread->PriorityDecrement == 0) && (Thread->Priority < 14)) {
    00205         Thread->PriorityDecrement = 14 - Thread->BasePriority;
    00206         Thread->DecrementCount = ROUND_TRIP_DECREMENT_COUNT;
    00207         Thread->Priority = 14;
    00208         Thread->Quantum = Thread->ApcState.Process->ThreadQuantum * 2;
    00209
    00210     } else if (Thread->PriorityDecrement != 0) {
    00211         Thread->DecrementCount -= 1;
    00212         if (Thread->DecrementCount == 0) {
    00213             KiUnlockDispatcherDatabase(OldIrql);
    00214             KeSetPriorityThread(Thread, Thread->BasePriority);
    00215             goto redoboost;
    00216
    00217         } else {
    00218             Thread->Quantum = Thread->ApcState.Process->ThreadQuantum * 2;
    00219         }
    00220     }
    00221
    00222     KiUnlockDispatcherDatabase(OldIrql);
    00223     return;
    00224 }

VOID FASTCALL KiUnwaitThread | ( | IN PRKTHREAD | Thread,
|  | IN LONG_PTR | WaitStatus,
|  | IN KPRIORITY | Increment
| ) |

Definition at line 31 of file waitsup.c.

References _KPROCESS::BasePriority, _KQUEUE::CurrentCount, FALSE, _KTIMER::Header, Increment, _DISPATCHER_HEADER::Inserted, KiReadyThread(), KiRemoveTreeTimer, MEMORY_PRIORITY_FOREGROUND, _KWAIT_BLOCK::NextWaitBlock, NULL, PKQUEUE, PsPrioritySeperation, _KPROCESS::ThreadQuantum, TIME_CRITICAL_PRIORITY_BOUND, WAIT_QUANTUM_DECREMENT, and _KWAIT_BLOCK::WaitListEntry.

Referenced by KeAlertResumeThread(), KeAlertThread(), KeSetEvent(), KeSetEventBoostPriority(), KiActivateWaiterQueue(), KiInsertQueueApc(), and KiWaitTest().

    00039                    :
    00040
    00041     This function unwaits a thread, sets the thread's wait completion status,
    00042     calculates the thread's new priority, and readies the thread for execution.
    00043
    00044 Arguments:
    00045
    00046     Thread - Supplies a pointer to a dispatcher object of type thread.
    00047
    00048     WaitStatus - Supplies the wait completion status.
    00049
    00050     Increment - Supplies the priority increment that is to be applied to
    00051         the thread's priority.
    00052
    00053 Return Value:
    00054
    00055     None.
    00056
    00057 --*/
    00058
    00059 {
    00060
    00061     KPRIORITY NewPriority;
    00062     PKPROCESS Process;
    00063     PKQUEUE Queue;
    00064     PKTIMER Timer;
    00065     PRKWAIT_BLOCK WaitBlock;
    00066
    00067     //
    00068     // Set wait completion status, remove wait blocks from object wait
    00069     // lists, and remove thread from wait list.
    00070     //
    00071
    00072     Thread->WaitStatus |= WaitStatus;
    00073     WaitBlock = Thread->WaitBlockList;
    00074     do {
    00075         RemoveEntryList(&WaitBlock->WaitListEntry);
    00076         WaitBlock = WaitBlock->NextWaitBlock;
    00077     } while (WaitBlock != Thread->WaitBlockList);
    00078
    00079     RemoveEntryList(&Thread->WaitListEntry);
    00080
    00081     //
    00082     // If thread timer is still active, then cancel thread timer.
    00083     //
    00084
    00085     Timer = &Thread->Timer;
    00086     if (Timer->Header.Inserted != FALSE) {
    00087         KiRemoveTreeTimer(Timer);
    00088     }
    00089
    00090     //
    00091     // If the thread is processing a queue entry, then increment the
    00092     // count of currently active threads.
    00093     //
    00094
    00095     Queue = Thread->Queue;
    00096     if (Queue != NULL) {
    00097         Queue->CurrentCount += 1;
    00098     }
    00099
    00100     //
    00101     // If the thread runs at a realtime priority level, then reset the
    00102     // thread quantum. Otherwise, compute the next thread priority and
    00103     // charge the thread for the wait operation.
    00104     //
    00105
    00106     Process = Thread->ApcState.Process;
    00107     if (Thread->Priority < LOW_REALTIME_PRIORITY) {
    00108         if ((Thread->PriorityDecrement == 0) &&
    00109             (Thread->DisableBoost == FALSE)) {
    00110             NewPriority = Thread->BasePriority + Increment;
    00111             if (((PEPROCESS)Process)->Vm.MemoryPriority == MEMORY_PRIORITY_FOREGROUND) {
    00112                 NewPriority += PsPrioritySeperation;
    00113             }
    00114
    00115             if (NewPriority > Thread->Priority) {
    00116                 if (NewPriority >= LOW_REALTIME_PRIORITY) {
    00117                     Thread->Priority = LOW_REALTIME_PRIORITY - 1;
    00118
    00119                 } else {
    00120                     Thread->Priority = (SCHAR)NewPriority;
    00121                 }
    00122             }
    00123         }
    00124
    00125         if (Thread->BasePriority >= TIME_CRITICAL_PRIORITY_BOUND) {
    00126             Thread->Quantum = Process->ThreadQuantum;
    00127
    00128         } else {
    00129             Thread->Quantum -= WAIT_QUANTUM_DECREMENT;
    00130             if (Thread->Quantum <= 0) {
    00131                 Thread->Quantum = Process->ThreadQuantum;
    00132                 Thread->Priority -= (Thread->PriorityDecrement + 1);
    00133                 if (Thread->Priority < Thread->BasePriority) {
    00134                     Thread->Priority = Thread->BasePriority;
    00135                 }
    00136
    00137                 Thread->PriorityDecrement = 0;
    00138             }
    00139         }
    00140
    00141     } else {
    00142         Thread->Quantum = Process->ThreadQuantum;
    00143     }
    00144
    00145     //
    00146     // Reready the thread for execution.
    00147     //
    00148
    00149     KiReadyThread(Thread);
    00150     return;
    00151 }

VOID FASTCALL KiWaitSatisfyAll | ( | IN PRKWAIT_BLOCK | WaitBlock | ) |

Definition at line 228 of file waitsup.c.

References KiWaitSatisfyAny, _KWAIT_BLOCK::NextWaitBlock, _KWAIT_BLOCK::Object, _KWAIT_BLOCK::Thread, and _KWAIT_BLOCK::WaitKey.

Referenced by KeWaitForMultipleObjects(), and KiWaitTest().

    00234                    :
    00235
    00236     This function satisfies a wait all and performs any side effects that
    00237     are necessary.
    00238
    00239 Arguments:
    00240
    00241     WaitBlock - Supplies a pointer to a wait block.
    00242
    00243 Return Value:
    00244
    00245     None.
    00246
    00247 --*/
    00248
    00249 {
    00250
    00251     PKMUTANT Object;
    00252     PRKTHREAD Thread;
    00253     PRKWAIT_BLOCK WaitBlock1;
    00254
    00255     //
    00256     // If the wait type was WaitAny, then perform neccessary side effects on
    00257     // the object specified by the wait block. Else perform necessary side
    00258     // effects on all the objects that were involved in the wait operation.
    00259     //
    00260
    00261     WaitBlock1 = WaitBlock;
    00262     Thread = WaitBlock1->Thread;
    00263     do {
    00264         if (WaitBlock1->WaitKey != (CSHORT)STATUS_TIMEOUT) {
    00265             Object = (PKMUTANT)WaitBlock1->Object;
    00266             KiWaitSatisfyAny(Object, Thread);
    00267         }
    00268
    00269         WaitBlock1 = WaitBlock1->NextWaitBlock;
    00270     } while (WaitBlock1 != WaitBlock);
    00271
    00272     return;
    00273 }

VOID FASTCALL KiWaitTest | ( | IN PVOID | Object,
|  | IN KPRIORITY | Increment
| ) |

Definition at line 277 of file waitsup.c.

References Event(), _KMUTANT::Header, Increment, KiUnwaitThread(), KiWaitSatisfyAll(), KiWaitSatisfyAny, MutantObject, _KWAIT_BLOCK::NextWaitBlock, NTSTATUS(), _KWAIT_BLOCK::Object, _KMUTANT::OwnerThread, _DISPATCHER_HEADER::SignalState, _KWAIT_BLOCK::Thread, _DISPATCHER_HEADER::Type, _KWAIT_BLOCK::WaitKey, and _KWAIT_BLOCK::WaitType.

Referenced by KeAlertResumeThread(), KeDetachProcess(), KeForceResumeThread(), KePulseEvent(), KeReleaseMutant(), KeReleaseSemaphore(), KeResumeThread(), KeRundownThread(), KeSetEvent(), KeSetProcess(), KeSetTimerEx(), KeTerminateThread(), KeThawAllThreads(), KeUnstackDetachProcess(), KiAttachProcess(), KiReadyThread(), and KiTimerListExpire().

    00284                    :
    00285
    00286     This function tests if a wait can be satisfied when an object attains
    00287     a state of signaled. If a wait can be satisfied, then the subject thread
    00288     is unwaited with a completion status that is the WaitKey of the wait
    00289     block from the object wait list. As many waits as possible are satisfied.
    00290
    00291 Arguments:
    00292
    00293     Object - Supplies a pointer to a dispatcher object.
    00294
    00295 Return Value:
    00296
    00297     None.
    00298
    00299 --*/
    00300
    00301 {
    00302
    00303     PKEVENT Event;
    00304     PLIST_ENTRY ListHead;
    00305     PRKWAIT_BLOCK NextBlock;
    00306     PKMUTANT Mutant;
    00307     PRKTHREAD Thread;
    00308     PRKWAIT_BLOCK WaitBlock;
    00309     PLIST_ENTRY WaitEntry;
    00310
    00311     //
    00312     // As long as the signal state of the specified object is Signaled and
    00313     // there are waiters in the object wait list, then try to satisfy a wait.
    00314     //
    00315
    00316     Event = (PKEVENT)Object;
    00317     ListHead = &Event->Header.WaitListHead;
    00318     WaitEntry = ListHead->Flink;
    00319     while ((Event->Header.SignalState > 0) &&
    00320            (WaitEntry != ListHead)) {
    00321         WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
    00322         Thread = WaitBlock->Thread;
    00323         if (WaitBlock->WaitType != WaitAny) {
    00324
    00325             //
    00326             // The wait type is wait all - if all the objects are in
    00327             // a Signaled state, then satisfy the wait.
    00328             //
    00329
    00330             NextBlock = WaitBlock->NextWaitBlock;
    00331             while (NextBlock != WaitBlock) {
    00332                 if (NextBlock->WaitKey != (CSHORT)(STATUS_TIMEOUT)) {
    00333                     Mutant = (PKMUTANT)NextBlock->Object;
    00334                     if ((Mutant->Header.Type == MutantObject) &&
    00335                         (Mutant->Header.SignalState <= 0) &&
    00336                         (Thread == Mutant->OwnerThread)) {
    00337                         goto next;
    00338
    00339                     } else if (Mutant->Header.SignalState <= 0) {
    00340                         goto scan;
    00341                     }
    00342                 }
    00343
    00344             next:
    00345                 NextBlock = NextBlock->NextWaitBlock;
    00346             }
    00347
    00348             //
    00349             // All objects associated with the wait are in the Signaled
    00350             // state - satisfy the wait.
    00351             //
    00352
    00353             WaitEntry = WaitEntry->Blink;
    00354             KiWaitSatisfyAll(WaitBlock);
    00355
    00356         } else {
    00357
    00358             //
    00359             // The wait type is wait any - satisfy the wait.
    00360             //
    00361
    00362             WaitEntry = WaitEntry->Blink;
    00363             KiWaitSatisfyAny((PKMUTANT)Event, Thread);
    00364         }
    00365
    00366         KiUnwaitThread(Thread, (NTSTATUS)WaitBlock->WaitKey, Increment);
    00367
    00368     scan:
    00369         WaitEntry = WaitEntry->Flink;
    00370     }
    00371
    00372     return;
    00373 }
    }