From 076c1c6ac33c38795c9bd0718bd2ddf21e37c7d9 Mon Sep 17 00:00:00 2001 From: David Welch Date: Tue, 6 Feb 2001 00:11:20 +0000 Subject: [PATCH] Fixed timer code Fixed NtClose return in case of error Added new APC-like primitive for terminating threads Fixed restriction on size of working set svn path=/trunk/; revision=1603 --- reactos/Makefile | 2 +- reactos/apps/tests/bench/bench-thread.c | 8 +- reactos/apps/tests/thread/thread.c | 13 ++- reactos/include/ddk/cctypes.h | 5 + reactos/include/pe.h | 1 + reactos/install.sh | 3 +- reactos/lib/kernel32/process/proc.c | 46 +++++--- reactos/ntoskrnl/include/internal/ke.h | 2 + reactos/ntoskrnl/include/internal/mm.h | 40 +++---- reactos/ntoskrnl/ke/apc.c | 106 ++++++++++++----- reactos/ntoskrnl/ke/i386/irq.c | 12 +- reactos/ntoskrnl/ke/i386/usercall.c | 32 +----- reactos/ntoskrnl/ke/kthread.c | 21 +++- reactos/ntoskrnl/ke/main.c | 23 ++-- reactos/ntoskrnl/ke/timer.c | 13 ++- reactos/ntoskrnl/mm/freelist.c | 2 + reactos/ntoskrnl/mm/i386/page.c | 4 +- reactos/ntoskrnl/mm/i386/pfault.c | 11 +- reactos/ntoskrnl/mm/pagefile.c | 63 +++++++--- reactos/ntoskrnl/mm/section.c | 4 +- reactos/ntoskrnl/mm/wset.c | 147 ++++++++++++++++++------ reactos/ntoskrnl/ob/handle.c | 4 +- reactos/ntoskrnl/ps/kill.c | 60 +++++++--- reactos/ntoskrnl/ps/suspend.c | 54 +++------ 24 files changed, 440 insertions(+), 236 deletions(-) diff --git a/reactos/Makefile b/reactos/Makefile index d3e3daf42bf..b0a10994523 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -56,7 +56,7 @@ NET_DEVICE_DRIVERS = ne2000 SYS_APPS = shell winlogon services APPS = args hello test cat bench apc shm lpc thread event file gditest \ - pteb consume dump_shared_data vmtest regtest + pteb consume dump_shared_data vmtest regtest timer # objdir diff --git a/reactos/apps/tests/bench/bench-thread.c b/reactos/apps/tests/bench/bench-thread.c index afdf278ea6f..ae17b2b963d 100644 --- a/reactos/apps/tests/bench/bench-thread.c +++ b/reactos/apps/tests/bench/bench-thread.c @@ -1,14 +1,14 @@ #include #include -#define NR_THREADS (0x1) +#define NR_THREADS (30) DWORD WINAPI thread_main1(LPVOID param) { printf("Thread 1 running (Counter %lu)\n", (DWORD)param); - + SleepEx(INFINITE, TRUE); return 0; } @@ -17,7 +17,7 @@ DWORD WINAPI thread_main2(LPVOID param) { printf("Thread 2 running (Counter %lu)\n", (DWORD)param); - + Sleep(INFINITE); return 0; } @@ -77,6 +77,6 @@ int main (void) printf("Thread terminated...\n"); #endif - + printf("Exiting\n"); return 0; } diff --git a/reactos/apps/tests/thread/thread.c b/reactos/apps/tests/thread/thread.c index 05921e96ca8..edb17e75f15 100644 --- a/reactos/apps/tests/thread/thread.c +++ b/reactos/apps/tests/thread/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.6 2000/01/31 20:24:27 ekohl Exp $ +/* $Id: thread.c,v 1.7 2001/02/06 00:11:17 dwelch Exp $ * * * @@ -48,12 +48,13 @@ int main (int argc, char* argv[]) // The user must supply one argument (the seed). if he/she doesn't // then we show the help. - if(argc < 2) { - showHelp(); - return 1; - } + // if(argc < 2) { + // showHelp(); + // return 1; + // } - nr = atoi(argv[1]); + // nr = atoi(argv[1]); + nr = 500; printf("Seed %ld\n", nr); printf("Creating %d threads...\n",NR_THREADS*2); diff --git a/reactos/include/ddk/cctypes.h b/reactos/include/ddk/cctypes.h index 5b84de75c0e..72cb3e1e6e0 100644 --- a/reactos/include/ddk/cctypes.h +++ b/reactos/include/ddk/cctypes.h @@ -75,7 +75,12 @@ typedef VOID (*PFLUSH_TO_LSN)(IN PVOID LogHandle, IN LARGE_INTEGER Lsn); typedef struct _REACTOS_COMMON_FCB_HEADER { + CSHORT NodeTypeCode; + CSHORT NodeByteSize; PBCB Bcb; + LARGE_INTEGER AllocationSize; + LARGE_INTEGER FileSize; + LARGE_INTEGER ValidDataLength; } REACTOS_COMMON_FCB_HEADER; #endif /* __INCLUDE_DDK_CCTYPES_H */ diff --git a/reactos/include/pe.h b/reactos/include/pe.h index 306302e41fd..3d74de8bd03 100644 --- a/reactos/include/pe.h +++ b/reactos/include/pe.h @@ -19,6 +19,7 @@ #define IMAGE_DOS_SIGNATURE 0x5a4d #define IMAGE_OS2_SIGNATURE 0x454e + #define IMAGE_OS2_SIGNATURE_LE 0x454c #define IMAGE_VXD_SIGNATURE 0x454c #define IMAGE_NT_SIGNATURE 0x00004550 diff --git a/reactos/install.sh b/reactos/install.sh index c8cc42e2364..48c765fcf35 100644 --- a/reactos/install.sh +++ b/reactos/install.sh @@ -41,4 +41,5 @@ cp apps/dump_shared_data/dump_shared_data.exe $1/reactos/bin cp apps/vmtest/vmtest.exe $1/reactos/bin cp apps/uitest/uitest.exe $1/reactos/bin/ cp apps/gditest/gditest.exe $1/reactos/bin/ -cp apps/ptest/ptest.exe $1/reactos/bin +cp apps/ptest/ptest.exe $1/reactos/bin/ +cp apps/timer/timer.exe $1/reactos/bin/ \ No newline at end of file diff --git a/reactos/lib/kernel32/process/proc.c b/reactos/lib/kernel32/process/proc.c index b770d65af5c..8833760f696 100644 --- a/reactos/lib/kernel32/process/proc.c +++ b/reactos/lib/kernel32/process/proc.c @@ -1,4 +1,4 @@ -/* $Id: proc.c,v 1.36 2000/12/28 20:38:27 ekohl Exp $ +/* $Id: proc.c,v 1.37 2001/02/06 00:11:18 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -284,25 +284,35 @@ Sleep ( } -DWORD -STDCALL -SleepEx ( - DWORD dwMilliseconds, - BOOL bAlertable - ) +DWORD STDCALL +SleepEx (DWORD dwMilliseconds, + BOOL bAlertable) { - TIME Interval; - NTSTATUS errCode; + TIME Interval; + NTSTATUS errCode; + + if (dwMilliseconds != INFINITE) + { + /* + * System time units are 100 nanoseconds (a nanosecond is a billionth of + * a second). + */ + Interval.QuadPart = dwMilliseconds; + Interval.QuadPart = -(Interval.QuadPart * 10000); + } + else + { + /* Approximately 292000 years hence */ + Interval.QuadPart = -0x7FFFFFFFFFFFFFFF; + } - Interval.QuadPart = dwMilliseconds * 1000; - - errCode = NtDelayExecution (bAlertable, & Interval); - if (!NT_SUCCESS(errCode)) - { - SetLastErrorByStatus (errCode); - return -1; - } - return 0; + errCode = NtDelayExecution (bAlertable, &Interval); + if (!NT_SUCCESS(errCode)) + { + SetLastErrorByStatus (errCode); + return -1; + } + return 0; } diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index fcd0d265d89..ff0191196e3 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -102,6 +102,8 @@ PULONG KeGetStackTopThread(struct _ETHREAD* Thread); VOID KeContextToTrapFrame(PCONTEXT Context, PKTRAP_FRAME TrapFrame); VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait); +VOID +KiDeliverNormalApc(VOID); BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc); diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index fffea5aff38..b0cf1a54a4c 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -24,7 +24,7 @@ typedef ULONG SWAPENTRY; #define MEMORY_AREA_SECTION_VIEW_RESERVE (9) #define MEMORY_AREA_CACHE_SEGMENT (10) #define MEMORY_AREA_SHARED_DATA (11) - +#define MEMORY_AREA_WORKING_SET (12) #define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \ ((x) / (4*1024*1024)) @@ -119,28 +119,23 @@ typedef struct } Data; } MEMORY_AREA, *PMEMORY_AREA; -#define WSET_ADDRESSES_IN_PAGE (1020) - -typedef struct _MWORKING_SET -{ - PVOID Address[WSET_ADDRESSES_IN_PAGE]; - struct _MWORKING_SET* Next; -} MWORKING_SET, *PMWORKING_SET; - typedef struct _MADDRESS_SPACE { - LIST_ENTRY MAreaListHead; - KMUTEX Lock; - ULONG LowestAddress; - struct _EPROCESS* Process; - ULONG WorkingSetSize; - ULONG WorkingSetLruFirst; - ULONG WorkingSetLruLast; - ULONG WorkingSetPagesAllocated; - PUSHORT PageTableRefCountTable; - ULONG PageTableRefCountTableSize; + LIST_ENTRY MAreaListHead; + KMUTEX Lock; + ULONG LowestAddress; + struct _EPROCESS* Process; + PMEMORY_AREA WorkingSetArea; + ULONG WorkingSetSize; + ULONG WorkingSetLruFirst; + ULONG WorkingSetLruLast; + ULONG WorkingSetPagesAllocated; + ULONG WorkingSetMaximumLength; + PUSHORT PageTableRefCountTable; + ULONG PageTableRefCountTableSize; } MADDRESS_SPACE, *PMADDRESS_SPACE; + /* FUNCTIONS */ VOID MmLockAddressSpace(PMADDRESS_SPACE AddressSpace); @@ -268,11 +263,12 @@ ULONG MmTrimWorkingSet(struct _EPROCESS* Process, ULONG ReduceHint); VOID MmRemovePageFromWorkingSet(struct _EPROCESS* Process, PVOID Address); -BOOLEAN MmAddPageToWorkingSet(struct _EPROCESS* Process, - PVOID Address); +VOID +MmAddPageToWorkingSet(struct _EPROCESS* Process, PVOID Address); VOID MmInitPagingFile(VOID); -VOID MmReserveSwapPages(ULONG Nr); +BOOLEAN +MmReserveSwapPages(ULONG Nr); VOID MmDereserveSwapPages(ULONG Nr); SWAPENTRY MmAllocSwapPage(VOID); VOID MmFreeSwapPage(SWAPENTRY Entry); diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index c7e8b31e064..6905c6d50fe 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -33,21 +33,6 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus); /* 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"); -} - VOID KiRundownThread(VOID) /* * FUNCTION: @@ -74,7 +59,51 @@ BOOLEAN KiTestAlert(VOID) return(TRUE); } -BOOLEAN KiDeliverUserApc(PKTRAP_FRAME TrapFrame) +VOID +KiDeliverNormalApc(VOID) +{ + PETHREAD Thread = PsGetCurrentThread(); + PLIST_ENTRY current; + PKAPC Apc; + KIRQL oldlvl; + PKNORMAL_ROUTINE NormalRoutine; + PVOID NormalContext; + PVOID SystemArgument1; + PVOID SystemArgument2; + + 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--; + } + } + KeReleaseSpinLock(&PiApcLock, oldlvl); +} + +BOOLEAN +KiDeliverUserApc(PKTRAP_FRAME TrapFrame) /* * FUNCTION: Tests whether there are any pending APCs for the current thread * and if so the APCs will be delivered on exit from kernel mode. @@ -205,17 +234,26 @@ VOID STDCALL KiDeliverApc(ULONG Unknown1, KeAcquireSpinLock(&PiApcLock, &oldlvl); while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) { - 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); - Thread->Tcb.ApcState.KernelApcInProgress--; + 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); + + Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); + Apc->KernelRoutine(Apc, + &Apc->NormalRoutine, + &Apc->NormalContext, + &Apc->SystemArgument1, + &Apc->SystemArgument2); + + KeAcquireSpinLock(&PiApcLock, &oldlvl); + Thread->Tcb.ApcState.KernelApcInProgress--; + } } KeReleaseSpinLock(&PiApcLock, oldlvl); } @@ -267,11 +305,23 @@ KeInsertQueueApc (PKAPC Apc, Apc->Inserted = TRUE; if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 && - TargetThread->WaitIrql < APC_LEVEL) + TargetThread->WaitIrql < APC_LEVEL && Apc->NormalRoutine == NULL) { KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), STATUS_KERNEL_APC); } + if (Apc->ApcMode == KernelMode && Apc->NormalRoutine != NULL) + { + TargetThread->Alerted[1] = 1; + if (TargetThread->Alertable == TRUE && + TargetThread->WaitMode == UserMode) + { + PETHREAD Thread; + + Thread = CONTAINING_RECORD(TargetThread, ETHREAD, Tcb); + KeRemoveAllWaitsThread(Thread, STATUS_USER_APC); + } + } /* * For user mode APCs if the thread is already waiting then we wait it diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index dec4dd5dc7b..ecaa2a0cf88 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.4 2001/01/18 15:00:08 dwelch Exp $ +/* $Id: irq.c,v 1.5 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -199,6 +199,13 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe) { PsDispatchThread(THREAD_STATE_RUNNABLE); } + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->Alerted[1] != 0 && + Trapframe->Cs != KERNEL_CS) + { + HalEndSystemInterrupt (APC_LEVEL, 0); + KiDeliverNormalApc(); + } } HalEndSystemInterrupt (old_level, 0); @@ -426,8 +433,7 @@ IoConnectInterrupt(PKINTERRUPT* InterruptObject, } -VOID -STDCALL +VOID STDCALL IoDisconnectInterrupt(PKINTERRUPT InterruptObject) /* * FUNCTION: Releases a drivers isr diff --git a/reactos/ntoskrnl/ke/i386/usercall.c b/reactos/ntoskrnl/ke/i386/usercall.c index 9ac361e943c..16068ea22e6 100644 --- a/reactos/ntoskrnl/ke/i386/usercall.c +++ b/reactos/ntoskrnl/ke/i386/usercall.c @@ -1,4 +1,4 @@ -/* $Id: usercall.c,v 1.18 2001/01/19 15:09:01 dwelch Exp $ +/* $Id: usercall.c,v 1.19 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -25,10 +25,6 @@ #include #include -/* GLOBALS *******************************************************************/ - -VOID PsTerminateCurrentThread(NTSTATUS ExitStatus); - /* FUNCTIONS *****************************************************************/ VOID KiSystemCallHook(ULONG Nr, ...) @@ -53,32 +49,14 @@ VOID KiSystemCallHook(ULONG Nr, ...) ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame) { - KIRQL oldIrql; - PETHREAD EThread; - extern KSPIN_LOCK PiThreadListLock; - - assert(KeGetCurrentIrql() == PASSIVE_LEVEL); - - /* - * Check if the current thread is terminating - */ - KeAcquireSpinLock(&PiThreadListLock, &oldIrql); - EThread = PsGetCurrentThread(); - if (EThread->DeadThread) + if (KeGetCurrentThread()->Alerted[1] != 0 && TrapFrame->Cs != KERNEL_CS) { - KeReleaseSpinLock(&PiThreadListLock, oldIrql); - PsTerminateCurrentThread(EThread->ExitStatus); + KiDeliverNormalApc(); } - else + if (KeGetCurrentThread()->Alerted[0] != 0 && TrapFrame->Cs != KERNEL_CS) { - KeReleaseSpinLock(&PiThreadListLock, oldIrql); + KiDeliverUserApc(TrapFrame); } - - if (KeGetCurrentThread()->Alerted[0] == 0 || TrapFrame->Cs == KERNEL_CS) - { - return(NtStatus); - } - KiDeliverUserApc(TrapFrame); return(NtStatus); } diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 57303a38a0f..8027f030613 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -38,6 +38,18 @@ extern VOID PiTimeoutThread(struct _KDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2); +VOID +PiSuspendThreadRundownRoutine(PKAPC Apc); +VOID +PiSuspendThreadKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2); +VOID +PiSuspendThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2); /* FUNCTIONS *****************************************************************/ @@ -141,7 +153,14 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) Thread->ApcQueueable = 0; Thread->AutoAlignment = 0; Thread->StackBase = KernelStack; - memset(&Thread->SuspendApc, 0, sizeof(KAPC)); + KeInitializeApc(&Thread->SuspendApc, + Thread, + 0, + PiSuspendThreadKernelRoutine, + PiSuspendThreadRundownRoutine, + PiSuspendThreadNormalRoutine, + KernelMode, + NULL); KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255); Thread->ThreadListEntry.Flink = NULL; Thread->ThreadListEntry.Blink = NULL; diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index e3928ac39f9..52d41ce462e 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.76 2001/01/18 16:54:22 ekohl Exp $ +/* $Id: main.c,v 1.77 2001/02/06 00:11:18 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -475,14 +475,6 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); KeInit1(); KeLowerIrql(DISPATCH_LEVEL); - - { - char tmpbuf[80]; - sprintf(tmpbuf,"system with %d/%d MB memory\n", - (unsigned int)(KeLoaderBlock.MemLower)/1024, - (unsigned int)(KeLoaderBlock.MemHigher)/1024); - HalDisplayString(tmpbuf); - } /* * Display version number and copyright/warranty message @@ -495,6 +487,19 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock) HalDisplayString("are welcome to change it and/or distribute copies of it " "under certain\n"); HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n"); + + /* + * Fail at runtime if someone has changed various structures without + * updating the offsets used for the assembler code + */ + assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK); + assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB); + assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK); + assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE); + assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME); + assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS); + assert(FIELD_OFFSET(KPROCESS, PageTableDirectory) == + KPROCESS_PAGE_TABLE_DIRECTORY); last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd; diff --git a/reactos/ntoskrnl/ke/timer.c b/reactos/ntoskrnl/ke/timer.c index c2b3478361f..6d3a1f1651a 100644 --- a/reactos/ntoskrnl/ke/timer.c +++ b/reactos/ntoskrnl/ke/timer.c @@ -1,4 +1,4 @@ -/* $Id: timer.c,v 1.37 2001/02/05 02:31:04 phreak Exp $ +/* $Id: timer.c,v 1.38 2001/02/06 00:11:18 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -119,8 +119,8 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval) DPRINT("KeAddThreadTimeout(Thread %x, Interval %x)\n",Thread,Interval); - KeInitializeTimer(&(Thread->Timer)); - KeSetTimer( &(Thread->Timer), *Interval, &Thread->TimerDpc ); + KeInitializeTimer(&Thread->Timer); + KeSetTimer(&Thread->Timer, *Interval, &Thread->TimerDpc); DPRINT("Thread->Timer.entry.Flink %x\n", Thread->Timer.TimerListEntry.Flink); @@ -136,10 +136,11 @@ NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable, LARGE_INTEGER Timeout; Timeout = *((PLARGE_INTEGER)Interval); - Timeout.QuadPart = -Timeout.QuadPart; DPRINT("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n", Alertable, Internal, Timeout); + DPRINT("Execution delay is %d/%d\n", + Timeout.u.Highpart, Timeout.u.LowPart); Status = KeDelayExecutionThread(UserMode, Alertable, &Timeout); return(Status); } @@ -161,9 +162,9 @@ KeDelayExecutionThread (KPROCESSOR_MODE WaitMode, { PKTHREAD CurrentThread = KeGetCurrentThread(); KeAddThreadTimeout(CurrentThread, Interval); - return (KeWaitForSingleObject(&(CurrentThread->Timer), + return (KeWaitForSingleObject(&CurrentThread->Timer, Executive, - KernelMode, + UserMode, Alertable, NULL)); } diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index c26391d75c4..6fc89ff4f48 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -280,6 +280,8 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress, InsertTailList(&FreePageListHead, &MmPageArray[i].ListEntry); } + MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + + MmStats.NrReservedPages + MmStats.NrUserPages; return((PVOID)LastKernelAddress); } diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 366412f0161..ee079b91cac 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -1,4 +1,4 @@ -/* $Id: page.c,v 1.17 2001/01/08 02:14:06 dwelch Exp $ +/* $Id: page.c,v 1.18 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -283,7 +283,7 @@ ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process, VOID MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage) /* - * FUNCTION: Delete a virtual mapping +` * FUNCTION: Delete a virtual mapping */ { PULONG Pte; diff --git a/reactos/ntoskrnl/mm/i386/pfault.c b/reactos/ntoskrnl/mm/i386/pfault.c index 36ccd5936d6..99feb83fee6 100644 --- a/reactos/ntoskrnl/mm/i386/pfault.c +++ b/reactos/ntoskrnl/mm/i386/pfault.c @@ -12,6 +12,9 @@ #include #include +#include +#include +#include #define NDEBUG #include @@ -54,7 +57,13 @@ NTSTATUS MmPageFault(ULONG Cs, { Status = MmNotPresentFault(Mode, Cr2); } - + + if (KeGetCurrentThread() != NULL && + KeGetCurrentThread()->Alerted[1] != 0 && + Cs != KERNEL_CS) + { + KiDeliverNormalApc(); + } if (!NT_SUCCESS(Status) && (Mode == KernelMode) && ((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) && ((*Eip) <= (ULONG)MmSafeCopyFromUserRestart)) diff --git a/reactos/ntoskrnl/mm/pagefile.c b/reactos/ntoskrnl/mm/pagefile.c index 436bb153f6e..f8efa10c77d 100644 --- a/reactos/ntoskrnl/mm/pagefile.c +++ b/reactos/ntoskrnl/mm/pagefile.c @@ -1,4 +1,4 @@ -/* $Id: pagefile.c,v 1.9 2001/01/13 18:38:09 dwelch Exp $ +/* $Id: pagefile.c,v 1.10 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -38,14 +38,32 @@ typedef struct _PAGINGFILE #define MAX_PAGING_FILES (32) +/* List of paging files, both used and free */ static PPAGINGFILE PagingFileList[MAX_PAGING_FILES]; +/* Lock for examining the list of paging files */ static KSPIN_LOCK PagingFileListLock; +/* Number of pages that are available for swapping */ static ULONG MiFreeSwapPages; +/* Number of pages that have been allocated for swapping */ static ULONG MiUsedSwapPages; +/* + * Number of pages that have been reserved for swapping but not yet allocated + */ static ULONG MiReservedSwapPages; +/* + * Ratio between reserved and available swap pages, e.g. setting this to five + * forces one swap page to be available for every five swap pages that are + * reserved. Setting this to zero turns off commit checking altogether. + */ #define MM_PAGEFILE_COMMIT_RATIO (1) +/* + * Number of pages that can be used for potentially swapable memory without + * pagefile space being reserved. The intention is that is allows smss + * to start up and create page files while ordinarily having a commit + * ratio of one. + */ #define MM_PAGEFILE_COMMIT_GRACE (256) #if 0 @@ -53,9 +71,11 @@ static PVOID MmCoreDumpPageFrame; static BYTE MmCoreDumpHeader[PAGESIZE]; #endif +/* + * Translate between a swap entry and a file and offset pair. + */ #define FILE_FROM_ENTRY(i) ((i) >> 24) #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1) - #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) || ((j) + 1)) /* FUNCTIONS *****************************************************************/ @@ -111,7 +131,8 @@ NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl) return(Status); } -VOID MmInitPagingFile(VOID) +VOID +MmInitPagingFile(VOID) { ULONG i; @@ -127,27 +148,38 @@ VOID MmInitPagingFile(VOID) } } -VOID MmReserveSwapPages(ULONG Nr) +BOOLEAN +MmReserveSwapPages(ULONG Nr) { KIRQL oldIrql; + ULONG MiAvailSwapPages; KeAcquireSpinLock(&PagingFileListLock, &oldIrql); + MiAvailSwapPages = + (MiFreeSwapPages * MM_PAGEFILE_COMMIT_RATIO) + MM_PAGEFILE_COMMIT_GRACE; + if (MM_PAGEFILE_COMMIT_RATIO != 0 && MiAvailSwapPages < MiReservedSwapPages) + { + KeReleaseSpinLock(&PagingFileListLock, oldIrql); + return(FALSE); + } MiReservedSwapPages = MiReservedSwapPages + Nr; -// MiFreeSwapPages = MiFreeSwapPages - Nr; KeReleaseSpinLock(&PagingFileListLock, oldIrql); + + return(TRUE); } -VOID MmDereserveSwapPages(ULONG Nr) +VOID +MmDereserveSwapPages(ULONG Nr) { KIRQL oldIrql; KeAcquireSpinLock(&PagingFileListLock, &oldIrql); MiReservedSwapPages = MiReservedSwapPages - Nr; -// MiFreeSwapPages = MiFreeSwapPages - Nr; KeReleaseSpinLock(&PagingFileListLock, oldIrql); } -ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) +static ULONG +MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) { KIRQL oldIrql; ULONG i; @@ -170,7 +202,8 @@ ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) return(0); } -VOID MmFreeSwapPage(SWAPENTRY Entry) +VOID +MmFreeSwapPage(SWAPENTRY Entry) { ULONG i; ULONG off; @@ -194,7 +227,8 @@ VOID MmFreeSwapPage(SWAPENTRY Entry) KeReleaseSpinLock(&PagingFileListLock, oldIrql); } -SWAPENTRY MmAllocSwapPage(VOID) +SWAPENTRY +MmAllocSwapPage(VOID) { KIRQL oldIrql; ULONG i; @@ -256,10 +290,11 @@ NTSTATUS STDCALL MmDumpToPagingFile(PCONTEXT Context, } #endif -NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING PageFileName, - IN ULONG MinimumSize, - IN ULONG MaximumSize, - OUT PULONG ActualSize) +NTSTATUS STDCALL +NtCreatePagingFile(IN PUNICODE_STRING PageFileName, + IN ULONG MinimumSize, + IN ULONG MaximumSize, + OUT PULONG ActualSize) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index adc31e0de71..a0344f10362 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -1,4 +1,4 @@ -/* $Id: section.c,v 1.43 2001/01/28 15:17:52 ekohl Exp $ +/* $Id: section.c,v 1.44 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -1135,7 +1135,7 @@ MmAllocateSection (IN ULONG Length) Length, 0, &marea); - if (!NT_SUCCESS(STATUS_SUCCESS)) + if (!NT_SUCCESS(Status)) { return (NULL); } diff --git a/reactos/ntoskrnl/mm/wset.c b/reactos/ntoskrnl/mm/wset.c index 67d9cfdd778..f30e6e38c6b 100644 --- a/reactos/ntoskrnl/mm/wset.c +++ b/reactos/ntoskrnl/mm/wset.c @@ -1,4 +1,4 @@ -/* $Id: wset.c,v 1.6 2001/01/08 02:14:06 dwelch Exp $ +/* $Id: wset.c,v 1.7 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -38,16 +39,55 @@ VOID MmUnlockWorkingSet(PEPROCESS Process) KeReleaseMutex(&Process->WorkingSetLock, FALSE); } -VOID MmInitializeWorkingSet(PEPROCESS Process, - PMADDRESS_SPACE AddressSpace) +VOID +MmInitializeWorkingSet(PEPROCESS Process, PMADDRESS_SPACE AddressSpace) { - AddressSpace->WorkingSetSize = 0; - AddressSpace->WorkingSetLruFirst = 0; - AddressSpace->WorkingSetLruLast = 0; - AddressSpace->WorkingSetPagesAllocated = 1; - KeInitializeMutex(&Process->WorkingSetLock, 1); - Process->WorkingSetPage = ExAllocatePage(); - memset(Process->WorkingSetPage, 0, 4096); + PVOID BaseAddress; + ULONG MaximumLength; + PVOID FirstPage; + NTSTATUS Status; + + /* + * The maximum number of pages in the working set is the maximum + * of the size of physical memory and the size of the user address space + */ + MaximumLength = MmStats.NrTotalPages - MmStats.NrReservedPages; + MaximumLength = min(MaximumLength, KERNEL_BASE / PAGESIZE); + MaximumLength = PAGE_ROUND_UP(MaximumLength * sizeof(ULONG)); + + FirstPage = MmAllocPageMaybeSwap(0); + if (FirstPage == NULL) + { + KeBugCheck(0); + } + + BaseAddress = 0; + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_WORKING_SET, + &BaseAddress, + MaximumLength, + 0, + &AddressSpace->WorkingSetArea); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + AddressSpace->WorkingSetSize = 0; + AddressSpace->WorkingSetLruFirst = 0; + AddressSpace->WorkingSetLruLast = 0; + AddressSpace->WorkingSetMaximumLength = MaximumLength; + KeInitializeMutex(&Process->WorkingSetLock, 1); + Process->WorkingSetPage = BaseAddress; + Status = MmCreateVirtualMapping(NULL, + Process->WorkingSetPage, + PAGE_READWRITE, + (ULONG)FirstPage); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + memset(Process->WorkingSetPage, 0, 4096); } ULONG MmPageOutPage(PMADDRESS_SPACE AddressSpace, @@ -87,13 +127,13 @@ ULONG MmTrimWorkingSet(PEPROCESS Process, { ULONG i, j; PMADDRESS_SPACE AddressSpace; - PMWORKING_SET WSet; + PVOID* WSet; ULONG Count; BOOLEAN Ul; MmLockWorkingSet(Process); - WSet = (PMWORKING_SET)Process->WorkingSetPage; + WSet = (PVOID*)Process->WorkingSetPage; AddressSpace = &Process->AddressSpace; Count = 0; @@ -104,7 +144,7 @@ ULONG MmTrimWorkingSet(PEPROCESS Process, PVOID Address; PMEMORY_AREA MArea; - Address = WSet->Address[j]; + Address = WSet[j]; MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address); @@ -124,7 +164,7 @@ ULONG MmTrimWorkingSet(PEPROCESS Process, } else { - j = (j + 1) % WSET_ADDRESSES_IN_PAGE; + j = (j + 1) % AddressSpace->WorkingSetMaximumLength; i++; } @@ -143,58 +183,93 @@ VOID MmRemovePageFromWorkingSet(PEPROCESS Process, { ULONG i; PMADDRESS_SPACE AddressSpace; - PMWORKING_SET WSet; + PVOID* WSet; ULONG j; - WSet = (PMWORKING_SET)Process->WorkingSetPage; + WSet = (PVOID*)Process->WorkingSetPage; AddressSpace = &Process->AddressSpace; j = AddressSpace->WorkingSetLruFirst; for (i = 0; i < AddressSpace->WorkingSetSize; i++) { - if (WSet->Address[j] == Address) + if (WSet[j] == Address) { - WSet->Address[j] = - WSet->Address[AddressSpace->WorkingSetLruLast - 1]; + WSet[j] = WSet[AddressSpace->WorkingSetLruLast - 1]; if (AddressSpace->WorkingSetLruLast != 0) { - AddressSpace->WorkingSetLruLast = - AddressSpace->WorkingSetLruLast --; + AddressSpace->WorkingSetLruLast--; } else { - AddressSpace->WorkingSetLruLast = WSET_ADDRESSES_IN_PAGE; + AddressSpace->WorkingSetLruLast = + AddressSpace->WorkingSetMaximumLength; } return; } - j = (j + 1) % WSET_ADDRESSES_IN_PAGE; + j = (j + 1) % AddressSpace->WorkingSetMaximumLength; } KeBugCheck(0); } -BOOLEAN MmAddPageToWorkingSet(PEPROCESS Process, - PVOID Address) +VOID +MmAddPageToWorkingSet(PEPROCESS Process, + PVOID Address) { - PMWORKING_SET WSet; + PVOID* WSet; PMADDRESS_SPACE AddressSpace; - + BOOLEAN Present; + ULONG Current; + PVOID NextAddress; + AddressSpace = &Process->AddressSpace; - if (((AddressSpace->WorkingSetLruLast + 1) % WSET_ADDRESSES_IN_PAGE) == - AddressSpace->WorkingSetLruFirst) + /* + * This can't happen unless there is a bug + */ + if (AddressSpace->WorkingSetSize == AddressSpace->WorkingSetMaximumLength) { - return(FALSE); + KeBugCheck(0); } - WSet = (PMWORKING_SET)Process->WorkingSetPage; + WSet = (PVOID*)Process->WorkingSetPage; - WSet->Address[AddressSpace->WorkingSetLruLast] = Address; + Current = AddressSpace->WorkingSetLruLast; - AddressSpace->WorkingSetLruLast = - (AddressSpace->WorkingSetLruLast + 1) % WSET_ADDRESSES_IN_PAGE; + /* + * If we are growing the working set then check to see if we need + * to allocate a page + */ + NextAddress = (PVOID)PAGE_ROUND_DOWN((PVOID)&WSet[Current]); + Present = MmIsPagePresent(NULL, NextAddress); + if (!Present) + { + PVOID Page; + NTSTATUS Status; + + Page = MmAllocPageMaybeSwap(0); + if (Page == 0) + { + KeBugCheck(0); + } + + Status = MmCreateVirtualMapping(NULL, + NextAddress, + PAGE_READWRITE, + (ULONG)Page); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(0); + } + } + + /* + * Insert the page in the working set + */ + WSet[Current] = Address; + + AddressSpace->WorkingSetLruLast = + (Current + 1) % AddressSpace->WorkingSetMaximumLength; AddressSpace->WorkingSetSize++; - - return(TRUE); } diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index 7e9de6e3741..1b48a6740ea 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -1,4 +1,4 @@ -/* $Id: handle.c,v 1.27 2001/02/02 20:46:36 ekohl Exp $ +/* $Id: handle.c,v 1.28 2001/02/06 00:11:19 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -595,7 +595,7 @@ NTSTATUS STDCALL NtClose(HANDLE Handle) ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle); if (ObjectBody == NULL) { - return(STATUS_HANDLES_CLOSED); + return(STATUS_INVALID_HANDLE); } Header = BODY_TO_HEADER(ObjectBody); diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index b427eb9c686..588628f3457 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -139,6 +139,30 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus) KeBugCheck(0); } +VOID +PiTerminateThreadRundownRoutine(PKAPC Apc) +{ + ExFreePool(Apc); +} + +VOID +PiTerminateThreadKernelRoutine(PKAPC Apc, + PKNORMAL_ROUTINE* NormalRoutine, + PVOID* NormalContext, + PVOID* SystemArgument1, + PVOID* SystemArguemnt2) +{ + ExFreePool(Apc); +} + +VOID +PiTerminateThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2) +{ + PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus); +} + VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus) /* @@ -146,22 +170,26 @@ PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus) * NOTES: This function must be called with PiThreadListLock held */ { - DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n", - Thread, ExitStatus); - - /* - * We must synchronize the termination of a thread with its execution - * so all this routine does is to mark the thread as terminated and - * wake it if possible. The thread will then kill itself when it - * next exits kernel mode. - */ - Thread->DeadThread = 1; - Thread->ExitStatus = ExitStatus; - if (Thread->Tcb.State == THREAD_STATE_FROZEN && - (Thread->Tcb.Alertable || Thread->Tcb.WaitMode == UserMode)) - { - KeRemoveAllWaitsThread(Thread, STATUS_ALERTED); - } + PKAPC Apc; + + DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n", + Thread, ExitStatus); + + Thread->DeadThread = 1; + Thread->ExitStatus = ExitStatus; + Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); + KeInitializeApc(Apc, + &Thread->Tcb, + 0, + PiTerminateThreadKernelRoutine, + PiTerminateThreadRundownRoutine, + PiTerminateThreadNormalRoutine, + KernelMode, + NULL); + KeInsertQueueApc(Apc, + NULL, + NULL, + KernelMode); } NTSTATUS STDCALL diff --git a/reactos/ntoskrnl/ps/suspend.c b/reactos/ntoskrnl/ps/suspend.c index 803b70322a6..4c6162c524e 100644 --- a/reactos/ntoskrnl/ps/suspend.c +++ b/reactos/ntoskrnl/ps/suspend.c @@ -1,4 +1,4 @@ -/* $Id: suspend.c,v 1.2 2001/01/21 14:54:30 dwelch Exp $ +/* $Id: suspend.c,v 1.3 2001/02/06 00:11:20 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -28,7 +28,6 @@ VOID PiSuspendThreadRundownRoutine(PKAPC Apc) { - ExFreePool(Apc); } VOID @@ -37,13 +36,19 @@ PiSuspendThreadKernelRoutine(PKAPC Apc, PVOID* NormalContext, PVOID* SystemArgument1, PVOID* SystemArguemnt2) +{ +} + +VOID +PiSuspendThreadNormalRoutine(PVOID NormalContext, + PVOID SystemArgument1, + PVOID SystemArgument2) { KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore, 0, UserMode, TRUE, NULL); - ExFreePool(Apc); } NTSTATUS @@ -56,45 +61,20 @@ PsResumeThread(PETHREAD Thread, PULONG SuspendCount) NTSTATUS PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount) { - PKAPC Apc; - NTSTATUS Status; + ULONG OldValue; - /* - * If we are suspending ourselves then we can cut out the work in - * sending an APC - */ - if (Thread == PsGetCurrentThread()) + OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount); + if (OldValue == 0) { - Status = KeWaitForSingleObject(&Thread->Tcb.SuspendSemaphore, - 0, - UserMode, - FALSE, - NULL); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - return(Status); + KeInsertQueueApc(&Thread->Tcb.SuspendApc, + NULL, + NULL, + 0); } - - Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); - if (Apc == NULL) + else { - return(STATUS_NO_MEMORY); + InterlockedDecrement(&Thread->Tcb.SuspendSemaphore.Header.SignalState); } - - KeInitializeApc(Apc, - &Thread->Tcb, - 0, - PiSuspendThreadKernelRoutine, - PiSuspendThreadRundownRoutine, - NULL, - KernelMode, - NULL); - KeInsertQueueApc(Apc, - NULL, - NULL, - 0); return(STATUS_SUCCESS); }