From ac7a3aa54272bb9cd2224b8cd39a6fa2f2608e3e Mon Sep 17 00:00:00 2001 From: David Welch Date: Mon, 13 Dec 1999 22:04:41 +0000 Subject: [PATCH] Reworked APC and waiting code, seems more stable now KeWaitForMultipleObjects is broken, shouldn't be difficult to fix Corrected bug in ntdll ldr which prevented VC applications being loaded Added thread testing application Tried to make thread termination reentrant Improved stack frame dump svn path=/trunk/; revision=868 --- reactos/Makefile | 2 +- reactos/apps/tests/thread/makefile | 41 ++ reactos/apps/tests/thread/thread.c | 45 +++ reactos/include/ddk/pstypes.h | 2 +- reactos/include/internal/ke.h | 4 +- reactos/include/internal/ps.h | 19 +- reactos/install.sh | 1 + reactos/lib/crtdll/makefile | 4 +- reactos/lib/kernel32/process/proc.c | 45 +-- reactos/lib/kernel32/thread/thread.c | 2 +- reactos/lib/ntdll/ldr/utils.c | 8 +- reactos/ntoskrnl/hal/x86/irql.c | 55 +-- reactos/ntoskrnl/hal/x86/spinlock.c | 6 +- reactos/ntoskrnl/io/irp.c | 12 +- reactos/ntoskrnl/ke/apc.c | 139 +++---- reactos/ntoskrnl/ke/bug.c | 19 +- reactos/ntoskrnl/ke/i386/exp.c | 12 +- reactos/ntoskrnl/ke/main.c | 80 +--- reactos/ntoskrnl/ke/timer.c | 18 +- reactos/ntoskrnl/ke/wait.c | 129 ++++--- reactos/ntoskrnl/ldr/loader.c | 4 +- reactos/ntoskrnl/makefile_rex | 8 +- reactos/ntoskrnl/mm/i386/memsafe.s | 2 +- reactos/ntoskrnl/mm/pagefile.c | 2 +- reactos/ntoskrnl/mm/virtual.c | 2 +- reactos/ntoskrnl/nt/port.c | 4 +- reactos/ntoskrnl/ps/create.c | 392 +++++++++++++++++++ reactos/ntoskrnl/ps/kill.c | 13 +- reactos/ntoskrnl/ps/thread.c | 548 +++++---------------------- 29 files changed, 858 insertions(+), 760 deletions(-) create mode 100644 reactos/apps/tests/thread/makefile create mode 100644 reactos/apps/tests/thread/thread.c create mode 100644 reactos/ntoskrnl/ps/create.c diff --git a/reactos/Makefile b/reactos/Makefile index 398e18c024d..d2b0a37d4b3 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -41,7 +41,7 @@ FS_DRIVERS = vfat # FS_DRIVERS = minix ext2 template KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) -APPS = args hello shell test cat bench apc shm lpc +APPS = args hello shell test cat bench apc shm lpc thread # APPS = cmd all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS) diff --git a/reactos/apps/tests/thread/makefile b/reactos/apps/tests/thread/makefile new file mode 100644 index 00000000000..d2d18d38f54 --- /dev/null +++ b/reactos/apps/tests/thread/makefile @@ -0,0 +1,41 @@ +# +# +# +PROGS = thread + +all: $(PROGS:%=%.exe) + +.phony: all + +clean: $(PROGS:%=%_clean) + +$(PROGS:%=%_clean): %_clean: + - $(RM) $*.o + - $(RM) $*.exe + - $(RM) $*.sym + +.phony: clean + +floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe +ifeq ($(DOSCLI),yes) + $(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe +else + $(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe +endif + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe) + +$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe +ifeq ($(DOSCLI),yes) + $(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe +else + $(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe +endif + +thread.exe: thread.c + $(CC) $(CFLAGS) thread.c -lkernel32 -o thread.exe + $(NM) --numeric-sort thread.exe > thread.sym + +include ../../rules.mak diff --git a/reactos/apps/tests/thread/thread.c b/reactos/apps/tests/thread/thread.c new file mode 100644 index 00000000000..2b03be5a85f --- /dev/null +++ b/reactos/apps/tests/thread/thread.c @@ -0,0 +1,45 @@ +#include +#include + +#define NR_THREADS (10) + +ULONG nr; + +DWORD WINAPI thread_main1(LPVOID param) +{ + ULONG s; + + printf("Thread %d running\n", (DWORD)param); + s = nr = ((nr * 1103515245) + 12345) & 0x7fffffff; + s = s % 10; + printf("s %d\n", s); + Sleep(s); + return 0; +} + +int main (int argc, char* argv[]) +{ + HANDLE hThread; + DWORD i=0; + DWORD id; + ULONG nr; + + nr = atoi(argv[1]); + printf("Seed %d\n", nr); + + printf("Creating %d threads...\n",NR_THREADS*2); + for (i=0;i #include -//#define NDEBUG +#define NDEBUG #include diff --git a/reactos/lib/ntdll/ldr/utils.c b/reactos/lib/ntdll/ldr/utils.c index 27d64e92299..0d2d9e5547d 100644 --- a/reactos/lib/ntdll/ldr/utils.c +++ b/reactos/lib/ntdll/ldr/utils.c @@ -1,4 +1,4 @@ -/* $Id: utils.c,v 1.19 1999/12/11 21:14:47 dwelch Exp $ +/* $Id: utils.c,v 1.20 1999/12/13 22:04:34 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -698,7 +698,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders, PDLL Module; NTSTATUS Status; - DPRINT1("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders, + DPRINT("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders, ImageBase); /* @@ -708,7 +708,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders, ImageBase + NTHeaders->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] .VirtualAddress); - DPRINT1("ImportModuleDirectory %x\n", ImportModuleDirectory); + DPRINT("ImportModuleDirectory %x\n", ImportModuleDirectory); while (ImportModuleDirectory->dwRVAModuleName) { @@ -717,7 +717,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders, DWORD pName; PWORD pHint; - DPRINT1("ImportModule->Directory->dwRVAModuleName %s\n", + DPRINT("ImportModule->Directory->dwRVAModuleName %s\n", (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName)); Status = LdrLoadDll(&Module, diff --git a/reactos/ntoskrnl/hal/x86/irql.c b/reactos/ntoskrnl/hal/x86/irql.c index bce36232a18..7b3f9102b38 100644 --- a/reactos/ntoskrnl/hal/x86/irql.c +++ b/reactos/ntoskrnl/hal/x86/irql.c @@ -47,8 +47,6 @@ static unsigned int HiSetCurrentPICMask(unsigned int mask) return mask; } -extern VOID KeApcProlog2(); - static VOID HiSwitchIrql(KIRQL oldIrql) /* * FUNCTION: Switches to the current irql @@ -85,28 +83,37 @@ static VOID HiSwitchIrql(KIRQL oldIrql) __asm__("sti\n\t"); return; } - HiSetCurrentPICMask(0); - if(CurrentIrql == APC_LEVEL) - { - if (DpcQueueSize > 0 ) - { - KeSetCurrentIrql(DISPATCH_LEVEL); - __asm__("sti\n\t"); - KeDrainDpcQueue(); - __asm__("cli\n\t"); - KeSetCurrentIrql(PASSIVE_LEVEL); - } - __asm__("sti\n\t"); - return; - } - if( CurrentIrql == PASSIVE_LEVEL && CurrentThread && CurrentThread->ApcState.KernelApcPending ) - { - KeSetCurrentIrql( APC_LEVEL ); - KeApcProlog2(); - KeSetCurrentIrql( PASSIVE_LEVEL ); - } - - __asm__("sti\n\t"); + + HiSetCurrentPICMask(0); + if (CurrentIrql == APC_LEVEL) + { + if (DpcQueueSize > 0 ) + { + KeSetCurrentIrql(DISPATCH_LEVEL); + __asm__("sti\n\t"); + KeDrainDpcQueue(); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + } + __asm__("sti\n\t"); + return; + } + + if (CurrentIrql == PASSIVE_LEVEL && + CurrentThread != NULL && + CurrentThread->ApcState.KernelApcPending) + { + KeSetCurrentIrql(APC_LEVEL); + __asm__("sti\n\t"); + KeCallApcsThread(); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + __asm__("sti\n\t"); + } + else + { + __asm__("sti\n\t"); + } } VOID KeSetCurrentIrql(KIRQL newlvl) diff --git a/reactos/ntoskrnl/hal/x86/spinlock.c b/reactos/ntoskrnl/hal/x86/spinlock.c index 72ab20671d2..995a187ac72 100644 --- a/reactos/ntoskrnl/hal/x86/spinlock.c +++ b/reactos/ntoskrnl/hal/x86/spinlock.c @@ -67,13 +67,9 @@ VOID KeAcquireSpinLockAtDpcLevel(PKSPIN_LOCK SpinLock) * SpinLock = Spinlock to acquire */ { - if (SpinLock->Lock == 1) - { - DbgPrint("May be acquiring locked spinlock\n"); - } while (InterlockedExchange(&SpinLock->Lock, 1) == 1) { - DbgPrint("Spinning on spinlock\n"); + DbgPrint("Spinning on spinlock %x\n", SpinLock); KeBugCheck(0); } } diff --git a/reactos/ntoskrnl/io/irp.c b/reactos/ntoskrnl/io/irp.c index f58e67239ce..87c088751fe 100644 --- a/reactos/ntoskrnl/io/irp.c +++ b/reactos/ntoskrnl/io/irp.c @@ -253,7 +253,7 @@ VOID IopCompleteRequest(struct _KAPC* Apc, "(*SystemArgument1) %x\n", Apc, SystemArgument1, *SystemArgument1); IoSecondStageCompletion((PIRP)(*SystemArgument1), - SystemArgument2); + (KPRIORITY)(*SystemArgument2)); } VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) @@ -270,8 +270,8 @@ VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) NTSTATUS Status; PKTHREAD Thread; - DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d)\n", - Irp,PriorityBoost); + DPRINT("IoCompleteRequest(Irp %x, PriorityBoost %d) Event %x THread %x\n", + Irp,PriorityBoost, Irp->UserEvent, PsGetCurrentThread()); for (i=0;iStackCount;i++) { @@ -307,14 +307,16 @@ VOID IoCompleteRequest(PIRP Irp, CCHAR PriorityBoost) (PVOID) Irp->Overlay.AsynchronousParameters.UserApcContext); KeInsertQueueApc(&Irp->Tail.Apc, - Irp, - PriorityBoost, + (PVOID)Irp, + (PVOID)(ULONG)PriorityBoost, KernelMode); + DPRINT("Finished dispatching APC\n"); } else { DPRINT("Calling completion routine directly\n"); IoSecondStageCompletion(Irp,PriorityBoost); + DPRINT("Finished completition routine\n"); } } diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index 61a1902bc42..ad41ffd106f 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -16,19 +16,32 @@ #include #include #include +#include #define NDEBUG #include -extern VOID KeApcProlog(VOID); +/* GLOBALS *******************************************************************/ + static KSPIN_LOCK PiApcLock; -/* PROTOTYPES ****************************************************************/ - -VOID KeApcProlog3(PKAPC Apc); - /* FUNCTIONS *****************************************************************/ +VOID KeCallKernelRoutineApc(PKAPC Apc) +/* + * FUNCTION: Call the kernel routine for an APC + */ +{ + DPRINT("KeCallKernelRoutineApc(Apc %x)\n",Apc); + + Apc->KernelRoutine(Apc, + &Apc->NormalRoutine, + &Apc->NormalContext, + &Apc->SystemArgument1, + &Apc->SystemArgument2); + DPRINT("Finished KeCallKernelRoutineApc()\n"); +} + BOOLEAN KiTestAlert(PKTHREAD Thread, PCONTEXT UserContext) /* @@ -77,81 +90,41 @@ BOOLEAN KiTestAlert(PKTHREAD Thread, * Now call for the kernel routine for the APC, which will free * the APC data structure */ - KeApcProlog3(Apc); + KeCallKernelRoutineApc(Apc); } UserContext->Esp = (ULONG)Esp; InitializeListHead(&Thread->ApcState.ApcListHead[1]); return(TRUE); } -VOID KeApcProlog2() +VOID KeCallApcsThread(VOID) { PETHREAD Thread = PsGetCurrentThread(); PLIST_ENTRY current; PKAPC Apc; KIRQL oldlvl; - DPRINT( "KeApcProlog2()\n" ); - KeLowerIrql( APC_LEVEL ); - KeAcquireSpinLock( &PiApcLock, &oldlvl ); - while( !IsListEmpty( &(Thread->Tcb.ApcState.ApcListHead[0]) ) ) + DPRINT("KeCallApcsThread()\n"); + KeAcquireSpinLock(&PiApcLock, &oldlvl); + while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) { - DPRINT( "Delivering APC\n" ); - current = RemoveTailList( &(Thread->Tcb.ApcState.ApcListHead[0]) ); - KeReleaseSpinLock( &PiApcLock, oldlvl ); - Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); - KeApcProlog3(Apc); - KeAcquireSpinLock( &PiApcLock, &oldlvl ); + DPRINT("Delivering APC\n"); + current = RemoveTailList(&(Thread->Tcb.ApcState.ApcListHead[0])); + Thread->Tcb.ApcState.KernelApcInProgress++; + Thread->Tcb.ApcState.KernelApcPending--; + KeReleaseSpinLock(&PiApcLock, oldlvl); + + Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); + KeCallKernelRoutineApc(Apc); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + DPRINT("Called kernel routine for APC\n"); +// PsFreezeThread(Thread, NULL, FALSE, KernelMode); + DPRINT("Done frozen thread\n"); + Thread->Tcb.ApcState.KernelApcInProgress--; } - KeReleaseSpinLock( &PiApcLock, oldlvl ); - Thread->Tcb.WaitStatus = STATUS_ALERTED; - KeLowerIrql( PASSIVE_LEVEL ); -} - -VOID KeApcProlog3(PKAPC Apc) -/* - * FUNCTION: This is called from the prolog proper (in assembly) to deliver - * a kernel APC - */ -{ - PKTHREAD Thread = KeGetCurrentThread(); - DPRINT("KeApcProlog3(Apc %x)\n",Apc); - InterlockedIncrement( &(Thread->ApcState.KernelApcInProgress) ); - InterlockedDecrement( &(Thread->ApcState.KernelApcPending) ); - - Apc->KernelRoutine(Apc, - &Apc->NormalRoutine, - &Apc->NormalContext, - &Apc->SystemArgument1, - &Apc->SystemArgument2); - InterlockedDecrement( &(Thread->ApcState.KernelApcInProgress) ); -} - -VOID KeDeliverKernelApc( PKTHREAD TargetThread ) -/* - * FUNCTION: Simulates an interrupt on the target thread which will transfer - * control to a kernel mode routine - * Must be called while holding the PiApcLock - */ -{ - PULONG Stack; - - DPRINT( "KeDeliverKernelApc( TargetThread %x)\n", TargetThread ); - if (TargetThread == KeGetCurrentThread()) - { - KeApcProlog2(); - return; - } - - TargetThread->Context.esp = TargetThread->Context.esp - 12; - Stack = (PULONG)TargetThread->Context.esp; - Stack[0] = TargetThread->Context.eip; - Stack[1] = TargetThread->Context.cs; - Stack[2] = TargetThread->Context.eflags; - TargetThread->Context.eip = (ULONG)KeApcProlog; - - PsResumeThread(CONTAINING_RECORD(TargetThread,ETHREAD,Tcb), - NULL); + KeReleaseSpinLock(&PiApcLock, oldlvl); +// Thread->Tcb.WaitStatus = STATUS_KERNEL_APC; } VOID KeInsertQueueApc(PKAPC Apc, @@ -173,7 +146,7 @@ VOID KeInsertQueueApc(PKAPC Apc, "SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1, SystemArgument2,Mode); - KeAcquireSpinLock( &PiApcLock, &oldlvl ); + KeAcquireSpinLock(&PiApcLock, &oldlvl); Apc->SystemArgument1 = SystemArgument1; Apc->SystemArgument2 = SystemArgument2; @@ -200,25 +173,12 @@ VOID KeInsertQueueApc(PKAPC Apc, } Apc->Inserted = TRUE; - DPRINT("TargetThread->KernelApcDisable %d\n", - TargetThread->KernelApcDisable); - DPRINT("Apc->KernelRoutine %x\n", Apc->KernelRoutine); - DPRINT( "TargetThread->Altertable = %x, TargetThread->WaitIrql = %d\n", TargetThread->Alertable, TargetThread->WaitIrql ); - if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 ) - if( TargetThread != PsGetCurrentThread() ) - { - PsSuspendThread( CONTAINING_RECORD( TargetThread, ETHREAD, Tcb ), NULL, TRUE, KernelMode ); - KeReleaseSpinLock( &PiApcLock, oldlvl ); - if( TargetThread->WaitIrql < APC_LEVEL ) - KeDeliverKernelApc( TargetThread ); - } - else { - if( TargetThread->WaitIrql < APC_LEVEL ) - KeDeliverKernelApc( TargetThread ); - } - else + if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 && + TargetThread->WaitIrql < APC_LEVEL) { - DPRINT("Queuing APC for later delivery\n"); + KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), + STATUS_KERNEL_APC); + KeReleaseSpinLock(&PiApcLock, oldlvl); } if (Apc->ApcMode == UserMode && TargetThread->Alertable == TRUE && TargetThread->WaitMode == UserMode) @@ -228,8 +188,9 @@ VOID KeInsertQueueApc(PKAPC Apc, DPRINT("Resuming thread for user APC\n"); Status = STATUS_USER_APC; - PsResumeThread((PETHREAD)TargetThread, - &Status); + KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), + STATUS_USER_APC); + KeReleaseSpinLock(&PiApcLock, oldlvl); } } @@ -332,8 +293,8 @@ NTSTATUS STDCALL NtTestAlert(VOID) return(STATUS_SUCCESS); } -VOID PiInitApcManagement() +VOID PiInitApcManagement(VOID) { - KeInitializeSpinLock( &PiApcLock ); + KeInitializeSpinLock(&PiApcLock); } diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index 8c89f9734f7..754debdeba7 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -19,6 +19,7 @@ /* GLOBALS ******************************************************************/ static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL}; +static ULONG InBugCheck; VOID PsDumpThreads(VOID); @@ -32,6 +33,7 @@ BOOLEAN KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord) VOID KeInitializeBugCheck(VOID) { InitializeListHead(&BugcheckCallbackListHead); + InBugCheck = 0; } VOID KeInitializeCallbackRecord(PKBUGCHECK_CALLBACK_RECORD CallbackRecord) @@ -72,7 +74,7 @@ VOID KeBugCheckEx(ULONG BugCheckCode, BugCheckParameter1,BugCheckParameter2,BugCheckParameter3, BugCheckParameter4); PsDumpThreads(); - KeDumpStackFrames(0,64); + KeDumpStackFrames(&((&BugCheckCode)[-1]),64); for(;;) __asm__("hlt\n\t"); //PJS: use HLT instruction, rather than busy wait @@ -87,6 +89,19 @@ VOID KeBugCheck(ULONG BugCheckCode) * RETURNS: Doesn't */ { - KeBugCheckEx(BugCheckCode,0,0,0,0); + __asm__("cli\n\t"); + DbgPrint("Bug detected (code %x)\n", BugCheckCode); + if (InBugCheck == 1) + { + DbgPrint("Recursive bug check halting now\n"); + for(;;); + } + InBugCheck = 1; + PsDumpThreads(); + KeDumpStackFrames(&((&BugCheckCode)[-1]), 80); + for(;;) + { + __asm__("hlt\n\t"); + } } diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 688471a9d16..2394ad27768 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -242,7 +242,7 @@ asmlinkage void exception_handler(unsigned int edi, } DbgPrint("CS:EIP %x:%x\n",cs&0xffff,eip); DbgPrint("CS:EIP %x:", cs&0xffff); - print_address(eip); + print_address((PVOID)eip); DbgPrint("\n"); __asm__("movl %%cr2,%0\n\t" : "=d" (cr2)); @@ -302,7 +302,7 @@ asmlinkage void exception_handler(unsigned int edi, stack[i] <= ((ULONG)&init_stack_top))) { // DbgPrint(" %.8x", stack[i]); - print_address(stack[i]); + print_address((PVOID)stack[i]); DbgPrint(" "); } } @@ -328,6 +328,7 @@ asmlinkage void exception_handler(unsigned int edi, DbgPrint("\n"); DbgPrint("Killing current task\n"); +// for(;;); KeLowerIrql(PASSIVE_LEVEL); if ((cs&0xffff) == USER_CS) { @@ -338,12 +339,13 @@ asmlinkage void exception_handler(unsigned int edi, for(;;); } -VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames) +VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames) { - PULONG Stack = &((&DummyArg)[-1]); + PULONG Stack = (PULONG)_Stack; ULONG i; Stack = (PVOID)(((ULONG)Stack) & (~0x3)); + DbgPrint("Stack: %x\n", Stack); DbgPrint("Frames:\n"); for (i=0; i KERNEL_BASE) { // DbgPrint("%.8x ",Stack[i]); - print_address(Stack[i]); + print_address((PVOID)Stack[i]); DbgPrint(" "); } if (Stack[i] == 0xceafbeef) diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 2426de7c320..e730e4a4736 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.31 1999/11/24 11:51:50 dwelch Exp $ +/* $Id: main.c,v 1.32 1999/12/13 22:04:36 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -26,7 +26,7 @@ #include #include -#define NDEBUG +//#define NDEBUG #include /* FUNCTIONS ****************************************************************/ @@ -128,70 +128,6 @@ unsigned int old_idt[256][2]; //extern unsigned int idt[]; unsigned int old_idt_valid = 1; -ERESOURCE TestResource; - -NTSTATUS thread_main(PVOID param) -{ - ULONG Id; - - Id = (ULONG)param; - - DbgPrint("THREAD(%d) Resource %x\n",Id,&TestResource); - - DbgPrint("THREAD(%d) Acquiring resource for shared access\n", Id); - - ExAcquireResourceExclusiveLite(&TestResource, TRUE); - - DbgPrint("THREAD(%d) Acquired resource for shared access\n", Id); - - return(STATUS_SUCCESS); -} - -VOID resource_test(VOID) -{ - HANDLE thread1_handle; - CLIENT_ID thread1_cid; - HANDLE thread2_handle; - CLIENT_ID thread2_cid; - ULONG i; - - ExInitializeResourceLite(&TestResource); - - DbgPrint("Resource %x\n", &TestResource); - - ExAcquireResourceExclusiveLite(&TestResource, TRUE); - - DbgPrint("Acquired resource for exclusive access\n"); - - PsCreateSystemThread(&thread1_handle, - THREAD_ALL_ACCESS, - NULL, - NULL, - &thread1_cid, - thread_main, - (PVOID)1); - PsCreateSystemThread(&thread2_handle, - THREAD_ALL_ACCESS, - NULL, - NULL, - &thread2_cid, - thread_main, - (PVOID)2); - - DbgPrint("KeGetCurrentIrql() %d\n", KeGetCurrentIrql()); - - for (i=0; i<10000000; i++) - { - __asm__("nop\n\t"); - } - - ExReleaseResourceLite(&TestResource); - - DbgPrint("Released resource\n"); - - for(;;); -} - asmlinkage void _main(boot_param* _bp) /* * FUNCTION: Called by the boot loader to start the kernel @@ -271,7 +207,7 @@ asmlinkage void _main(boot_param* _bp) /* * Initalize services loaded at boot time */ - DPRINT("%d files loaded\n",bp.nr_files); + DPRINT1("%d files loaded\n",bp.nr_files); /* Pass 1: load registry chunks passed in */ start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]); @@ -279,7 +215,7 @@ asmlinkage void _main(boot_param* _bp) { if (!strcmp ((PCHAR) start, "REGEDIT4")) { - DPRINT("process registry chunk at %08lx\n", start); + DPRINT1("process registry chunk at %08lx\n", start); CmImportHive((PCHAR) start); } start = start + bp.module_length[i]; @@ -292,7 +228,7 @@ asmlinkage void _main(boot_param* _bp) { if (strcmp ((PCHAR) start, "REGEDIT4")) { - DPRINT("process module at %08lx\n", start); + DPRINT1("process module at %08lx\n", start); LdrProcessDriver((PVOID)start); } start = start + bp.module_length[i]; @@ -301,13 +237,15 @@ asmlinkage void _main(boot_param* _bp) /* * Load Auto configured drivers */ + CHECKPOINT; LdrLoadAutoConfigDrivers(); /* * Launch initial process */ - LdrLoadInitialProcess(); - + CHECKPOINT; + LdrLoadInitialProcess(); + /* * Enter idle loop */ diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index 1e335bdb884..2382ec2335a 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -1,4 +1,4 @@ -/* $Id: timer.c,v 1.23 1999/12/11 17:25:26 phreak Exp $ +/* $Id: timer.c,v 1.24 1999/12/13 22:04:36 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -132,8 +132,11 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval) NTSTATUS STDCALL NtDelayExecution(IN BOOLEAN Alertable, IN TIME* Interval) { - UNIMPLEMENTED; - return(STATUS_UNSUCCESSFUL); + NTSTATUS Status; + + Status = KeDelayExecutionThread(UserMode, Alertable, + (PLARGE_INTEGER)Internal); + return(Status); } @@ -396,7 +399,7 @@ VOID KeExpireTimers(VOID) // DPRINT("current_entry->Flink %x\n",current_entry->Flink); // DPRINT("current_entry->Flink->Flink %x\n",current_entry->Flink->Flink); - KeRaiseIrql( HIGH_LEVEL, &oldlvl ); + KeRaiseIrql(HIGH_LEVEL, &oldlvl); KeAcquireSpinLockAtDpcLevel(&TimerListLock); while (current_entry!=(&TimerListHead)) @@ -411,7 +414,7 @@ VOID KeExpireTimers(VOID) } } - KeReleaseSpinLock( &TimerListLock, oldlvl ); + KeReleaseSpinLock(&TimerListLock, oldlvl); // DPRINT("Finished KeExpireTimers()\n"); } @@ -429,7 +432,7 @@ VOID KiTimerInterrupt(VOID) extern unsigned int EiFreeNonPagedPool; extern unsigned int EiUsedNonPagedPool; extern ULONG PiNrThreads; - extern ULONG MiNrFreePages; +// extern ULONG MiNrFreePages; if (TimerInitDone == FALSE) { @@ -462,7 +465,8 @@ VOID KiTimerInterrupt(VOID) // sprintf(str,"%.8u %.8u",(unsigned int)EiNrUsedBlocks, // (unsigned int)EiFreeNonPagedPool); // sprintf(str,"%.8u %.8u",EiFreeNonPagedPool,EiUsedNonPagedPool); - sprintf(str,"%.8u %.8u",(unsigned int)PiNrRunnableThreads,(unsigned int)PiNrThreads); + sprintf(str,"%.8u %.8u",(unsigned int)PiNrRunnableThreads, + (unsigned int)PiNrThreads); // sprintf(str,"%.8u %.8u", (unsigned int)PiNrRunnableThreads, // (unsigned int)MiNrFreePages); for (i=0;i<17;i++) diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 24ed409c521..4e1f4d3f22b 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -18,6 +18,7 @@ #include #include +#include #define NDEBUG #include @@ -120,6 +121,32 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr) return(TRUE); } +VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus) +{ + PKWAIT_BLOCK WaitBlock; + BOOLEAN WasWaiting = FALSE; + + KeAcquireDispatcherDatabaseLock(FALSE); + + WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList; + if (WaitBlock != NULL) + { + WasWaiting = TRUE; + } + while (WaitBlock != NULL) + { + RemoveEntryList(&WaitBlock->WaitListEntry); + WaitBlock = WaitBlock->NextWaitBlock; + } + Thread->Tcb.WaitBlockList = NULL; + + if (WasWaiting) + { + PsUnfreezeThread(Thread, &WaitStatus); + } + + KeReleaseDispatcherDatabaseLock(FALSE); +} static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) { @@ -136,21 +163,21 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) while (!IsListEmpty(&(hdr->WaitListHead))) { - NTSTATUS Status = STATUS_WAIT_0; - current_entry = RemoveHeadList(&hdr->WaitListHead); - current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK, - WaitListEntry); + NTSTATUS Status = STATUS_WAIT_0; + current_entry = RemoveHeadList(&hdr->WaitListHead); + current = CONTAINING_RECORD(current_entry,KWAIT_BLOCK, + WaitListEntry); DPRINT("Waking %x\n",current->Thread); if (current->WaitType == WaitAny) { DPRINT("WaitAny: Remove all wait blocks.\n"); - //count the number of the wait block that is waking us, and set that as the wake status - for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; ++Status, PrevBlock = PrevBlock->NextWaitBlock ) - if( PrevBlock == current ) - break; - if( PrevBlock == 0 ) - DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" ); + //count the number of the wait block that is waking us, and set that as the wake status + for( PrevBlock = current->Thread->WaitBlockList; PrevBlock; ++Status, PrevBlock = PrevBlock->NextWaitBlock ) + if( PrevBlock == current ) + break; + if( PrevBlock == 0 ) + DbgPrint( "WaitOne: Wait Block not in list! Wait result will be corrupt\n" ); current->Thread->WaitBlockList = NULL; } else @@ -188,8 +215,8 @@ static BOOLEAN KeDispatcherObjectWakeAll(DISPATCHER_HEADER* hdr) KiSideEffectsBeforeWake(hdr); - PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), - &Status); + PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), + &Status); }; return(TRUE); } @@ -261,8 +288,8 @@ static BOOLEAN KeDispatcherObjectWakeOne(DISPATCHER_HEADER* hdr) KiSideEffectsBeforeWake(hdr); - PsResumeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), - &Status); + PsUnfreezeThread(CONTAINING_RECORD(current->Thread,ETHREAD,Tcb), + &Status); return(TRUE); } @@ -356,43 +383,53 @@ NTSTATUS KeWaitForSingleObject(PVOID Object, return(STATUS_USER_APC); } - KeAcquireDispatcherDatabaseLock(FALSE); - - DPRINT("hdr->SignalState %d\n", hdr->SignalState); - - if (KiIsObjectSignalled(hdr)) - { - KeReleaseDispatcherDatabaseLock(FALSE); - return(STATUS_WAIT_0); - } - if (Timeout != NULL) { - KeAddThreadTimeout(CurrentThread,Timeout); + KeAddThreadTimeout(CurrentThread,Timeout); } - - /* Append wait block to the KTHREAD wait block list */ - CurrentThread->WaitBlockList = &blk; - - blk.Object = Object; - blk.Thread = CurrentThread; - blk.WaitKey = 0; - blk.WaitType = WaitAny; - blk.NextWaitBlock = NULL; - DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x blk.WaitListEntry = %x\n", - hdr->WaitListHead.Flink,hdr->WaitListHead.Blink, blk.WaitListEntry ); - InsertTailList(&(hdr->WaitListHead),&(blk.WaitListEntry)); - KeReleaseDispatcherDatabaseLock(FALSE); - DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__, - KeGetCurrentIrql()); - PsSuspendThread(PsGetCurrentThread(), - &Status, - (UCHAR)Alertable, - WaitMode); + + do + { + KeAcquireDispatcherDatabaseLock(FALSE); + + DPRINT("hdr->SignalState %d\n", hdr->SignalState); + + if (KiIsObjectSignalled(hdr)) + { + KeReleaseDispatcherDatabaseLock(FALSE); + if (Timeout != NULL) + { + KeCancelTimer(&KeGetCurrentThread()->Timer); + } + return(STATUS_WAIT_0); + } + + /* Append wait block to the KTHREAD wait block list */ + CurrentThread->WaitBlockList = &blk; + + blk.Object = Object; + blk.Thread = CurrentThread; + blk.WaitKey = 0; + blk.WaitType = WaitAny; + blk.NextWaitBlock = NULL; + DPRINT("hdr->WaitListHead.Flink %x hdr->WaitListHead.Blink %x blk.WaitListEntry = %x\n", + hdr->WaitListHead.Flink,hdr->WaitListHead.Blink, blk.WaitListEntry ); + InsertTailList(&hdr->WaitListHead, &blk.WaitListEntry); + KeReleaseDispatcherDatabaseLock(FALSE); + DPRINT("Waiting for %x with irql %d\n", Object, KeGetCurrentIrql()); + PsFreezeThread(PsGetCurrentThread(), + &Status, + (UCHAR)Alertable, + WaitMode); + DPRINT("Woke from wait\n"); + + } while (Status == STATUS_KERNEL_APC); if (Timeout != NULL) + { KeCancelTimer(&KeGetCurrentThread()->Timer); - + } + DPRINT("Returning from KeWaitForSingleObject()\n"); return Status; } @@ -505,7 +542,7 @@ NTSTATUS KeWaitForMultipleObjects(ULONG Count, DPRINT("Waiting at %s:%d with irql %d\n", __FILE__, __LINE__, KeGetCurrentIrql()); - PsSuspendThread(PsGetCurrentThread(), + PsFreezeThread(PsGetCurrentThread(), &Status, Alertable, WaitMode); diff --git a/reactos/ntoskrnl/ldr/loader.c b/reactos/ntoskrnl/ldr/loader.c index 7ed8dc195d2..4feaf2aac9b 100644 --- a/reactos/ntoskrnl/ldr/loader.c +++ b/reactos/ntoskrnl/ldr/loader.c @@ -1,4 +1,4 @@ -/* $Id: loader.c,v 1.39 1999/12/04 04:59:38 bpalmer Exp $ +/* $Id: loader.c,v 1.40 1999/12/13 22:04:37 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -467,7 +467,7 @@ LdrPEProcessModule(PVOID ModuleLoadBase, PUNICODE_STRING pModuleName) unsigned int DriverSize, Idx, Idx2; ULONG RelocDelta, NumRelocs; DWORD CurrentSize, TotalRelocs; - PVOID DriverBase, CurrentBase; + PVOID DriverBase; PULONG PEMagic; PIMAGE_DOS_HEADER PEDosHeader; PIMAGE_FILE_HEADER PEFileHeader; diff --git a/reactos/ntoskrnl/makefile_rex b/reactos/ntoskrnl/makefile_rex index 64c9e9d127d..6fa3f1c7e05 100644 --- a/reactos/ntoskrnl/makefile_rex +++ b/reactos/ntoskrnl/makefile_rex @@ -1,4 +1,4 @@ -# $Id: makefile_rex,v 1.39 1999/12/10 17:04:35 dwelch Exp $ +# $Id: makefile_rex,v 1.40 1999/12/13 22:04:35 dwelch Exp $ # # ReactOS Operating System # @@ -26,7 +26,7 @@ RTL_OBJECTS = rtl/vsprintf.o rtl/lookas.o rtl/unicode.o rtl/time.o \ KE_OBJECTS = ke/main.o ke/timer.o ke/error.o ke/catch.o \ ke/dpc.o ke/wait.o ke/kqueue.o ke/dispatch.o \ ke/sem.o ke/critical.o ke/event.o ke/apc.o ke/bug.o \ - ke/mutex.o ke/kernel.o ke/ldt.o ke/apchelp.o \ + ke/mutex.o ke/kernel.o ke/ldt.o \ ke/process.o ke/gdt.o ke/idt.o ke/udelay.o KE_I386_OBJECTS = ke/i386/thread.o ke/i386/usercall.o ke/i386/exp.o @@ -48,7 +48,7 @@ IO_OBJECTS = io/iomgr.o io/create.o io/irp.o io/device.o io/rw.o \ OB_OBJECTS = ob/object.o ob/handle.o ob/namespc.o ob/ntobj.o ob/dirobj.o PS_OBJECTS = ps/psmgr.o ps/thread.o ps/process.o ps/idle.o ps/kill.o \ - ps/tinfo.o + ps/tinfo.o ps/create.o EX_OBJECTS = ex/work.o ex/fmutex.o ex/resource.o ex/time.o ex/interlck.o \ ex/callback.o ex/napi.o ex/power.o ex/sysinfo.o ex/locale.o \ @@ -226,6 +226,6 @@ ke/main.o: ke/main.c ../include/reactos/buildno.h #WITH_DEBUGGING = yes WIN32_LEAN_AND_MEAN = yes -#WARNINGS_ARE_ERRORS = yes +WARNINGS_ARE_ERRORS = yes include ../rules.mak diff --git a/reactos/ntoskrnl/mm/i386/memsafe.s b/reactos/ntoskrnl/mm/i386/memsafe.s index c1b38c7989a..6407dae74d0 100644 --- a/reactos/ntoskrnl/mm/i386/memsafe.s +++ b/reactos/ntoskrnl/mm/i386/memsafe.s @@ -71,4 +71,4 @@ _MmSafeCopyToUser: ret -_MemSafeCopyToUserEnd: +_MmSafeCopyToUserEnd: diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index 2c96adc47c2..e1e1ee56559 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -240,7 +240,7 @@ NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING PageFileName, break; } } - MiFreeSwapPages = MiFreeSwapPages + ActualSize; + MiFreeSwapPages = MiFreeSwapPages + MinimumSize; KeReleaseSpinLock(&PagingFileListLock, oldIrql); return(STATUS_SUCCESS); diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index 219d9594bd9..ce8c8492342 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -57,7 +57,7 @@ NTSTATUS MmReleaseMmInfo(PEPROCESS Process) PLIST_ENTRY CurrentEntry; PMEMORY_AREA Current; - DbgPrint("MmReleaseMmInfo(Process %x)\n",Process); + DPRINT("MmReleaseMmInfo(Process %x)\n",Process); while (!IsListEmpty(&Process->Pcb.MemoryAreaList)) { diff --git a/reactos/ntoskrnl/nt/port.c b/reactos/ntoskrnl/nt/port.c index 44971b11bf0..191cb7d38a4 100644 --- a/reactos/ntoskrnl/nt/port.c +++ b/reactos/ntoskrnl/nt/port.c @@ -1,4 +1,4 @@ -/* $Id: port.c,v 1.13 1999/12/10 17:04:36 dwelch Exp $ +/* $Id: port.c,v 1.14 1999/12/13 22:04:39 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -351,7 +351,7 @@ NTSTATUS STDCALL NtAcceptConnectPort (PHANDLE ServerPortHandle, { NTSTATUS Status; PEPORT NamedPort; - PEPORT OurPort; + PEPORT OurPort = NULL; PQUEUEDMESSAGE ConnectionRequest; KIRQL oldIrql; diff --git a/reactos/ntoskrnl/ps/create.c b/reactos/ntoskrnl/ps/create.c new file mode 100644 index 00000000000..2cb7916fb97 --- /dev/null +++ b/reactos/ntoskrnl/ps/create.c @@ -0,0 +1,392 @@ +/* $Id: create.c,v 1.1 1999/12/13 22:04:41 dwelch Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/ps/thread.c + * PURPOSE: Thread managment + * PROGRAMMER: David Welch (welch@mcmail.com) + * REVISION HISTORY: + * 23/06/98: Created + * 12/10/99: Phillip Susi: Thread priorities, and APC work + */ + +/* + * NOTE: + * + * All of the routines that manipulate the thread queue synchronize on + * a single spinlock + * + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBAL *******************************************************************/ + +static ULONG PiNextThreadUniqueId = 0; + +extern KSPIN_LOCK PiThreadListLock; +extern ULONG PiNrThreads; + +extern LIST_ENTRY PiThreadListHead; + +/* FUNCTIONS ***************************************************************/ + +static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 ) +{ + // wake up the thread, and tell it it timed out + NTSTATUS Status = STATUS_TIMEOUT; + PsUnfreezeThread( (ETHREAD *)Context, &Status ); +} + +VOID PiBeforeBeginThread(VOID) +{ + DPRINT("PiBeforeBeginThread()\n"); + //KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); + DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql()); +} + +VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext) +{ + NTSTATUS Ret; + +// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL); + KeLowerIrql(PASSIVE_LEVEL); + Ret = StartRoutine(StartContext); + PsTerminateSystemThread(Ret); + KeBugCheck(0); +} + +VOID PiDeleteThread(PVOID ObjectBody) +{ + KIRQL oldIrql; + DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody); + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess); + ((PETHREAD)ObjectBody)->ThreadsProcess = NULL; + PiNrThreads--; + RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry); + HalReleaseTask((PETHREAD)ObjectBody); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); +} + +VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount) +{ + DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody); + DPRINT("ObGetReferenceCount(ObjectBody) %d " + "ObGetHandleCount(ObjectBody) %d\n", + ObGetReferenceCount(ObjectBody), + ObGetHandleCount(ObjectBody)); +} + +NTSTATUS PsInitializeThread(HANDLE ProcessHandle, + PETHREAD * ThreadPtr, + PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ThreadAttributes) +{ + PETHREAD Thread; + NTSTATUS Status; + KIRQL oldIrql; + PEPROCESS Process; + + /* + * Reference process + */ + if (ProcessHandle != NULL) + { + Status = ObReferenceObjectByHandle(ProcessHandle, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode, + (PVOID*)&Process, + NULL); + if (Status != STATUS_SUCCESS) + { + DPRINT("Failed at %s:%d\n",__FILE__,__LINE__); + return(Status); + } + } + else + { + Process = SystemProcess; + ObReferenceObjectByPointer(Process, + PROCESS_CREATE_THREAD, + PsProcessType, + UserMode); + } + + /* + * Create and initialize thread + */ + Thread = ObCreateObject(ThreadHandle, + DesiredAccess, + ThreadAttributes, + PsThreadType); + DPRINT("Thread = %x\n",Thread); + + PiNrThreads++; + + Thread->Tcb.State = THREAD_STATE_SUSPENDED; + Thread->Tcb.SuspendCount = 0; + Thread->Tcb.FreezeCount = 1; + InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]); + InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]); + Thread->Tcb.KernelApcDisable = 1; + Thread->Tcb.WaitIrql = PASSIVE_LEVEL; + Thread->ThreadsProcess = Process; + KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread ); + + KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader, + InternalThreadType, + sizeof(ETHREAD), + FALSE); + + InitializeListHead(&Thread->IrpList); + Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement( + &PiNextThreadUniqueId); + Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; + DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread); + + *ThreadPtr = Thread; + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + + Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority; + Thread->Tcb.Priority = Thread->Tcb.BasePriority; + + return(STATUS_SUCCESS); +} + + +static NTSTATUS PsCreateTeb (HANDLE ProcessHandle, + PNT_TEB *TebPtr, + PETHREAD Thread, + PINITIAL_TEB InitialTeb) +{ + MEMORY_BASIC_INFORMATION Info; + NTSTATUS Status; + ULONG ByteCount; + ULONG RegionSize; + ULONG TebSize; + PVOID TebBase; + NT_TEB Teb; + + TebBase = (PVOID)0x7FFDE000; + TebSize = PAGESIZE; + + while (TRUE) + { + /* The TEB must reside in user space */ + Status = NtAllocateVirtualMemory(ProcessHandle, + &TebBase, + 0, + &TebSize, + MEM_COMMIT, + PAGE_READWRITE); + if (NT_SUCCESS(Status)) + { + DPRINT ("TEB allocated at %x\n", TebBase); + break; + } + else + { + DPRINT ("TEB allocation failed! Status %x\n",Status); + } + + TebBase = Info.BaseAddress - TebSize; + } + + DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); + + /* set all pointers to and from the TEB */ + Teb.Tib.Self = TebBase; + if (Thread->ThreadsProcess) + { + Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ + } + + /* store stack information from InitialTeb */ + if (InitialTeb != NULL) + { + Teb.Tib.StackBase = InitialTeb->StackBase; + Teb.Tib.StackLimit = InitialTeb->StackLimit; + + /* + * I don't know if this is really stored in a WNT-TEB, + * but it's needed to free the thread stack. (Eric Kohl) + */ + Teb.StackCommit = InitialTeb->StackCommit; + Teb.StackCommitMax = InitialTeb->StackCommitMax; + Teb.StackReserved = InitialTeb->StackReserved; + } + + + /* more initialization */ + Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; + Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; + + /* write TEB data into teb page */ + Status = NtWriteVirtualMemory(ProcessHandle, + TebBase, + &Teb, + sizeof(NT_TEB), + &ByteCount); + + if (!NT_SUCCESS(Status)) + { + /* free TEB */ + DPRINT ("Writing TEB failed!\n"); + + RegionSize = 0; + NtFreeVirtualMemory(ProcessHandle, + TebBase, + &RegionSize, + MEM_RELEASE); + + return Status; + } + + /* FIXME: fs:[0] = TEB */ + + if (TebPtr != NULL) + { +// *TebPtr = (PNT_TEB)TebBase; + } + + DPRINT ("TEB allocated at %p\n", TebBase); + + return Status; +} + + +NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID Client, + PCONTEXT ThreadContext, + PINITIAL_TEB InitialTeb, + BOOLEAN CreateSuspended) +{ + PETHREAD Thread; + PNT_TEB TebBase; + NTSTATUS Status; + + DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", + ThreadHandle,ThreadContext); + + Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, + DesiredAccess,ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = HalInitTaskWithContext(Thread,ThreadContext); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Status = PsCreateTeb (ProcessHandle, + &TebBase, + Thread, + InitialTeb); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + /* Attention: TebBase is in user memory space */ +// Thread->Tcb.Teb = TebBase; + + Thread->StartAddress=NULL; + + if (Client!=NULL) + { + *Client=Thread->Cid; + } + + if (!CreateSuspended) + { + DPRINT("Not creating suspended\n"); + PsUnfreezeThread(Thread, NULL); + } + DPRINT("Thread %x\n", Thread); + DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n", + ObGetReferenceCount(Thread), ObGetHandleCount(Thread)); + DPRINT("Finished PsCreateThread()\n"); + return(STATUS_SUCCESS); +} + + +NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, + ACCESS_MASK DesiredAccess, + POBJECT_ATTRIBUTES ObjectAttributes, + HANDLE ProcessHandle, + PCLIENT_ID ClientId, + PKSTART_ROUTINE StartRoutine, + PVOID StartContext) +/* + * FUNCTION: Creates a thread which executes in kernel mode + * ARGUMENTS: + * ThreadHandle (OUT) = Caller supplied storage for the returned thread + * handle + * DesiredAccess = Requested access to the thread + * ObjectAttributes = Object attributes (optional) + * ProcessHandle = Handle of process thread will run in + * NULL to use system process + * ClientId (OUT) = Caller supplied storage for the returned client id + * of the thread (optional) + * StartRoutine = Entry point for the thread + * StartContext = Argument supplied to the thread when it begins + * execution + * RETURNS: Success or failure status + */ +{ + PETHREAD Thread; + NTSTATUS Status; + + DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", + ThreadHandle,ProcessHandle); + + Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, + DesiredAccess,ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + Thread->StartAddress=StartRoutine; + Status = HalInitTask(Thread,StartRoutine,StartContext); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + if (ClientId!=NULL) + { + *ClientId=Thread->Cid; + } + + PsUnfreezeThread(Thread, NULL); + + return(STATUS_SUCCESS); +} + diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 2bc95ffe186..cd07204d2b0 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -16,7 +16,7 @@ #include #include -//#define NDEBUG +#define NDEBUG #include /* GLOBALS *******************************************************************/ @@ -32,17 +32,17 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus) * FUNCTION: Terminates the current thread */ { - KIRQL oldlvl; + KIRQL oldIrql; PETHREAD CurrentThread; PiNrRunnableThreads--; CurrentThread = PsGetCurrentThread(); - CurrentThread->ExitStatus = ExitStatus; - DPRINT("terminating %x\n",CurrentThread); - KeRaiseIrql(DISPATCH_LEVEL,&oldlvl); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + CurrentThread->ExitStatus = ExitStatus; DPRINT("ObGetReferenceCount(CurrentThread) %d\n", ObGetReferenceCount(CurrentThread)); @@ -52,7 +52,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus) CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE; KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader); - PsDispatchThread(THREAD_STATE_TERMINATED_1); + PsDispatchThreadNoLock(THREAD_STATE_TERMINATED_1); KeBugCheck(0); } @@ -69,6 +69,7 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus) PiNrRunnableThreads--; RemoveEntryList(&Thread->Tcb.QueueListEntry); } + RemoveEntryList(&Thread->Tcb.ThreadListEntry); Thread->Tcb.State = THREAD_STATE_TERMINATED_2; Thread->Tcb.DispatcherHeader.SignalState = TRUE; KeDispatcherObjectWake(&Thread->Tcb.DispatcherHeader); diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index e12ad921273..d7db66eb1f2 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.39 1999/12/12 03:56:53 phreak Exp $ +/* $Id: thread.c,v 1.40 1999/12/13 22:04:41 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -46,7 +46,7 @@ KSPIN_LOCK PiThreadListLock; /* * PURPOSE: List of threads associated with each priority level */ -static LIST_ENTRY PiThreadListHead = { &PiThreadListHead, &PiThreadListHead }; +LIST_ENTRY PiThreadListHead; static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS]; static BOOLEAN DoneInitYet = FALSE; ULONG PiNrThreads = 0; @@ -54,8 +54,6 @@ ULONG PiNrRunnableThreads = 0; static PETHREAD CurrentThread = NULL; -static ULONG PiNextThreadUniqueId = 0; - /* FUNCTIONS ***************************************************************/ PKTHREAD KeGetCurrentThread(VOID) @@ -88,7 +86,10 @@ VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus) if (current->ThreadsProcess == Process && current != PsGetCurrentThread()) { + KeReleaseSpinLock(&PiThreadListLock, oldlvl); PsTerminateOtherThread(current, ExitStatus); + KeAcquireSpinLock(&PiThreadListLock, &oldlvl); + current_entry = PiThreadListHead.Flink; } current_entry = current_entry->Flink; } @@ -104,31 +105,30 @@ static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread) InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority], &Thread->Tcb.QueueListEntry); -} - -VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext) -{ - NTSTATUS Ret; - -// KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL); - KeLowerIrql(PASSIVE_LEVEL); - Ret = StartRoutine(StartContext); - PsTerminateSystemThread(Ret); - KeBugCheck(0); + PiNrRunnableThreads++; } VOID PsDumpThreads(VOID) { PLIST_ENTRY current_entry; PETHREAD current; + ULONG t; + +// return; current_entry = PiThreadListHead.Flink; - + t = 0; + while (current_entry != &PiThreadListHead) { current = CONTAINING_RECORD(current_entry, ETHREAD, Tcb.ThreadListEntry); - + t++; + if (t >= PiNrThreads) + { + DbgPrint("Too many threads on list\n"); + return; + } DPRINT1("current %x current->Tcb.State %d eip %x ", current, current->Tcb.State, current->Tcb.Context.eip); @@ -148,6 +148,8 @@ VOID PsReapThreads(VOID) // DPRINT1("PsReapThreads()\n"); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + current_entry = PiThreadListHead.Flink; while (current_entry != &PiThreadListHead) @@ -159,11 +161,16 @@ VOID PsReapThreads(VOID) if (current->Tcb.State == THREAD_STATE_TERMINATED_1) { + RemoveEntryList(¤t->Tcb.ThreadListEntry); DPRINT("Reaping thread %x\n", current); current->Tcb.State = THREAD_STATE_TERMINATED_2; + KeReleaseSpinLock(&PiThreadListLock, oldIrql); ObDereferenceObject(current); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + current_entry = PiThreadListHead.Flink; } } + KeReleaseSpinLock(&PiThreadListLock, oldIrql); } static PETHREAD PsScanThreadList (KPRIORITY Priority) @@ -189,16 +196,11 @@ static PETHREAD PsScanThreadList (KPRIORITY Priority) } -static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) +VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) { KPRIORITY CurrentPriority; PETHREAD Candidate; - if (!DoneInitYet) - { - return; - } - CurrentThread->Tcb.State = NewThreadStatus; if (CurrentThread->Tcb.State == THREAD_STATE_RUNNABLE) { @@ -213,6 +215,8 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) Candidate = PsScanThreadList(CurrentPriority); if (Candidate == CurrentThread) { + PiNrRunnableThreads--; + KeReleaseSpinLockFromDpcLevel(&PiThreadListLock); return; } if (Candidate != NULL) @@ -223,12 +227,10 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) CurrentThread = Candidate; + PiNrRunnableThreads--; KeReleaseSpinLockFromDpcLevel( &PiThreadListLock ); - HalTaskSwitch(&CurrentThread->Tcb); - KeAcquireSpinLockAtDpcLevel( &PiThreadListLock ); - DPRINT( "Woken up, grabbed lock\n" ); + HalTaskSwitch(&CurrentThread->Tcb); PsReapThreads(); - DPRINT( "Reaped\n" ); return; } } @@ -236,200 +238,98 @@ static VOID PsDispatchThreadNoLock (ULONG NewThreadStatus) KeBugCheck(0); } -VOID PiBeforeBeginThread(VOID) -{ - DPRINT("PiBeforeBeginThread()\n"); - //KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL); - KeLowerIrql(PASSIVE_LEVEL); - DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql()); -} - VOID PsDispatchThread(ULONG NewThreadStatus) { KIRQL oldIrql; - KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + if (!DoneInitYet) + { + return; + } + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); CurrentThread->Tcb.WaitIrql = oldIrql; // save wait Irql PsDispatchThreadNoLock(NewThreadStatus); - KeReleaseSpinLock(&PiThreadListLock, oldIrql); KeLowerIrql(oldIrql); // DPRINT("oldIrql %d\n",oldIrql); } -static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 ) -{ - // wake up the thread, and tell it it timed out - NTSTATUS Status = STATUS_TIMEOUT; - PsResumeThread( (ETHREAD *)Context, &Status ); -} +/* + * Suspend and resume may only be called to suspend the current thread, except by apc.c + */ -NTSTATUS PsInitializeThread(HANDLE ProcessHandle, - PETHREAD * ThreadPtr, - PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ThreadAttributes) -{ - PETHREAD Thread; - NTSTATUS Status; - - PiNrThreads++; - - Thread = ObCreateObject(ThreadHandle, - DesiredAccess, - ThreadAttributes, - PsThreadType); - DPRINT("Thread = %x\n",Thread); - Thread->Tcb.State = THREAD_STATE_SUSPENDED; - Thread->Tcb.SuspendCount = 1; - InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]); - InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]); - Thread->Tcb.KernelApcDisable = 1; - Thread->Tcb.WaitIrql = PASSIVE_LEVEL; - KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread ); - - KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader, - InternalThreadType, - sizeof(ETHREAD), - FALSE); - - if (ProcessHandle != NULL) - { - Status = ObReferenceObjectByHandle(ProcessHandle, - PROCESS_CREATE_THREAD, - PsProcessType, - UserMode, - (PVOID*)&Thread->ThreadsProcess, - NULL); - if (Status != STATUS_SUCCESS) - { - DPRINT("Failed at %s:%d\n",__FILE__,__LINE__); - ObDereferenceObject( Thread ); - PiNrThreads--; - return(Status); - } - } - else - { - Thread->ThreadsProcess = SystemProcess; - ObReferenceObjectByPointer(Thread->ThreadsProcess, - PROCESS_CREATE_THREAD, - PsProcessType, - UserMode); - } - InitializeListHead(&Thread->IrpList); - Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement( - &PiNextThreadUniqueId); - Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId; - DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread); - - *ThreadPtr = Thread; - - InsertTailList(&PiThreadListHead, &Thread->Tcb.ThreadListEntry); - - Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority; - Thread->Tcb.Priority = Thread->Tcb.BasePriority; - - return(STATUS_SUCCESS); -} - - -// Suspend and resume may only be called to suspend the current thread, except by apc.c - -ULONG PsResumeThread(PETHREAD Thread, - PNTSTATUS WaitStatus) +ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus) { KIRQL oldIrql; ULONG r; - - DPRINT("PsResumeThread(Thread %x) CurrentThread %x \n",Thread, - PsGetCurrentThread()); - DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount); + + DPRINT("PsUnfreezeThread(Thread %x, WaitStatus %x)\n", Thread, WaitStatus); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount); - r = Thread->Tcb.SuspendCount; - if ( Thread->Tcb.SuspendCount == TRUE ) + + Thread->Tcb.FreezeCount--; + r = Thread->Tcb.FreezeCount; + + if (r <= 0) { -// DPRINT("Marking thread %x as runnable\n",Thread); - Thread->Tcb.SuspendCount = FALSE; + DPRINT("Resuming thread\n"); Thread->Tcb.State = THREAD_STATE_RUNNABLE; if (WaitStatus != NULL) { Thread->Tcb.WaitStatus = *WaitStatus; } PsInsertIntoThreadList(Thread->Tcb.Priority, Thread); - PiNrRunnableThreads++; } - DPRINT("About release ThreadListLock = %x\n", &PiThreadListLock); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); - DPRINT("Finished PsResumeThread()\n"); - return r; + return(r); } - -ULONG PsSuspendThread(PETHREAD Thread, - PNTSTATUS WaitStatus, - UCHAR Alertable, - ULONG WaitMode) +ULONG PsFreezeThread(PETHREAD Thread, PNTSTATUS Status, UCHAR Alertable, + ULONG WaitMode) { KIRQL oldIrql; ULONG r; - DPRINT("PsSuspendThread(Thread %x)\n",Thread); - DPRINT("Thread->Tcb.BasePriority %d\n", Thread->Tcb.BasePriority); - DPRINT("Thread->Tcb.SuspendCount %d\n",Thread->Tcb.SuspendCount); KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - r = Thread->Tcb.SuspendCount; - if ( Thread->Tcb.SuspendCount == FALSE ) - { - Thread->Tcb.SuspendCount = TRUE; - if (Thread != PsGetCurrentThread()) - { - if (Thread->Tcb.State == THREAD_STATE_RUNNABLE) - RemoveEntryList(&Thread->Tcb.QueueListEntry); - Thread->Tcb.State = THREAD_STATE_SUSPENDED; - Thread->Tcb.Alertable = Alertable; - Thread->Tcb.WaitMode = WaitMode; - PiNrRunnableThreads--; - } - else - { - DPRINT("Suspending current thread\n"); - Thread->Tcb.Alertable = Alertable; - Thread->Tcb.WaitMode = WaitMode; - PiNrRunnableThreads--; - Thread->Tcb.WaitIrql = oldIrql; // save wait IRQL - PsDispatchThreadNoLock(THREAD_STATE_SUSPENDED); - if (WaitStatus != NULL) - { - *WaitStatus = PsGetCurrentThread()->Tcb.WaitStatus; - } - } - } - DPRINT("About to release ThreadListLock = %x\n", &PiThreadListLock); - KeReleaseSpinLock(&PiThreadListLock, oldIrql); - DPRINT("PsSuspendThread() finished\n"); - return r; -} - - -VOID PiDeleteThread(PVOID ObjectBody) -{ - DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody); - ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess); - ((PETHREAD)ObjectBody)->ThreadsProcess = NULL; - PiNrThreads--; - RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry); - HalReleaseTask((PETHREAD)ObjectBody); -} - -VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount) -{ - DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody); - DPRINT("ObGetReferenceCount(ObjectBody) %d " - "ObGetHandleCount(ObjectBody) %d\n", - ObGetReferenceCount(ObjectBody), - ObGetHandleCount(ObjectBody)); + Thread->Tcb.FreezeCount++; + r = Thread->Tcb.FreezeCount; + + DPRINT("r %d\n", r); + + if (r == 0) + { + DPRINT("Not suspending thread\n"); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + return(r); + } + + Thread->Tcb.Alertable = Alertable; + Thread->Tcb.WaitMode = WaitMode; + + if (PsGetCurrentThread() != Thread) + { + DPRINT("Suspending other\n"); + if (Thread->Tcb.State == THREAD_STATE_RUNNABLE) + { + RemoveEntryList(&Thread->Tcb.QueueListEntry); + } + Thread->Tcb.State = THREAD_STATE_FROZEN; + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + } + else + { + DPRINT("Suspending self\n"); + Thread->Tcb.WaitIrql = oldIrql; + PsDispatchThreadNoLock(THREAD_STATE_FROZEN); + if (Status != NULL) + { + *Status = Thread->Tcb.WaitStatus; + } + KeLowerIrql(oldIrql); + } + return(r); } VOID PsInitThreadManagment(VOID) @@ -474,8 +374,9 @@ VOID PsInitThreadManagment(VOID) THREAD_ALL_ACCESS,NULL); HalInitFirstTask(FirstThread); FirstThread->Tcb.State = THREAD_STATE_RUNNING; - FirstThread->Tcb.SuspendCount = 0; - + FirstThread->Tcb.FreezeCount = 0; + ZwClose(FirstThreadHandle); + DPRINT("FirstThread %x\n",FirstThread); CurrentThread = FirstThread; @@ -484,226 +385,10 @@ VOID PsInitThreadManagment(VOID) } -static NTSTATUS -PsCreateTeb (HANDLE ProcessHandle, - PNT_TEB *TebPtr, - PETHREAD Thread, - PINITIAL_TEB InitialTeb) -{ - MEMORY_BASIC_INFORMATION Info; - NTSTATUS Status; - ULONG ByteCount; - ULONG RegionSize; - ULONG TebSize; - PVOID TebBase; - NT_TEB Teb; - - TebBase = (PVOID)0x7FFDE000; - TebSize = PAGESIZE; - - while (TRUE) - { - /* The TEB must reside in user space */ - Status = NtAllocateVirtualMemory(ProcessHandle, - &TebBase, - 0, - &TebSize, - MEM_COMMIT, - PAGE_READWRITE); - if (NT_SUCCESS(Status)) - { - DPRINT ("TEB allocated at %x\n", TebBase); - break; - } - else - { - DPRINT ("TEB allocation failed! Status %x\n",Status); - } - - TebBase = Info.BaseAddress - TebSize; - } - - DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize); - - /* set all pointers to and from the TEB */ - Teb.Tib.Self = TebBase; - if (Thread->ThreadsProcess) - { - Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */ - } - - /* store stack information from InitialTeb */ - if (InitialTeb != NULL) - { - Teb.Tib.StackBase = InitialTeb->StackBase; - Teb.Tib.StackLimit = InitialTeb->StackLimit; - - /* - * I don't know if this is really stored in a WNT-TEB, - * but it's needed to free the thread stack. (Eric Kohl) - */ - Teb.StackCommit = InitialTeb->StackCommit; - Teb.StackCommitMax = InitialTeb->StackCommitMax; - Teb.StackReserved = InitialTeb->StackReserved; - } - - - /* more initialization */ - Teb.Cid.UniqueThread = Thread->Cid.UniqueThread; - Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess; - - /* write TEB data into teb page */ - Status = NtWriteVirtualMemory(ProcessHandle, - TebBase, - &Teb, - sizeof(NT_TEB), - &ByteCount); - - if (!NT_SUCCESS(Status)) - { - /* free TEB */ - DPRINT ("Writing TEB failed!\n"); - - RegionSize = 0; - NtFreeVirtualMemory(ProcessHandle, - TebBase, - &RegionSize, - MEM_RELEASE); - - return Status; - } - - /* FIXME: fs:[0] = TEB */ - - if (TebPtr != NULL) - { -// *TebPtr = (PNT_TEB)TebBase; - } - - DPRINT ("TEB allocated at %p\n", TebBase); - - return Status; -} - - -NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID Client, - PCONTEXT ThreadContext, - PINITIAL_TEB InitialTeb, - BOOLEAN CreateSuspended) -{ - PETHREAD Thread; - PNT_TEB TebBase; - NTSTATUS Status; - - DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n", - ThreadHandle,ThreadContext); - - Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, - DesiredAccess,ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = HalInitTaskWithContext(Thread,ThreadContext); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Status = PsCreateTeb (ProcessHandle, - &TebBase, - Thread, - InitialTeb); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - /* Attention: TebBase is in user memory space */ -// Thread->Tcb.Teb = TebBase; - - Thread->StartAddress=NULL; - - if (Client!=NULL) - { - *Client=Thread->Cid; - } - - if (!CreateSuspended) - { - DPRINT("Not creating suspended\n"); - PsResumeThread(Thread, NULL); - } - DPRINT("Thread %x\n", Thread); - DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n", - ObGetReferenceCount(Thread), ObGetHandleCount(Thread)); - DPRINT("Finished PsCreateThread()\n"); - return(STATUS_SUCCESS); -} - - -NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle, - ACCESS_MASK DesiredAccess, - POBJECT_ATTRIBUTES ObjectAttributes, - HANDLE ProcessHandle, - PCLIENT_ID ClientId, - PKSTART_ROUTINE StartRoutine, - PVOID StartContext) /* - * FUNCTION: Creates a thread which executes in kernel mode - * ARGUMENTS: - * ThreadHandle (OUT) = Caller supplied storage for the returned thread - * handle - * DesiredAccess = Requested access to the thread - * ObjectAttributes = Object attributes (optional) - * ProcessHandle = Handle of process thread will run in - * NULL to use system process - * ClientId (OUT) = Caller supplied storage for the returned client id - * of the thread (optional) - * StartRoutine = Entry point for the thread - * StartContext = Argument supplied to the thread when it begins - * execution - * RETURNS: Success or failure status + * Sets thread's base priority relative to the process' base priority + * Should only be passed in THREAD_PRIORITY_ constants in pstypes.h */ -{ - PETHREAD Thread; - NTSTATUS Status; - - DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n", - ThreadHandle,ProcessHandle); - - Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle, - DesiredAccess,ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - Thread->StartAddress=StartRoutine; - Status = HalInitTask(Thread,StartRoutine,StartContext); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - if (ClientId!=NULL) - { - *ClientId=Thread->Cid; - } - - PsResumeThread(Thread, NULL); - - return(STATUS_SUCCESS); -} - - -// Sets thread's base priority relative to the process' base priority -// Should only be passed in THREAD_PRIORITY_ constants in pstypes.h LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment) { Thread->BasePriority = ((PETHREAD)Thread)->ThreadsProcess->Pcb.BasePriority + Increment; @@ -758,7 +443,7 @@ NTSTATUS STDCALL NtAlertThread (IN HANDLE ThreadHandle) } ThreadStatus = STATUS_ALERTED; - (VOID)PsResumeThread(Thread, &ThreadStatus); + (VOID)PsUnfreezeThread(Thread, &ThreadStatus); ObDereferenceObject(Thread); return(STATUS_SUCCESS); @@ -794,24 +479,8 @@ NTSTATUS STDCALL NtResumeThread (IN HANDLE ThreadHandle, * RETURNS: Status */ { - PETHREAD Thread; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - (*SuspendCount) = PsResumeThread(Thread, NULL); - - ObDereferenceObject(Thread); - return(STATUS_SUCCESS); + UNIMPLEMENTED; + return(STATUS_UNSUCCESSFUL); } @@ -838,27 +507,8 @@ NTSTATUS STDCALL NtSuspendThread (IN HANDLE ThreadHandle, * RETURNS: Status */ { - PETHREAD Thread; - NTSTATUS Status; - - Status = ObReferenceObjectByHandle(ThreadHandle, - THREAD_SUSPEND_RESUME, - PsThreadType, - UserMode, - (PVOID*)&Thread, - NULL); - if (Status != STATUS_SUCCESS) - { - return(Status); - } - - (*PreviousSuspendCount) = PsSuspendThread(Thread, - NULL, - FALSE, - UserMode); - - ObDereferenceObject(Thread); - return(STATUS_SUCCESS); + UNIMPLEMENTED; + return(STATUS_UNSUCCESSFUL); }