From 95fbecfd46586cf79d0d28da5eba77578a3ba200 Mon Sep 17 00:00:00 2001 From: David Welch Date: Fri, 9 Aug 2002 17:23:57 +0000 Subject: [PATCH] 2002-08-09 David Welch * 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 * ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy the LDR variable from the right address. 2002-08-09 David Welch * 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 * 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 * apps/tests/thread/thread.c (main): Test suspend and resume functionality. svn path=/trunk/; revision=3324 --- reactos/ChangeLog | 33 ++++++++++++++ reactos/apps/tests/thread/thread.c | 32 ++++++++++---- reactos/lib/kernel32/thread/thread.c | 50 +--------------------- reactos/lib/ntdll/ldr/startup.c | 12 ++++-- reactos/ntoskrnl/include/internal/ps.h | 4 +- reactos/ntoskrnl/ke/apc.c | 59 ++++++++++++++------------ reactos/ntoskrnl/ke/i386/usertrap.c | 2 +- reactos/ntoskrnl/ke/kthread.c | 4 +- reactos/ntoskrnl/ke/sem.c | 20 ++++----- reactos/ntoskrnl/ps/create.c | 16 ++++--- reactos/ntoskrnl/ps/psmgr.c | 3 +- reactos/ntoskrnl/ps/suspend.c | 56 ++++++++++++++++++------ 12 files changed, 165 insertions(+), 126 deletions(-) diff --git a/reactos/ChangeLog b/reactos/ChangeLog index baffcc020f5..2fab6fc71aa 100644 --- a/reactos/ChangeLog +++ b/reactos/ChangeLog @@ -1,3 +1,36 @@ +2002-08-09 David Welch + + * 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 + + * ntoskrnl/ke/i386/usertrap.c (print_user_address): Copy + the LDR variable from the right address. + +2002-08-09 David Welch + + * 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 + + * 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 + + * apps/tests/thread/thread.c (main): Test suspend and + resume functionality. + 2002-08-08 David Welch * ntoskrnl/mm/section (NtQuerySection): Return the diff --git a/reactos/apps/tests/thread/thread.c b/reactos/apps/tests/thread/thread.c index edb17e75f15..e7819516c82 100644 --- a/reactos/apps/tests/thread/thread.c +++ b/reactos/apps/tests/thread/thread.c @@ -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 id; ULONG nr; - + HANDLE ThreadHandle[NR_THREADS]; // The user must supply one argument (the seed). if he/she doesn't // then we show the help. @@ -60,16 +60,30 @@ int main (int argc, char* argv[]) printf("Creating %d threads...\n",NR_THREADS*2); for (i=0;iLoaderLock); - - 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, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index c0b50cbf2e1..bf77cb0a267 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -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 * PROJECT: ReactOS kernel @@ -62,11 +62,14 @@ LdrInitializeThunk (ULONG Unknown1, PDLLMAIN_FUNC Entrypoint; PLDR_MODULE current; - current_entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink; - while (current_entry != &NtCurrentPeb()->Ldr->InLoadOrderModuleList) + RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock); + current_entry = + NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Flink; + while (current_entry != + &NtCurrentPeb()->Ldr->InInitializationOrderModuleList) { current = CONTAINING_RECORD(current_entry, LDR_MODULE, - InLoadOrderModuleList); + InInitializationOrderModuleList); Entrypoint = (PDLLMAIN_FUNC)current->EntryPoint; if (Entrypoint != NULL && current->BaseAddress != NtCurrentPeb()->ImageBaseAddress) @@ -75,6 +78,7 @@ LdrInitializeThunk (ULONG Unknown1, } current_entry = current_entry->Flink; } + RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock); return; } diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 5cc5550b21c..5ee14e084a1 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * PURPOSE: Process manager definitions @@ -580,6 +580,8 @@ PiTimeoutThread(struct _KDPC *dpc, VOID STDCALL PsDispatchThread(ULONG NewThreadStatus); +VOID +PsInitialiseSuspendImplementation(VOID); #endif /* ASSEMBLER */ diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index 0db4dbb1a13..8a8a6336bc0 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -90,32 +90,35 @@ KiDeliverNormalApc(VOID) KeAcquireSpinLock(&PiApcLock, &oldlvl); while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) - { - current = Thread->Tcb.ApcState.ApcListHead[0].Blink; - Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); - if (Apc->NormalRoutine != NULL) - { - (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]); - Thread->Tcb.ApcState.KernelApcInProgress++; - Thread->Tcb.ApcState.KernelApcPending--; - - KeReleaseSpinLock(&PiApcLock, oldlvl); - - NormalRoutine = Apc->NormalRoutine; - NormalContext = Apc->NormalContext; - SystemArgument1 = Apc->SystemArgument1; - SystemArgument2 = Apc->SystemArgument2; - Apc->KernelRoutine(Apc, - &NormalRoutine, - &NormalContext, - &SystemArgument1, - &SystemArgument2); - NormalRoutine(NormalContext, SystemArgument1, SystemArgument2); - - KeAcquireSpinLock(&PiApcLock, &oldlvl); - Thread->Tcb.ApcState.KernelApcInProgress--; - } - } + { + current = Thread->Tcb.ApcState.ApcListHead[0].Blink; + Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); + if (Apc->NormalRoutine == NULL) + { + DbgPrint("Exiting kernel with kernel APCs pending.\n"); + KeBugCheck(0); + } + (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]); + Apc->Inserted = FALSE; + Thread->Tcb.ApcState.KernelApcInProgress++; + Thread->Tcb.ApcState.KernelApcPending--; + + KeReleaseSpinLock(&PiApcLock, oldlvl); + + NormalRoutine = Apc->NormalRoutine; + NormalContext = Apc->NormalContext; + SystemArgument1 = Apc->SystemArgument1; + SystemArgument2 = Apc->SystemArgument2; + Apc->KernelRoutine(Apc, + &NormalRoutine, + &NormalContext, + &SystemArgument1, + &SystemArgument2); + NormalRoutine(NormalContext, SystemArgument1, SystemArgument2); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + Thread->Tcb.ApcState.KernelApcInProgress--; + } KeReleaseSpinLock(&PiApcLock, oldlvl); } @@ -161,8 +164,9 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame) while (!IsListEmpty(&Thread->ApcState.ApcListHead[1])) { current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]); - KeReleaseSpinLock(&PiApcLock, oldlvl); Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry); + Apc->Inserted = FALSE; + KeReleaseSpinLock(&PiApcLock, oldlvl); /* * Save the thread's current context (in other words the registers @@ -259,6 +263,7 @@ KiDeliverApc(ULONG Unknown1, if (Apc->NormalRoutine == NULL) { current_entry = current_entry->Flink; + Apc->Inserted = FALSE; RemoveEntryList(&Apc->ApcListEntry); Thread->Tcb.ApcState.KernelApcInProgress++; Thread->Tcb.ApcState.KernelApcPending--; diff --git a/reactos/ntoskrnl/ke/i386/usertrap.c b/reactos/ntoskrnl/ke/i386/usertrap.c index d1fb32f4f5a..27e245f4cf6 100644 --- a/reactos/ntoskrnl/ke/i386/usertrap.c +++ b/reactos/ntoskrnl/ke/i386/usertrap.c @@ -92,7 +92,7 @@ print_user_address(PVOID address) return(TRUE); } - Status = MmSafeCopyFromUser(&Ldr, Peb->Ldr, sizeof(PPEB_LDR_DATA)); + Status = MmSafeCopyFromUser(&Ldr, &Peb->Ldr, sizeof(PPEB_LDR_DATA)); if (!NT_SUCCESS(Status)) { DbgPrint("<%x>", address); diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 45e737d7cd0..ab10ef47b73 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * PURPOSE: Microkernel thread support @@ -224,7 +224,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) PiSuspendThreadNormalRoutine, KernelMode, NULL); - KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255); + KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 128); Thread->ThreadListEntry.Flink = NULL; Thread->ThreadListEntry.Blink = NULL; Thread->FreezeCount = 0; diff --git a/reactos/ntoskrnl/ke/sem.c b/reactos/ntoskrnl/ke/sem.c index 99f7b94d6b7..8b1defa59e6 100644 --- a/reactos/ntoskrnl/ke/sem.c +++ b/reactos/ntoskrnl/ke/sem.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * FILE: ntoskrnl/ke/sem.c @@ -81,30 +81,28 @@ KeReleaseSemaphore (PKSEMAPHORE Semaphore, * object is Not-Signaled. */ { - ULONG initState = Semaphore->Header.SignalState; + ULONG InitialState; DPRINT("KeReleaseSemaphore(Semaphore %x, Increment %d, Adjustment %d, " "Wait %d)\n", Semaphore, Increment, Adjustment, Wait); KeAcquireDispatcherDatabaseLock(Wait); - if (Semaphore->Limit < initState+Adjustment - || initState > initState+Adjustment) + InitialState = Semaphore->Header.SignalState; + if (Semaphore->Limit < InitialState + Adjustment || + InitialState > InitialState + Adjustment) { ExRaiseStatus(STATUS_SEMAPHORE_LIMIT_EXCEEDED); } - Semaphore->Header.SignalState+=Adjustment; - DPRINT("initState %d\n", initState); - if(initState == 0) + Semaphore->Header.SignalState += Adjustment; + if (InitialState == 0) { - // wake up SignalState waiters - DPRINT("Waking waiters\n"); - KeDispatcherObjectWake(&Semaphore->Header); + KeDispatcherObjectWake(&Semaphore->Header); } KeReleaseDispatcherDatabaseLock(Wait); - return initState; + return(InitialState); } /* EOF */ diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c index 20136ddf25d..c2d21d20fa1 100644 --- a/reactos/ntoskrnl/ps/create.c +++ b/reactos/ntoskrnl/ps/create.c @@ -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 * PROJECT: ReactOS kernel @@ -590,15 +590,13 @@ NtCreateThread(PHANDLE ThreadHandle, { return(Status); } - - /* Attention: TebBase is in user memory space */ Thread->Tcb.Teb = TebBase; - Thread->StartAddress=NULL; + Thread->StartAddress = 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 * 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 @@ -680,7 +682,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle, return(Status); } - Thread->StartAddress=StartRoutine; + Thread->StartAddress = StartRoutine; Status = Ke386InitThread(&Thread->Tcb, StartRoutine, StartContext); @@ -689,7 +691,7 @@ PsCreateSystemThread(PHANDLE ThreadHandle, return(Status); } - if (ClientId!=NULL) + if (ClientId != NULL) { *ClientId=Thread->Cid; } diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 9189c774ff3..9832a2dc530 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -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 * PROJECT: ReactOS kernel @@ -32,6 +32,7 @@ VOID PiInitProcessManager(VOID) PsInitThreadManagment(); PsInitIdleThread(); PiInitApcManagement(); + PsInitialiseSuspendImplementation(); } diff --git a/reactos/ntoskrnl/ps/suspend.c b/reactos/ntoskrnl/ps/suspend.c index 86effe3518d..ae74467a663 100644 --- a/reactos/ntoskrnl/ps/suspend.c +++ b/reactos/ntoskrnl/ps/suspend.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 * FILE: ntoskrnl/ps/suspend.c @@ -39,6 +39,10 @@ * */ +/* GLOBALS *******************************************************************/ + +static FAST_MUTEX SuspendMutex; + /* FUNCTIONS *****************************************************************/ VOID STDCALL @@ -62,20 +66,36 @@ PiSuspendThreadNormalRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2) { - KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore, - 0, - UserMode, - TRUE, - NULL); + PETHREAD CurrentThread = PsGetCurrentThread(); + while (CurrentThread->Tcb.SuspendCount > 0) + { + KeWaitForSingleObject(&CurrentThread->Tcb.SuspendSemaphore, + 0, + UserMode, + TRUE, + NULL); + } } NTSTATUS PsResumeThread(PETHREAD Thread, PULONG SuspendCount) { - *SuspendCount = InterlockedDecrement((PULONG)&Thread->Tcb.SuspendCount); - KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE); - + ExAcquireFastMutex(&SuspendMutex); + 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); } @@ -85,19 +105,21 @@ PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount) { ULONG OldValue; - OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount); - if (OldValue == 0) + ExAcquireFastMutex(&SuspendMutex); + OldValue = Thread->Tcb.SuspendCount; + Thread->Tcb.SuspendCount++; + if (!Thread->Tcb.SuspendApc.Inserted) { KeInsertQueueApc(&Thread->Tcb.SuspendApc, NULL, NULL, 0); } - else + ExReleaseFastMutex(&SuspendMutex); + if (PreviousSuspendCount != NULL) { - InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState); + *PreviousSuspendCount = OldValue; } - return(STATUS_SUCCESS); } @@ -186,4 +208,10 @@ NtSuspendThread(IN HANDLE ThreadHandle, return(STATUS_SUCCESS); } +VOID +PsInitialiseSuspendImplementation(VOID) +{ + ExInitializeFastMutex(&SuspendMutex); +} + /* EOF */