diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 68e73bc57bb..b70b545331d 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -526,6 +526,12 @@ ULONG NTAPI KeForceResumeThread(IN PKTHREAD Thread); +VOID +NTAPI +KeThawAllThreads( + VOID +); + VOID NTAPI KeFreezeAllThreads( diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index db44380e610..e2f63f6ab85 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -304,11 +304,17 @@ KeFreezeAllThreads(VOID) /* Release the APC lock */ KiReleaseApcLockFromDpcLevel(&ApcLock); + + /* Move to the next thread */ + NextEntry = NextEntry->Flink; } /* Release the process lock and exit the dispatcher */ KiReleaseProcessLock(&LockHandle); KiExitDispatcher(LockHandle.OldIrql); + + /* Leave the critical region */ + KeLeaveCriticalRegion(); } ULONG @@ -573,6 +579,71 @@ KeSuspendThread(PKTHREAD Thread) return PreviousCount; } +VOID +NTAPI +KeThawAllThreads(VOID) +{ + KLOCK_QUEUE_HANDLE LockHandle, ApcLock; + PKTHREAD Current, CurrentThread = KeGetCurrentThread(); + PKPROCESS Process = CurrentThread->ApcState.Process; + PLIST_ENTRY ListHead, NextEntry; + LONG OldCount; + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); + + /* Lock the process */ + KiAcquireProcessLock(Process, &LockHandle); + + /* Enter a critical region */ + KeEnterCriticalRegion(); + + /* Loop the Process's Threads */ + ListHead = &Process->ThreadListHead; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the current thread */ + Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); + + /* Lock it */ + KiAcquireApcLockAtDpcLevel(Current, &ApcLock); + + /* Make sure we are frozen */ + OldCount = Current->FreezeCount; + if (OldCount) + { + /* Decrease the freeze count */ + Current->FreezeCount--; + + /* Check if both counts are zero now */ + if (!(Current->SuspendCount) && (!Current->FreezeCount)) + { + /* Lock the dispatcher */ + KiAcquireDispatcherLockAtDpcLevel(); + + /* Signal the suspend semaphore and wake it */ + Current->SuspendSemaphore.Header.SignalState++; + KiWaitTest(&Current->SuspendSemaphore, 1); + + /* Unlock the dispatcher */ + KiReleaseDispatcherLockFromDpcLevel(); + } + } + + /* Release the APC lock */ + KiReleaseApcLockFromDpcLevel(&ApcLock); + + /* Go to the next one */ + NextEntry = NextEntry->Flink; + } + + /* Release the process lock and exit the dispatcher */ + KiReleaseProcessLock(&LockHandle); + KiExitDispatcher(LockHandle.OldIrql); + + /* Leave the critical region */ + KeLeaveCriticalRegion(); +} + BOOLEAN NTAPI KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)