From cc5dc64c307a780d718e1a9e8a8cdb32c000bfe6 Mon Sep 17 00:00:00 2001 From: David Welch Date: Sat, 18 Dec 1999 17:48:23 +0000 Subject: [PATCH] Worked around compiler bug in NtDelayExecution Added some page free checking Reorganised thread code a bit svn path=/trunk/; revision=892 --- reactos/apps/tests/thread/thread.c | 1 + reactos/include/ddk/pstypes.h | 8 +-- reactos/include/ddk/zw.h | 9 +-- reactos/include/internal/ps.h | 1 + reactos/include/kernel32/kernel32.h | 2 + reactos/ntoskrnl/ke/i386/usercall.c | 80 ++++++-------------------- reactos/ntoskrnl/ke/main.c | 4 +- reactos/ntoskrnl/ke/timer.c | 13 +++-- reactos/ntoskrnl/mm/freelist.c | 12 +++- reactos/ntoskrnl/mm/i386/page.c | 28 +++++++-- reactos/ntoskrnl/ps/kill.c | 84 +++++++++++++++++++++++++-- reactos/ntoskrnl/ps/thread.c | 89 +++-------------------------- 12 files changed, 160 insertions(+), 171 deletions(-) diff --git a/reactos/apps/tests/thread/thread.c b/reactos/apps/tests/thread/thread.c index 2b03be5a85f..e9aa2c6a768 100644 --- a/reactos/apps/tests/thread/thread.c +++ b/reactos/apps/tests/thread/thread.c @@ -14,6 +14,7 @@ DWORD WINAPI thread_main1(LPVOID param) s = s % 10; printf("s %d\n", s); Sleep(s); + printf("Thread %d finished\n", (DWORD)param); return 0; } diff --git a/reactos/include/ddk/pstypes.h b/reactos/include/ddk/pstypes.h index dc3a53d6c7a..05afb2acf19 100644 --- a/reactos/include/ddk/pstypes.h +++ b/reactos/include/ddk/pstypes.h @@ -174,7 +174,7 @@ typedef struct _KTHREAD PVOID KernelStack; UCHAR DebugActive; UCHAR State; - USHORT Alerted; + UCHAR Alerted[2]; UCHAR Iopl; UCHAR NpxState; UCHAR Saturation; @@ -199,9 +199,9 @@ typedef struct _KTHREAD KAFFINITY UserAffinity; UCHAR SystemAffinityActive; UCHAR Pad; - PKQUEUE Queue; + PKQUEUE Queue; + KSPIN_LOCK ApcQueueLock; KTIMER Timer; - KDPC TimerDpc; // Added by Phillip Susi for internal KeAddThreadTimeout() impl. LIST_ENTRY QueueListEntry; KAFFINITY Affinity; UCHAR Preempted; @@ -234,7 +234,7 @@ typedef struct _KTHREAD /* Provisionally added by David Welch */ hal_thread_state Context; - + KDPC TimerDpc; // Added by Phillip Susi for internal KeAddThreadTimeout() impl. } KTHREAD, *PKTHREAD; // According to documentation the stack should have a commited [ 1 page ] and diff --git a/reactos/include/ddk/zw.h b/reactos/include/ddk/zw.h index 7146e088e96..eeb8208ca8b 100644 --- a/reactos/include/ddk/zw.h +++ b/reactos/include/ddk/zw.h @@ -1,5 +1,5 @@ -/* $Id: zw.h,v 1.23 1999/12/10 17:04:33 dwelch Exp $ +/* $Id: zw.h,v 1.24 1999/12/18 17:48:21 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -1201,12 +1201,7 @@ NtCurrentTeb(VOID * Interval = Specifies the interval to wait. * RETURNS: Status */ -NTSTATUS -STDCALL -NtDelayExecution( - IN BOOLEAN Alertable, - IN TIME* Interval - ); +NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable, IN TIME* Interval); NTSTATUS STDCALL diff --git a/reactos/include/internal/ps.h b/reactos/include/internal/ps.h index 603525c8f24..affca540c7c 100644 --- a/reactos/include/internal/ps.h +++ b/reactos/include/internal/ps.h @@ -31,6 +31,7 @@ ULONG PsFreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus, VOID PiInitApcManagement(VOID); VOID PiDeleteThread(PVOID ObjectBody); VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount); +VOID PsReapThreads(VOID); NTSTATUS PsInitializeThread(HANDLE ProcessHandle, PETHREAD* ThreadPtr, PHANDLE ThreadHandle, diff --git a/reactos/include/kernel32/kernel32.h b/reactos/include/kernel32/kernel32.h index dd1ffd0c946..3c3cabf1c92 100644 --- a/reactos/include/kernel32/kernel32.h +++ b/reactos/include/kernel32/kernel32.h @@ -10,6 +10,8 @@ #define CHECKPOINT do { dprintf("(KERNEL32:%s:%d) Checkpoint\n",__FILE__,__LINE__); } while(0); #endif +#define DPRINT1(args...) do { dprintf("(KERNEL32:%s:%d) ",__FILE__,__LINE__); dprintf(args); } while(0); + void dprintf(char* fmt, ...); void aprintf(char* fmt, ...); diff --git a/reactos/ntoskrnl/ke/i386/usercall.c b/reactos/ntoskrnl/ke/i386/usercall.c index dd060aab89e..b80161fdb90 100644 --- a/reactos/ntoskrnl/ke/i386/usercall.c +++ b/reactos/ntoskrnl/ke/i386/usercall.c @@ -1,4 +1,4 @@ -/* $Id: usercall.c,v 1.3 1999/12/02 20:53:53 dwelch Exp $ +/* $Id: usercall.c,v 1.4 1999/12/18 17:48:22 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -99,11 +99,24 @@ void PsBeginThreadWithContextInternal(void); "popl %ebp\n\t" "iret\n\t"); -VOID KiSystemCallHook(ULONG Nr) +VOID KiSystemCallHook(ULONG Nr, ...) { -// DbgPrint("KiSystemCallHook(Nr %d) %x ", Nr, PsGetCurrentProcess()); -// DbgPrint("SystemCall %x\n", _SystemServiceTable[Nr].Function); +#ifdef TRACE_SYSTEM_CALLS + va_list ap; + ULONG i; + + va_start(ap, Nr); + + DbgPrint("%x/%d ", _SystemServiceTable[Nr].Function,Nr); + DbgPrint("%x (", _SystemServiceTable[Nr].ParametersSize); + for (i = 0; i < _SystemServiceTable[Nr].ParametersSize / 4; i++) + { + DbgPrint("%x, ", va_arg(ap, ULONG)); + } + DbgPrint(")\n"); assert_irql(PASSIVE_LEVEL); + va_end(ap); +#endif } ULONG KiAfterSystemCallHook(ULONG NtStatus, PCONTEXT Context) @@ -210,62 +223,3 @@ void interrupt_handler2e(void); "iret\n\t"); - -void old_interrupt_handler2e(void); - __asm__("\n\t.global _old_interrupt_handler2e\n\t" - "_old_interrupt_handler2e:\n\t" - - /* Save the users context */ - "pushl %ds\n\t" - "pushl %es\n\t" - "pushl %esi\n\t" - "pushl %edi\n\t" - "pushl %ebp\n\t" - "pushl %ebx\n\t" - - /* Set ES to kernel segment */ - "movw $"STR(KERNEL_DS)",%bx\n\t" - "movw %bx,%es\n\t" - - /* Allocate new Kernel stack frame */ - "movl %esp,%ebp\n\t" - - /* Users's current stack frame pointer is source */ - "movl %edx,%esi\n\t" - - /* FIXME: determine system service table to use */ - /* FIXME: chech to see if SS is valid/inrange */ - - /* Allocate room for argument list from kernel stack */ - "movl %es:__SystemServiceTable(,%eax,8),%ecx\n\t" - "subl %ecx,%esp\n\t" - - /* Copy the arguments from the user stack to the kernel stack */ - "movl %esp,%edi\n\t" - "rep\n\tmovsb\n\t" - - /* DS is now also kernel segment */ - "movw %bx,%ds\n\t" - - /* Call system call hook */ - "pushl %eax\n\t" - "call _KiSystemCallHook\n\t" - "popl %eax\n\t" - - /* Make the system service call */ - "movl %ds:__SystemServiceTable+4(,%eax,8),%eax\n\t" - "call *%eax\n\t" - - /* Deallocate the kernel stack frame */ - "movl %ebp,%esp\n\t" - - /* Restore the user context */ - "popl %ebx\n\t" - "popl %ebp\n\t" - "popl %edi\n\t" - "popl %esi\n\t" - "popl %es\n\t" - "popl %ds\n\t" - "iret\n\t"); - - diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index e730e4a4736..df5cdf5cb48 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.32 1999/12/13 22:04:36 dwelch Exp $ +/* $Id: main.c,v 1.33 1999/12/18 17:48:22 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 ****************************************************************/ diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index 2382ec2335a..9978b471802 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -1,4 +1,4 @@ -/* $Id: timer.c,v 1.24 1999/12/13 22:04:36 dwelch Exp $ +/* $Id: timer.c,v 1.25 1999/12/18 17:48:22 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -129,13 +129,18 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval) } -NTSTATUS STDCALL NtDelayExecution(IN BOOLEAN Alertable, +NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable, IN TIME* Interval) { NTSTATUS Status; + PLARGE_INTEGER IntervalP; - Status = KeDelayExecutionThread(UserMode, Alertable, - (PLARGE_INTEGER)Internal); + IntervalP = (PLARGE_INTEGER)Interval; + + DPRINT1("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n", + Alertable, Internal, IntervalP); + + Status = KeDelayExecutionThread(UserMode, Alertable, IntervalP); return(Status); } diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 9422ecd1b12..ae4ddce3f1e 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -168,7 +168,11 @@ VOID MmFreePage(PVOID PhysicalAddress, ULONG Nr) DPRINT("MmFreePage(PhysicalAddress %x, Nr %x)\n", PhysicalAddress, Nr); - assert(((ULONG)PhysicalAddress) <= 0x400000); + if (((ULONG)PhysicalAddress) > 0x400000) + { + DbgPrint("MmFreePage() failed with %x\n", PhysicalAddress); + KeBugCheck(0); + } MiNrFreePages = MiNrFreePages + Nr; MiNrUsedPages = MiNrUsedPages - Nr; @@ -218,7 +222,11 @@ PVOID MmAllocPage(VOID) MiNrUsedPages = MiNrUsedPages + 1; MiNrFreePages = MiNrFreePages - 1; - assert(offset <= 0x400000); + if (offset > 0x400000) + { + DbgPrint("Failed in MmAllocPage() with offset %x\n", offset); + KeBugCheck(0); + } DPRINT("MmAllocPage() = %x\n",offset); return((PVOID)offset); diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index d0a11a068bf..f1e6ef0a979 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -23,6 +23,8 @@ /* GLOBALS *****************************************************************/ +extern ULONG MiNrFreePages; + #define PA_BIT_PRESENT (0) #define PA_BIT_READWRITE (1) #define PA_BIT_USER (2) @@ -168,9 +170,17 @@ VOID MmDeletePageEntry(PEPROCESS Process, PVOID Address, BOOL FreePage) } return; } - page_tlb = ADDR_TO_PTE(Address); + page_tlb = ADDR_TO_PTE(Address); if (FreePage && PAGE_MASK(*page_tlb) != 0) { + if (PAGE_MASK(*page_tlb) >= 0x400000) + { + DbgPrint("MmDeletePageEntry(Address %x) Physical %x Free %d, " + "Entry %x\n", + Address, PAGE_MASK(*page_tlb), MiNrFreePages, + *page_tlb); + KeBugCheck(0); + } MmFreePage((PVOID)PAGE_MASK(*page_tlb),1); } *page_tlb = 0; @@ -219,11 +229,19 @@ VOID MmSetPage(PEPROCESS Process, PEPROCESS CurrentProcess = PsGetCurrentProcess(); ULONG Attributes = 0; - DPRINT("MmSetPage(Process %x, Address %x, flProtect %x, " - "PhysicalAddress %x)\n",Process,Address,flProtect, - PhysicalAddress); + if (PAGE_ROUND_DOWN(Address) == 0x77631000) + { + DPRINT1("MmSetPage(Process %x, Address %x, flProtect %x, " + "PhysicalAddress %x)\n",Process,Address,flProtect, + PhysicalAddress); + } - assert(((ULONG)PhysicalAddress)<0x400000); + if (((ULONG)PhysicalAddress) >= 0x400000) + { + DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n", + Process, Address, PhysicalAddress); + KeBugCheck(0); + } Attributes = ProtectToPTE(flProtect); diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index 8ae130a41bc..129705d4374 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -24,9 +24,88 @@ extern ULONG PiNrThreads; extern ULONG PiNrRunnableThreads; extern KSPIN_LOCK PiThreadListLock; +extern LIST_ENTRY PiThreadListHead; /* FUNCTIONS *****************************************************************/ +VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus) +{ + KIRQL oldlvl; + PLIST_ENTRY current_entry; + PETHREAD current; + + KeAcquireSpinLock(&PiThreadListLock, &oldlvl); + + current_entry = PiThreadListHead.Flink; + while (current_entry != &PiThreadListHead) + { + current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.QueueListEntry); + if (current->ThreadsProcess == Process && + current != PsGetCurrentThread()) + { + KeReleaseSpinLock(&PiThreadListLock, oldlvl); + PsTerminateOtherThread(current, ExitStatus); + KeAcquireSpinLock(&PiThreadListLock, &oldlvl); + current_entry = PiThreadListHead.Flink; + } + current_entry = current_entry->Flink; + } + + KeReleaseSpinLock(&PiThreadListLock, oldlvl); +} + +VOID PsReapThreads(VOID) +{ + PLIST_ENTRY current_entry; + PETHREAD current; + KIRQL oldIrql; + +// DPRINT1("PsReapThreads()\n"); + + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + + current_entry = PiThreadListHead.Flink; + + while (current_entry != &PiThreadListHead) + { + current = CONTAINING_RECORD(current_entry, ETHREAD, + Tcb.ThreadListEntry); + + current_entry = current_entry->Flink; + + if (current->Tcb.State == THREAD_STATE_TERMINATED_1) + { + PEPROCESS Process = current->ThreadsProcess; + NTSTATUS Status = current->ExitStatus; + + ObReferenceObjectByPointer(Process, + 0, + PsProcessType, + KernelMode ); + DPRINT("Reaping thread %x\n", current); + current->Tcb.State = THREAD_STATE_TERMINATED_2; + RemoveEntryList(¤t->Tcb.ProcessThreadListEntry); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + ObDereferenceObject(current); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + if(IsListEmpty( &Process->Pcb.ThreadListHead)) + { + /* + * TODO: Optimize this so it doesnt jerk the IRQL around so + * much :) + */ + DPRINT("Last thread terminated, terminating process\n"); + KeReleaseSpinLock(&PiThreadListLock, oldIrql); + PiTerminateProcess(Process, Status); + KeAcquireSpinLock(&PiThreadListLock, &oldIrql); + } + ObDereferenceObject(Process); + current_entry = PiThreadListHead.Flink; + } + } + KeReleaseSpinLock(&PiThreadListLock, oldIrql); +} + VOID PsTerminateCurrentThread(NTSTATUS ExitStatus) /* * FUNCTION: Terminates the current thread @@ -35,7 +114,6 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus) KIRQL oldIrql; PETHREAD CurrentThread; - CurrentThread = PsGetCurrentThread(); DPRINT("terminating %x\n",CurrentThread); @@ -65,15 +143,13 @@ VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus) KeAcquireSpinLock(&PiThreadListLock, &oldIrql); if (Thread->Tcb.State == THREAD_STATE_RUNNABLE) { - 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); - ObDereferenceObject(Thread); KeReleaseSpinLock(&PiThreadListLock, oldIrql); + ObDereferenceObject(Thread); } NTSTATUS STDCALL PiTerminateProcess(PEPROCESS Process, diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 265721a82c9..c9b20c73805 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.43 1999/12/18 07:33:53 phreak Exp $ +/* $Id: thread.c,v 1.44 1999/12/18 17:48:23 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -71,32 +71,6 @@ HANDLE PsGetCurrentThreadId(VOID) return(CurrentThread->Cid.UniqueThread); } -VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus) -{ - KIRQL oldlvl; - PLIST_ENTRY current_entry; - PETHREAD current; - - KeAcquireSpinLock(&PiThreadListLock, &oldlvl); - - current_entry = PiThreadListHead.Flink; - while (current_entry != &PiThreadListHead) - { - current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.QueueListEntry); - if (current->ThreadsProcess == Process && - current != PsGetCurrentThread()) - { - KeReleaseSpinLock(&PiThreadListLock, oldlvl); - PsTerminateOtherThread(current, ExitStatus); - KeAcquireSpinLock(&PiThreadListLock, &oldlvl); - current_entry = PiThreadListHead.Flink; - } - current_entry = current_entry->Flink; - } - - KeReleaseSpinLock(&PiThreadListLock, oldlvl); -} - static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread) { // DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority, @@ -129,63 +103,17 @@ VOID PsDumpThreads(VOID) DbgPrint("Too many threads on list\n"); return; } - DPRINT1("current %x current->Tcb.State %d eip %x ", + DbgPrint("current %x current->Tcb.State %d eip %x ", current, current->Tcb.State, current->Tcb.Context.eip); // KeDumpStackFrames(0, 16); - DPRINT1("PID %d ", current->ThreadsProcess->UniqueProcessId); - DPRINT1("\n"); + DbgPrint("PID %d ", current->ThreadsProcess->UniqueProcessId); + DbgPrint("\n"); current_entry = current_entry->Flink; } } -VOID PsReapThreads(VOID) -{ - PLIST_ENTRY current_entry; - PETHREAD current; - KIRQL oldIrql; - -// DPRINT1("PsReapThreads()\n"); - - KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - - current_entry = PiThreadListHead.Flink; - - while (current_entry != &PiThreadListHead) - { - current = CONTAINING_RECORD(current_entry, ETHREAD, - Tcb.ThreadListEntry); - - current_entry = current_entry->Flink; - - if (current->Tcb.State == THREAD_STATE_TERMINATED_1) - { - PEPROCESS Process = current->ThreadsProcess; - NTSTATUS Status = current->ExitStatus; - - ObReferenceObjectByPointer( Process, 0, PsProcessType, KernelMode ); - DPRINT("Reaping thread %x\n", current); - current->Tcb.State = THREAD_STATE_TERMINATED_2; - RemoveEntryList( ¤t->Tcb.ProcessThreadListEntry ); - KeReleaseSpinLock(&PiThreadListLock, oldIrql); - ObDereferenceObject(current); - KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - if( IsListEmpty( &Process->Pcb.ThreadListHead ) ) - { - //TODO: Optimize this so it doesnt jerk the IRQL around so much :) - DPRINT( "Last thread terminated, terminating process\n" ); - KeReleaseSpinLock(&PiThreadListLock, oldIrql); - PiTerminateProcess( Process, Status ); - KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - } - ObDereferenceObject( Process ); - current_entry = PiThreadListHead.Flink; - } - } - KeReleaseSpinLock(&PiThreadListLock, oldIrql); -} - static PETHREAD PsScanThreadList (KPRIORITY Priority) { PLIST_ENTRY current_entry; @@ -282,14 +210,15 @@ ULONG PsUnfreezeThread(PETHREAD Thread, PNTSTATUS WaitStatus) Thread->Tcb.FreezeCount--; r = Thread->Tcb.FreezeCount; + if (WaitStatus != NULL) + { + Thread->Tcb.WaitStatus = *WaitStatus; + } + if (r <= 0) { DPRINT("Resuming thread\n"); Thread->Tcb.State = THREAD_STATE_RUNNABLE; - if (WaitStatus != NULL) - { - Thread->Tcb.WaitStatus = *WaitStatus; - } PsInsertIntoThreadList(Thread->Tcb.Priority, Thread); }