2002-08-09 David Welch <welch@computer2.darkstar.org>

* ntoskrnl/ps/create.c (NtCreateThread): Call PsSuspendThread
	if NtCreateThread has CreateSuspended as TRUE.
	* ntoskrnl/ps/suspend.c (PsSuspendThread, PsResumeThread,
	PiSuspendThreadKernelRoutine): Fixed suspend functionality.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

	* ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy
	the LDR variable from the right address.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

	* ntoskrnl/ke/apc.c (KiDeliverNormalApc): Check for
	kernel APCs pending on exit from the kernel.
	* ntoskrnl/ke/apc.c (KiDeliverNormalApc, KiDeliverUserApc,
	KiDeliverApc): Set the APC's inserted flag to FALSE after
	removing it from the thread's queue.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

	* lib/kernel32/thread/thread.c (ThreadStartup): Don't
	call DLL entrypoints; this is done by LdrInitializeThunk.
	* lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call
	DLLs in initialization order; take the loader lock before
	calling.

2002-08-09  David Welch  <welch@computer2.darkstar.org>

	* apps/tests/thread/thread.c (main): Test suspend and
	resume functionality.

svn path=/trunk/; revision=3324
This commit is contained in:
David Welch 2002-08-09 17:23:57 +00:00
parent 5a801d58c3
commit 95fbecfd46
12 changed files with 165 additions and 126 deletions

View file

@ -1,3 +1,36 @@
2002-08-09 David Welch <welch@computer2.darkstar.org>
* ntoskrnl/ps/create.c (NtCreateThread): Call PsSuspendThread
if NtCreateThread has CreateSuspended as TRUE.
* ntoskrnl/ps/suspend.c (PsSuspendThread, PsResumeThread,
PiSuspendThreadKernelRoutine): Fixed suspend functionality.
2002-08-09 David Welch <welch@computer2.darkstar.org>
* ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy
the LDR variable from the right address.
2002-08-09 David Welch <welch@computer2.darkstar.org>
* ntoskrnl/ke/apc.c (KiDeliverNormalApc): Check for
kernel APCs pending on exit from the kernel.
* ntoskrnl/ke/apc.c (KiDeliverNormalApc, KiDeliverUserApc,
KiDeliverApc): Set the APC's inserted flag to FALSE after
removing it from the thread's queue.
2002-08-09 David Welch <welch@computer2.darkstar.org>
* lib/kernel32/thread/thread.c (ThreadStartup): Don't
call DLL entrypoints; this is done by LdrInitializeThunk.
* lib/ntdll/ldr/startup.c (LdrInitializeThunk): Call
DLLs in initialization order; take the loader lock before
calling.
2002-08-09 David Welch <welch@computer2.darkstar.org>
* apps/tests/thread/thread.c (main): Test suspend and
resume functionality.
2002-08-08 David Welch <welch@computer2.darkstar.org> 2002-08-08 David Welch <welch@computer2.darkstar.org>
* ntoskrnl/mm/section (NtQuerySection): Return the * ntoskrnl/mm/section (NtQuerySection): Return the

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.7 2001/02/06 00:11:17 dwelch Exp $ /* $Id: thread.c,v 1.8 2002/08/09 17:23:56 dwelch Exp $
* *
* *
* *
@ -44,7 +44,7 @@ int main (int argc, char* argv[])
DWORD i=0; DWORD i=0;
DWORD id; DWORD id;
ULONG nr; ULONG nr;
HANDLE ThreadHandle[NR_THREADS];
// The user must supply one argument (the seed). if he/she doesn't // The user must supply one argument (the seed). if he/she doesn't
// then we show the help. // then we show the help.
@ -60,16 +60,30 @@ int main (int argc, char* argv[])
printf("Creating %d threads...\n",NR_THREADS*2); printf("Creating %d threads...\n",NR_THREADS*2);
for (i=0;i<NR_THREADS;i++) for (i=0;i<NR_THREADS;i++)
{ {
CreateThread(NULL, ThreadHandle[i] = CreateThread(NULL,
0, 0,
thread_main1, thread_main1,
(LPVOID)i, (LPVOID)i,
0, CREATE_SUSPENDED,
&id); &id);
} }
for (i=0;i<NR_THREADS;i++)
{
ResumeThread(ThreadHandle[i]);
}
for (i=0;i<NR_THREADS;i++)
{
SuspendThread(ThreadHandle[i]);
}
for (i=0;i<NR_THREADS;i++)
{
ResumeThread(ThreadHandle[i]);
}
printf("All threads created...\n"); printf("All threads created...\n");
for(;;);
return 0; return 0;
} }

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.26 2001/08/15 20:35:39 ea Exp $ /* $Id: thread.c,v 1.27 2002/08/09 17:23:56 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -26,16 +26,6 @@
static VOID ThreadAttachDlls (VOID); static VOID ThreadAttachDlls (VOID);
/* Type for a DLL's entry point */
typedef
WINBOOL
STDCALL
(* PDLLMAIN_FUNC) (
HANDLE hInst,
ULONG ul_reason_for_call,
LPVOID lpReserved
);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
static VOID STDCALL static VOID STDCALL
@ -44,8 +34,6 @@ ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
{ {
UINT uExitCode; UINT uExitCode;
ThreadAttachDlls ();
/* FIXME: notify csrss of thread creation ?? */ /* FIXME: notify csrss of thread creation ?? */
uExitCode = (lpStartAddress)(lpParameter); uExitCode = (lpStartAddress)(lpParameter);
@ -53,42 +41,6 @@ ThreadStartup (LPTHREAD_START_ROUTINE lpStartAddress,
ExitThread(uExitCode); ExitThread(uExitCode);
} }
static VOID
ThreadAttachDlls (VOID)
{
PLIST_ENTRY ModuleListHead;
PLIST_ENTRY Entry;
PLDR_MODULE Module;
DPRINT("ThreadAttachDlls() called\n");
RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
Entry = ModuleListHead->Blink;
while (Entry != ModuleListHead)
{
Module = CONTAINING_RECORD(Entry, LDR_MODULE, InInitializationOrderModuleList);
if (Module->EntryPoint != 0)
{
PDLLMAIN_FUNC Entrypoint = (PDLLMAIN_FUNC)Module->EntryPoint;
DPRINT("Calling entry point at 0x%08x\n", Entrypoint);
Entrypoint (Module->BaseAddress,
DLL_THREAD_ATTACH,
NULL);
}
Entry = Entry->Blink;
}
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
DPRINT("ThreadAttachDlls() done\n");
}
HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, HANDLE STDCALL CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize, DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress, LPTHREAD_START_ROUTINE lpStartAddress,

View file

@ -1,4 +1,4 @@
/* $Id: startup.c,v 1.39 2002/08/08 17:54:13 dwelch Exp $ /* $Id: startup.c,v 1.40 2002/08/09 17:23:56 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -62,11 +62,14 @@ LdrInitializeThunk (ULONG Unknown1,
PDLLMAIN_FUNC Entrypoint; PDLLMAIN_FUNC Entrypoint;
PLDR_MODULE current; PLDR_MODULE current;
current_entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink; RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
while (current_entry != &NtCurrentPeb()->Ldr->InLoadOrderModuleList) current_entry =
NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink;
while (current_entry !=
&NtCurrentPeb()->Ldr->InInitializationOrderModuleList)
{ {
current = CONTAINING_RECORD(current_entry, LDR_MODULE, current = CONTAINING_RECORD(current_entry, LDR_MODULE,
InLoadOrderModuleList); InInitializationOrderModuleList);
Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint; Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint;
if (Entrypoint != NULL && if (Entrypoint != NULL &&
current->BaseAddress != NtCurrentPeb()->ImageBaseAddress) current->BaseAddress != NtCurrentPeb()->ImageBaseAddress)
@ -75,6 +78,7 @@ LdrInitializeThunk (ULONG Unknown1,
} }
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
} }
RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
return; return;
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: ps.h,v 1.37 2002/08/08 17:54:14 dwelch Exp $ /* $Id: ps.h,v 1.38 2002/08/09 17:23:56 dwelch Exp $
* *
* FILE: ntoskrnl/ke/kthread.c * FILE: ntoskrnl/ke/kthread.c
* PURPOSE: Process manager definitions * PURPOSE: Process manager definitions
@ -580,6 +580,8 @@ PiTimeoutThread(struct _KDPC *dpc,
VOID STDCALL VOID STDCALL
PsDispatchThread(ULONG NewThreadStatus); PsDispatchThread(ULONG NewThreadStatus);
VOID
PsInitialiseSuspendImplementation(VOID);
#endif /* ASSEMBLER */ #endif /* ASSEMBLER */

View file

@ -90,32 +90,35 @@ KiDeliverNormalApc(VOID)
KeAcquireSpinLock(&PiApcLock, &oldlvl); KeAcquireSpinLock(&PiApcLock, &oldlvl);
while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
{ {
current = Thread->Tcb.ApcState.ApcListHead[0].Blink; current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
if (Apc->NormalRoutine != NULL) if (Apc->NormalRoutine == NULL)
{ {
(VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]); DbgPrint("Exiting kernel with kernel APCs pending.\n");
Thread->Tcb.ApcState.KernelApcInProgress++; KeBugCheck(0);
Thread->Tcb.ApcState.KernelApcPending--; }
(VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
KeReleaseSpinLock(&PiApcLock, oldlvl); Apc->Inserted = FALSE;
Thread->Tcb.ApcState.KernelApcInProgress++;
NormalRoutine = Apc->NormalRoutine; Thread->Tcb.ApcState.KernelApcPending--;
NormalContext = Apc->NormalContext;
SystemArgument1 = Apc->SystemArgument1; KeReleaseSpinLock(&PiApcLock, oldlvl);
SystemArgument2 = Apc->SystemArgument2;
Apc->KernelRoutine(Apc, NormalRoutine = Apc->NormalRoutine;
&NormalRoutine, NormalContext = Apc->NormalContext;
&NormalContext, SystemArgument1 = Apc->SystemArgument1;
&SystemArgument1, SystemArgument2 = Apc->SystemArgument2;
&SystemArgument2); Apc->KernelRoutine(Apc,
NormalRoutine(NormalContext, SystemArgument1, SystemArgument2); &NormalRoutine,
&NormalContext,
KeAcquireSpinLock(&PiApcLock, &oldlvl); &SystemArgument1,
Thread->Tcb.ApcState.KernelApcInProgress--; &SystemArgument2);
} NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
}
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Thread->Tcb.ApcState.KernelApcInProgress--;
}
KeReleaseSpinLock(&PiApcLock, oldlvl); KeReleaseSpinLock(&PiApcLock, oldlvl);
} }
@ -161,8 +164,9 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
while (!IsListEmpty(&Thread->ApcState.ApcListHead[1])) while (!IsListEmpty(&Thread->ApcState.ApcListHead[1]))
{ {
current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]); current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]);
KeReleaseSpinLock(&PiApcLock, oldlvl);
Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry); Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
Apc->Inserted = FALSE;
KeReleaseSpinLock(&PiApcLock, oldlvl);
/* /*
* Save the thread's current context (in other words the registers * Save the thread's current context (in other words the registers
@ -259,6 +263,7 @@ KiDeliverApc(ULONG Unknown1,
if (Apc->NormalRoutine == NULL) if (Apc->NormalRoutine == NULL)
{ {
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
Apc->Inserted = FALSE;
RemoveEntryList(&Apc->ApcListEntry); RemoveEntryList(&Apc->ApcListEntry);
Thread->Tcb.ApcState.KernelApcInProgress++; Thread->Tcb.ApcState.KernelApcInProgress++;
Thread->Tcb.ApcState.KernelApcPending--; Thread->Tcb.ApcState.KernelApcPending--;

View file

@ -92,7 +92,7 @@ print_user_address(PVOID address)
return(TRUE); return(TRUE);
} }
Status = MmSafeCopyFromUser(&Ldr, Peb->Ldr, sizeof(PPEB_LDR_DATA)); Status = MmSafeCopyFromUser(&Ldr, &Peb->Ldr, sizeof(PPEB_LDR_DATA));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DbgPrint("<%x>", address); DbgPrint("<%x>", address);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: kthread.c,v 1.30 2002/08/08 17:54:14 dwelch Exp $ /* $Id: kthread.c,v 1.31 2002/08/09 17:23:57 dwelch Exp $
* *
* FILE: ntoskrnl/ke/kthread.c * FILE: ntoskrnl/ke/kthread.c
* PURPOSE: Microkernel thread support * PURPOSE: Microkernel thread support
@ -224,7 +224,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
PiSuspendThreadNormalRoutine, PiSuspendThreadNormalRoutine,
KernelMode, KernelMode,
NULL); NULL);
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255); KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128);
Thread->ThreadListEntry.Flink = NULL; Thread->ThreadListEntry.Flink = NULL;
Thread->ThreadListEntry.Blink = NULL; Thread->ThreadListEntry.Blink = NULL;
Thread->FreezeCount = 0; Thread->FreezeCount = 0;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: sem.c,v 1.8 2001/03/16 23:04:59 dwelch Exp $ /* $Id: sem.c,v 1.9 2002/08/09 17:23:57 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/sem.c * FILE: ntoskrnl/ke/sem.c
@ -81,30 +81,28 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore,
* object is Not-Signaled. * object is Not-Signaled.
*/ */
{ {
ULONG initState = Semaphore->Header.SignalState; ULONG InitialState;
DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, " DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, "
"Wait %d)\n", Semaphore, Increment, Adjustment, Wait); "Wait %d)\n", Semaphore, Increment, Adjustment, Wait);
KeAcquireDispatcherDatabaseLock(Wait); KeAcquireDispatcherDatabaseLock(Wait);
if (Semaphore->Limit < initState+Adjustment InitialState = Semaphore->Header.SignalState;
|| initState > initState+Adjustment) if (Semaphore->Limit < InitialState + Adjustment ||
InitialState > InitialState + Adjustment)
{ {
ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED);
} }
Semaphore->Header.SignalState+=Adjustment; Semaphore->Header.SignalState += Adjustment;
DPRINT("initState %d\n", initState); if (InitialState == 0)
if(initState == 0)
{ {
// wake up SignalState waiters KeDispatcherObjectWake(&Semaphore->Header);
DPRINT("Waking waiters\n");
KeDispatcherObjectWake(&Semaphore->Header);
} }
KeReleaseDispatcherDatabaseLock(Wait); KeReleaseDispatcherDatabaseLock(Wait);
return initState; return(InitialState);
} }
/* EOF */ /* EOF */

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.48 2002/08/08 17:54:16 dwelch Exp $ /* $Id: create.c,v 1.49 2002/08/09 17:23:57 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -590,15 +590,13 @@ NtCreateThread(PHANDLE ThreadHandle,
{ {
return(Status); return(Status);
} }
/* Attention: TebBase is in user memory space */
Thread->Tcb.Teb = TebBase; Thread->Tcb.Teb = TebBase;
Thread->StartAddress=NULL; Thread->StartAddress = NULL;
if (Client != NULL) if (Client != NULL)
{ {
*Client=Thread->Cid; *Client = Thread->Cid;
} }
/* /*
@ -615,6 +613,10 @@ NtCreateThread(PHANDLE ThreadHandle,
* If the thread is to be created suspended then queue an APC to * If the thread is to be created suspended then queue an APC to
* do the suspend before we run any userspace code. * do the suspend before we run any userspace code.
*/ */
if (CreateSuspended)
{
PsSuspendThread(Thread, NULL);
}
/* /*
* Queue an APC to the thread that will execute the ntdll startup * Queue an APC to the thread that will execute the ntdll startup
@ -680,7 +682,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
return(Status); return(Status);
} }
Thread->StartAddress=StartRoutine; Thread->StartAddress = StartRoutine;
Status = Ke386InitThread(&Thread->Tcb, Status = Ke386InitThread(&Thread->Tcb,
StartRoutine, StartRoutine,
StartContext); StartContext);
@ -689,7 +691,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
return(Status); return(Status);
} }
if (ClientId!=NULL) if (ClientId != NULL)
{ {
*ClientId=Thread->Cid; *ClientId=Thread->Cid;
} }

View file

@ -1,4 +1,4 @@
/* $Id: psmgr.c,v 1.11 2001/07/12 17:21:06 ekohl Exp $ /* $Id: psmgr.c,v 1.12 2002/08/09 17:23:57 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -32,6 +32,7 @@ VOID PiInitProcessManager(VOID)
PsInitThreadManagment(); PsInitThreadManagment();
PsInitIdleThread(); PsInitIdleThread();
PiInitApcManagement(); PiInitApcManagement();
PsInitialiseSuspendImplementation();
} }

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: suspend.c,v 1.7 2002/07/10 15:17:35 ekohl Exp $ /* $Id: suspend.c,v 1.8 2002/08/09 17:23:57 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/suspend.c * FILE: ntoskrnl/ps/suspend.c
@ -39,6 +39,10 @@
* *
*/ */
/* GLOBALS *******************************************************************/
static FAST_MUTEX SuspendMutex;
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID STDCALL VOID STDCALL
@ -62,20 +66,36 @@ PiSuspendThreadNormalRoutine(PVOID NormalContext,
PVOID SystemArgument1, PVOID SystemArgument1,
PVOID SystemArgument2) PVOID SystemArgument2)
{ {
KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore, PETHREAD CurrentThread = PsGetCurrentThread();
0, while (CurrentThread->Tcb.SuspendCount > 0)
UserMode, {
TRUE, KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore,
NULL); 0,
UserMode,
TRUE,
NULL);
}
} }
NTSTATUS NTSTATUS
PsResumeThread(PETHREAD Thread, PULONG SuspendCount) PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
{ {
*SuspendCount = InterlockedDecrement((PULONG)&Thread->Tcb.SuspendCount); ExAcquireFastMutex(&SuspendMutex);
KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE); if (SuspendCount != NULL)
{
*SuspendCount = Thread->Tcb.SuspendCount;
}
if (Thread->Tcb.SuspendCount > 0)
{
Thread->Tcb.SuspendCount--;
if (Thread->Tcb.SuspendCount == 0)
{
KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT,
1, FALSE);
}
}
ExReleaseFastMutex(&SuspendMutex);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -85,19 +105,21 @@ PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
{ {
ULONG OldValue; ULONG OldValue;
OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount); ExAcquireFastMutex(&SuspendMutex);
if (OldValue == 0) OldValue = Thread->Tcb.SuspendCount;
Thread->Tcb.SuspendCount++;
if (!Thread->Tcb.SuspendApc.Inserted)
{ {
KeInsertQueueApc(&Thread->Tcb.SuspendApc, KeInsertQueueApc(&Thread->Tcb.SuspendApc,
NULL, NULL,
NULL, NULL,
0); 0);
} }
else ExReleaseFastMutex(&SuspendMutex);
if (PreviousSuspendCount != NULL)
{ {
InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState); *PreviousSuspendCount = OldValue;
} }
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -186,4 +208,10 @@ NtSuspendThread(IN HANDLE ThreadHandle,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
VOID
PsInitialiseSuspendImplementation(VOID)
{
ExInitializeFastMutex(&SuspendMutex);
}
/* EOF */ /* EOF */