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
This commit is contained in:
David Welch 2001-02-06 00:11:20 +00:00
parent ae6b859854
commit 076c1c6ac3
24 changed files with 440 additions and 236 deletions

View file

@ -56,7 +56,7 @@ NET_DEVICE_DRIVERS = ne2000
SYS_APPS = shell winlogon services SYS_APPS = shell winlogon services
APPS = args hello test cat bench apc shm lpc thread event file gditest \ 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 # objdir

View file

@ -1,14 +1,14 @@
#include <stdio.h> #include <stdio.h>
#include <windows.h> #include <windows.h>
#define NR_THREADS (0x1) #define NR_THREADS (30)
DWORD WINAPI DWORD WINAPI
thread_main1(LPVOID param) thread_main1(LPVOID param)
{ {
printf("Thread 1 running (Counter %lu)\n", (DWORD)param); printf("Thread 1 running (Counter %lu)\n", (DWORD)param);
SleepEx(INFINITE, TRUE);
return 0; return 0;
} }
@ -17,7 +17,7 @@ DWORD WINAPI
thread_main2(LPVOID param) thread_main2(LPVOID param)
{ {
printf("Thread 2 running (Counter %lu)\n", (DWORD)param); printf("Thread 2 running (Counter %lu)\n", (DWORD)param);
Sleep(INFINITE);
return 0; return 0;
} }
@ -77,6 +77,6 @@ int main (void)
printf("Thread terminated...\n"); printf("Thread terminated...\n");
#endif #endif
printf("Exiting\n");
return 0; return 0;
} }

View file

@ -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 // The user must supply one argument (the seed). if he/she doesn't
// then we show the help. // then we show the help.
if(argc < 2) { // if(argc < 2) {
showHelp(); // showHelp();
return 1; // return 1;
} // }
nr = atoi(argv[1]); // nr = atoi(argv[1]);
nr = 500;
printf("Seed %ld\n", nr); printf("Seed %ld\n", nr);
printf("Creating %d threads...\n",NR_THREADS*2); printf("Creating %d threads...\n",NR_THREADS*2);

View file

@ -75,7 +75,12 @@ typedef VOID (*PFLUSH_TO_LSN)(IN PVOID LogHandle, IN LARGE_INTEGER Lsn);
typedef struct _REACTOS_COMMON_FCB_HEADER typedef struct _REACTOS_COMMON_FCB_HEADER
{ {
CSHORT NodeTypeCode;
CSHORT NodeByteSize;
PBCB Bcb; PBCB Bcb;
LARGE_INTEGER AllocationSize;
LARGE_INTEGER FileSize;
LARGE_INTEGER ValidDataLength;
} REACTOS_COMMON_FCB_HEADER; } REACTOS_COMMON_FCB_HEADER;
#endif /* __INCLUDE_DDK_CCTYPES_H */ #endif /* __INCLUDE_DDK_CCTYPES_H */

View file

@ -19,6 +19,7 @@
#define IMAGE_DOS_SIGNATURE 0x5a4d #define IMAGE_DOS_SIGNATURE 0x5a4d
#define IMAGE_OS2_SIGNATURE 0x454e #define IMAGE_OS2_SIGNATURE 0x454e
#define IMAGE_OS2_SIGNATURE_LE 0x454c #define IMAGE_OS2_SIGNATURE_LE 0x454c
#define IMAGE_VXD_SIGNATURE 0x454c #define IMAGE_VXD_SIGNATURE 0x454c
#define IMAGE_NT_SIGNATURE 0x00004550 #define IMAGE_NT_SIGNATURE 0x00004550

View file

@ -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/vmtest/vmtest.exe $1/reactos/bin
cp apps/uitest/uitest.exe $1/reactos/bin/ cp apps/uitest/uitest.exe $1/reactos/bin/
cp apps/gditest/gditest.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/

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries * PROJECT: ReactOS system libraries
@ -284,25 +284,35 @@ Sleep (
} }
DWORD DWORD STDCALL
STDCALL SleepEx (DWORD dwMilliseconds,
SleepEx ( BOOL bAlertable)
DWORD dwMilliseconds,
BOOL bAlertable
)
{ {
TIME Interval; TIME Interval;
NTSTATUS errCode; 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))
errCode = NtDelayExecution (bAlertable, & Interval); {
if (!NT_SUCCESS(errCode)) SetLastErrorByStatus (errCode);
{ return -1;
SetLastErrorByStatus (errCode); }
return -1; return 0;
}
return 0;
} }

View file

@ -102,6 +102,8 @@ PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
VOID KeContextToTrapFrame(PCONTEXT Context, VOID KeContextToTrapFrame(PCONTEXT Context,
PKTRAP_FRAME TrapFrame); PKTRAP_FRAME TrapFrame);
VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait); VOID KeReleaseDispatcherDatabaseLockAtDpcLevel(BOOLEAN Wait);
VOID
KiDeliverNormalApc(VOID);
BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc); BOOLEAN STDCALL KeRemoveQueueApc (PKAPC Apc);

View file

@ -24,7 +24,7 @@ typedef ULONG SWAPENTRY;
#define MEMORY_AREA_SECTION_VIEW_RESERVE (9) #define MEMORY_AREA_SECTION_VIEW_RESERVE (9)
#define MEMORY_AREA_CACHE_SEGMENT (10) #define MEMORY_AREA_CACHE_SEGMENT (10)
#define MEMORY_AREA_SHARED_DATA (11) #define MEMORY_AREA_SHARED_DATA (11)
#define MEMORY_AREA_WORKING_SET (12)
#define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \ #define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \
((x) / (4*1024*1024)) ((x) / (4*1024*1024))
@ -119,28 +119,23 @@ typedef struct
} Data; } Data;
} MEMORY_AREA, *PMEMORY_AREA; } 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 typedef struct _MADDRESS_SPACE
{ {
LIST_ENTRY MAreaListHead; LIST_ENTRY MAreaListHead;
KMUTEX Lock; KMUTEX Lock;
ULONG LowestAddress; ULONG LowestAddress;
struct _EPROCESS* Process; struct _EPROCESS* Process;
ULONG WorkingSetSize; PMEMORY_AREA WorkingSetArea;
ULONG WorkingSetLruFirst; ULONG WorkingSetSize;
ULONG WorkingSetLruLast; ULONG WorkingSetLruFirst;
ULONG WorkingSetPagesAllocated; ULONG WorkingSetLruLast;
PUSHORT PageTableRefCountTable; ULONG WorkingSetPagesAllocated;
ULONG PageTableRefCountTableSize; ULONG WorkingSetMaximumLength;
PUSHORT PageTableRefCountTable;
ULONG PageTableRefCountTableSize;
} MADDRESS_SPACE, *PMADDRESS_SPACE; } MADDRESS_SPACE, *PMADDRESS_SPACE;
/* FUNCTIONS */ /* FUNCTIONS */
VOID MmLockAddressSpace(PMADDRESS_SPACE AddressSpace); VOID MmLockAddressSpace(PMADDRESS_SPACE AddressSpace);
@ -268,11 +263,12 @@ ULONG MmTrimWorkingSet(struct _EPROCESS* Process,
ULONG ReduceHint); ULONG ReduceHint);
VOID MmRemovePageFromWorkingSet(struct _EPROCESS* Process, VOID MmRemovePageFromWorkingSet(struct _EPROCESS* Process,
PVOID Address); PVOID Address);
BOOLEAN MmAddPageToWorkingSet(struct _EPROCESS* Process, VOID
PVOID Address); MmAddPageToWorkingSet(struct _EPROCESS* Process, PVOID Address);
VOID MmInitPagingFile(VOID); VOID MmInitPagingFile(VOID);
VOID MmReserveSwapPages(ULONG Nr); BOOLEAN
MmReserveSwapPages(ULONG Nr);
VOID MmDereserveSwapPages(ULONG Nr); VOID MmDereserveSwapPages(ULONG Nr);
SWAPENTRY MmAllocSwapPage(VOID); SWAPENTRY MmAllocSwapPage(VOID);
VOID MmFreeSwapPage(SWAPENTRY Entry); VOID MmFreeSwapPage(SWAPENTRY Entry);

View file

@ -33,21 +33,6 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
/* FUNCTIONS *****************************************************************/ /* 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) VOID KiRundownThread(VOID)
/* /*
* FUNCTION: * FUNCTION:
@ -74,7 +59,51 @@ BOOLEAN KiTestAlert(VOID)
return(TRUE); 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 * 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. * 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); KeAcquireSpinLock(&PiApcLock, &oldlvl);
while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0]))) while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
{ {
DPRINT("Delivering APC\n"); current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
current = RemoveTailList(&(Thread->Tcb.ApcState.ApcListHead[0])); Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
Thread->Tcb.ApcState.KernelApcInProgress++; if (Apc->NormalRoutine == NULL)
Thread->Tcb.ApcState.KernelApcPending--; {
KeReleaseSpinLock(&PiApcLock, oldlvl); (void)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
Thread->Tcb.ApcState.KernelApcInProgress++;
Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry); Thread->Tcb.ApcState.KernelApcPending--;
KeCallKernelRoutineApc(Apc);
KeReleaseSpinLock(&PiApcLock, oldlvl);
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Thread->Tcb.ApcState.KernelApcInProgress--; 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); KeReleaseSpinLock(&PiApcLock, oldlvl);
} }
@ -267,11 +305,23 @@ KeInsertQueueApc (PKAPC Apc,
Apc->Inserted = TRUE; Apc->Inserted = TRUE;
if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 && if (Apc->ApcMode == KernelMode && TargetThread->KernelApcDisable >= 1 &&
TargetThread->WaitIrql < APC_LEVEL) TargetThread->WaitIrql < APC_LEVEL && Apc->NormalRoutine == NULL)
{ {
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb), KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
STATUS_KERNEL_APC); 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 * For user mode APCs if the thread is already waiting then we wait it

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -199,6 +199,13 @@ KiInterruptDispatch (ULONG irq, PKIRQ_TRAPFRAME Trapframe)
{ {
PsDispatchThread(THREAD_STATE_RUNNABLE); PsDispatchThread(THREAD_STATE_RUNNABLE);
} }
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->Alerted[1] != 0 &&
Trapframe->Cs != KERNEL_CS)
{
HalEndSystemInterrupt (APC_LEVEL, 0);
KiDeliverNormalApc();
}
} }
HalEndSystemInterrupt (old_level, 0); HalEndSystemInterrupt (old_level, 0);
@ -426,8 +433,7 @@ IoConnectInterrupt(PKINTERRUPT* InterruptObject,
} }
VOID VOID STDCALL
STDCALL
IoDisconnectInterrupt(PKINTERRUPT InterruptObject) IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
/* /*
* FUNCTION: Releases a drivers isr * FUNCTION: Releases a drivers isr

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -25,10 +25,6 @@
#include <ddk/defines.h> #include <ddk/defines.h>
#include <internal/ps.h> #include <internal/ps.h>
/* GLOBALS *******************************************************************/
VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
VOID KiSystemCallHook(ULONG Nr, ...) VOID KiSystemCallHook(ULONG Nr, ...)
@ -53,32 +49,14 @@ VOID KiSystemCallHook(ULONG Nr, ...)
ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame) ULONG KiAfterSystemCallHook(ULONG NtStatus, PKTRAP_FRAME TrapFrame)
{ {
KIRQL oldIrql; if (KeGetCurrentThread()->Alerted[1] != 0 && TrapFrame->Cs != KERNEL_CS)
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)
{ {
KeReleaseSpinLock(&PiThreadListLock, oldIrql); KiDeliverNormalApc();
PsTerminateCurrentThread(EThread->ExitStatus);
} }
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); return(NtStatus);
} }

View file

@ -38,6 +38,18 @@
extern VOID extern VOID
PiTimeoutThread(struct _KDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2); 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 *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -141,7 +153,14 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
Thread->ApcQueueable = 0; Thread->ApcQueueable = 0;
Thread->AutoAlignment = 0; Thread->AutoAlignment = 0;
Thread->StackBase = KernelStack; Thread->StackBase = KernelStack;
memset(&Thread->SuspendApc, 0, sizeof(KAPC)); KeInitializeApc(&Thread->SuspendApc,
Thread,
0,
PiSuspendThreadKernelRoutine,
PiSuspendThreadRundownRoutine,
PiSuspendThreadNormalRoutine,
KernelMode,
NULL);
KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255); KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 255);
Thread->ThreadListEntry.Flink = NULL; Thread->ThreadListEntry.Flink = NULL;
Thread->ThreadListEntry.Blink = NULL; Thread->ThreadListEntry.Blink = NULL;

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -475,14 +475,6 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock); HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
KeInit1(); KeInit1();
KeLowerIrql(DISPATCH_LEVEL); 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 * 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 " HalDisplayString("are welcome to change it and/or distribute copies of it "
"under certain\n"); "under certain\n");
HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\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; last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -119,8 +119,8 @@ NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
DPRINT("KeAddThreadTimeout(Thread %x, Interval %x)\n",Thread,Interval); DPRINT("KeAddThreadTimeout(Thread %x, Interval %x)\n",Thread,Interval);
KeInitializeTimer(&(Thread->Timer)); KeInitializeTimer(&Thread->Timer);
KeSetTimer( &(Thread->Timer), *Interval, &Thread->TimerDpc ); KeSetTimer(&Thread->Timer, *Interval, &Thread->TimerDpc);
DPRINT("Thread->Timer.entry.Flink %x\n", DPRINT("Thread->Timer.entry.Flink %x\n",
Thread->Timer.TimerListEntry.Flink); Thread->Timer.TimerListEntry.Flink);
@ -136,10 +136,11 @@ NTSTATUS STDCALL NtDelayExecution(IN ULONG Alertable,
LARGE_INTEGER Timeout; LARGE_INTEGER Timeout;
Timeout = *((PLARGE_INTEGER)Interval); Timeout = *((PLARGE_INTEGER)Interval);
Timeout.QuadPart = -Timeout.QuadPart;
DPRINT("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n", DPRINT("NtDelayExecution(Alertable %d, Internal %x) IntervalP %x\n",
Alertable, Internal, Timeout); Alertable, Internal, Timeout);
DPRINT("Execution delay is %d/%d\n",
Timeout.u.Highpart, Timeout.u.LowPart);
Status = KeDelayExecutionThread(UserMode, Alertable, &Timeout); Status = KeDelayExecutionThread(UserMode, Alertable, &Timeout);
return(Status); return(Status);
} }
@ -161,9 +162,9 @@ KeDelayExecutionThread (KPROCESSOR_MODE WaitMode,
{ {
PKTHREAD CurrentThread = KeGetCurrentThread(); PKTHREAD CurrentThread = KeGetCurrentThread();
KeAddThreadTimeout(CurrentThread, Interval); KeAddThreadTimeout(CurrentThread, Interval);
return (KeWaitForSingleObject(&(CurrentThread->Timer), return (KeWaitForSingleObject(&CurrentThread->Timer,
Executive, Executive,
KernelMode, UserMode,
Alertable, Alertable,
NULL)); NULL));
} }

View file

@ -280,6 +280,8 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
InsertTailList(&FreePageListHead, InsertTailList(&FreePageListHead,
&MmPageArray[i].ListEntry); &MmPageArray[i].ListEntry);
} }
MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages +
MmStats.NrReservedPages + MmStats.NrUserPages;
return((PVOID)LastKernelAddress); return((PVOID)LastKernelAddress);
} }

View file

@ -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 * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -283,7 +283,7 @@ ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process,
VOID MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage) VOID MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage)
/* /*
* FUNCTION: Delete a virtual mapping ` * FUNCTION: Delete a virtual mapping
*/ */
{ {
PULONG Pte; PULONG Pte;

View file

@ -12,6 +12,9 @@
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <internal/mm.h> #include <internal/mm.h>
#include <internal/ke.h>
#include <internal/i386/segment.h>
#include <internal/ps.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
@ -54,7 +57,13 @@ NTSTATUS MmPageFault(ULONG Cs,
{ {
Status = MmNotPresentFault(Mode, Cr2); Status = MmNotPresentFault(Mode, Cr2);
} }
if (KeGetCurrentThread() != NULL &&
KeGetCurrentThread()->Alerted[1] != 0 &&
Cs != KERNEL_CS)
{
KiDeliverNormalApc();
}
if (!NT_SUCCESS(Status) && (Mode == KernelMode) && if (!NT_SUCCESS(Status) && (Mode == KernelMode) &&
((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) && ((*Eip) >= (ULONG)MmSafeCopyFromUserUnsafeStart) &&
((*Eip) <= (ULONG)MmSafeCopyFromUserRestart)) ((*Eip) <= (ULONG)MmSafeCopyFromUserRestart))

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -38,14 +38,32 @@ typedef struct _PAGINGFILE
#define MAX_PAGING_FILES (32) #define MAX_PAGING_FILES (32)
/* List of paging files, both used and free */
static PPAGINGFILE PagingFileList[MAX_PAGING_FILES]; static PPAGINGFILE PagingFileList[MAX_PAGING_FILES];
/* Lock for examining the list of paging files */
static KSPIN_LOCK PagingFileListLock; static KSPIN_LOCK PagingFileListLock;
/* Number of pages that are available for swapping */
static ULONG MiFreeSwapPages; static ULONG MiFreeSwapPages;
/* Number of pages that have been allocated for swapping */
static ULONG MiUsedSwapPages; static ULONG MiUsedSwapPages;
/*
* Number of pages that have been reserved for swapping but not yet allocated
*/
static ULONG MiReservedSwapPages; 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) #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) #define MM_PAGEFILE_COMMIT_GRACE (256)
#if 0 #if 0
@ -53,9 +71,11 @@ static PVOID MmCoreDumpPageFrame;
static BYTE MmCoreDumpHeader[PAGESIZE]; static BYTE MmCoreDumpHeader[PAGESIZE];
#endif #endif
/*
* Translate between a swap entry and a file and offset pair.
*/
#define FILE_FROM_ENTRY(i) ((i) >> 24) #define FILE_FROM_ENTRY(i) ((i) >> 24)
#define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1) #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
#define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) || ((j) + 1)) #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) || ((j) + 1))
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -111,7 +131,8 @@ NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl)
return(Status); return(Status);
} }
VOID MmInitPagingFile(VOID) VOID
MmInitPagingFile(VOID)
{ {
ULONG i; ULONG i;
@ -127,27 +148,38 @@ VOID MmInitPagingFile(VOID)
} }
} }
VOID MmReserveSwapPages(ULONG Nr) BOOLEAN
MmReserveSwapPages(ULONG Nr)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG MiAvailSwapPages;
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); 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; MiReservedSwapPages = MiReservedSwapPages + Nr;
// MiFreeSwapPages = MiFreeSwapPages - Nr;
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
return(TRUE);
} }
VOID MmDereserveSwapPages(ULONG Nr) VOID
MmDereserveSwapPages(ULONG Nr)
{ {
KIRQL oldIrql; KIRQL oldIrql;
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
MiReservedSwapPages = MiReservedSwapPages - Nr; MiReservedSwapPages = MiReservedSwapPages - Nr;
// MiFreeSwapPages = MiFreeSwapPages - Nr;
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
} }
ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile) static ULONG
MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG i; ULONG i;
@ -170,7 +202,8 @@ ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
return(0); return(0);
} }
VOID MmFreeSwapPage(SWAPENTRY Entry) VOID
MmFreeSwapPage(SWAPENTRY Entry)
{ {
ULONG i; ULONG i;
ULONG off; ULONG off;
@ -194,7 +227,8 @@ VOID MmFreeSwapPage(SWAPENTRY Entry)
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
} }
SWAPENTRY MmAllocSwapPage(VOID) SWAPENTRY
MmAllocSwapPage(VOID)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG i; ULONG i;
@ -256,10 +290,11 @@ NTSTATUS STDCALL MmDumpToPagingFile(PCONTEXT Context,
} }
#endif #endif
NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING PageFileName, NTSTATUS STDCALL
IN ULONG MinimumSize, NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
IN ULONG MaximumSize, IN ULONG MinimumSize,
OUT PULONG ActualSize) IN ULONG MaximumSize,
OUT PULONG ActualSize)
{ {
NTSTATUS Status; NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -1135,7 +1135,7 @@ MmAllocateSection (IN ULONG Length)
Length, Length,
0, 0,
&marea); &marea);
if (!NT_SUCCESS(STATUS_SUCCESS)) if (!NT_SUCCESS(Status))
{ {
return (NULL); return (NULL);
} }

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -14,6 +14,7 @@
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
#include <internal/mm.h> #include <internal/mm.h>
#include <internal/ps.h> #include <internal/ps.h>
#include <ntos/minmax.h>
#include <internal/debug.h> #include <internal/debug.h>
@ -38,16 +39,55 @@ VOID MmUnlockWorkingSet(PEPROCESS Process)
KeReleaseMutex(&Process->WorkingSetLock, FALSE); KeReleaseMutex(&Process->WorkingSetLock, FALSE);
} }
VOID MmInitializeWorkingSet(PEPROCESS Process, VOID
PMADDRESS_SPACE AddressSpace) MmInitializeWorkingSet(PEPROCESS Process, PMADDRESS_SPACE AddressSpace)
{ {
AddressSpace->WorkingSetSize = 0; PVOID BaseAddress;
AddressSpace->WorkingSetLruFirst = 0; ULONG MaximumLength;
AddressSpace->WorkingSetLruLast = 0; PVOID FirstPage;
AddressSpace->WorkingSetPagesAllocated = 1; NTSTATUS Status;
KeInitializeMutex(&Process->WorkingSetLock, 1);
Process->WorkingSetPage = ExAllocatePage(); /*
memset(Process->WorkingSetPage, 0, 4096); * 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, ULONG MmPageOutPage(PMADDRESS_SPACE AddressSpace,
@ -87,13 +127,13 @@ ULONG MmTrimWorkingSet(PEPROCESS Process,
{ {
ULONG i, j; ULONG i, j;
PMADDRESS_SPACE AddressSpace; PMADDRESS_SPACE AddressSpace;
PMWORKING_SET WSet; PVOID* WSet;
ULONG Count; ULONG Count;
BOOLEAN Ul; BOOLEAN Ul;
MmLockWorkingSet(Process); MmLockWorkingSet(Process);
WSet = (PMWORKING_SET)Process->WorkingSetPage; WSet = (PVOID*)Process->WorkingSetPage;
AddressSpace = &Process->AddressSpace; AddressSpace = &Process->AddressSpace;
Count = 0; Count = 0;
@ -104,7 +144,7 @@ ULONG MmTrimWorkingSet(PEPROCESS Process,
PVOID Address; PVOID Address;
PMEMORY_AREA MArea; PMEMORY_AREA MArea;
Address = WSet->Address[j]; Address = WSet[j];
MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address); MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address);
@ -124,7 +164,7 @@ ULONG MmTrimWorkingSet(PEPROCESS Process,
} }
else else
{ {
j = (j + 1) % WSET_ADDRESSES_IN_PAGE; j = (j + 1) % AddressSpace->WorkingSetMaximumLength;
i++; i++;
} }
@ -143,58 +183,93 @@ VOID MmRemovePageFromWorkingSet(PEPROCESS Process,
{ {
ULONG i; ULONG i;
PMADDRESS_SPACE AddressSpace; PMADDRESS_SPACE AddressSpace;
PMWORKING_SET WSet; PVOID* WSet;
ULONG j; ULONG j;
WSet = (PMWORKING_SET)Process->WorkingSetPage; WSet = (PVOID*)Process->WorkingSetPage;
AddressSpace = &Process->AddressSpace; AddressSpace = &Process->AddressSpace;
j = AddressSpace->WorkingSetLruFirst; j = AddressSpace->WorkingSetLruFirst;
for (i = 0; i < AddressSpace->WorkingSetSize; i++) for (i = 0; i < AddressSpace->WorkingSetSize; i++)
{ {
if (WSet->Address[j] == Address) if (WSet[j] == Address)
{ {
WSet->Address[j] = WSet[j] = WSet[AddressSpace->WorkingSetLruLast - 1];
WSet->Address[AddressSpace->WorkingSetLruLast - 1];
if (AddressSpace->WorkingSetLruLast != 0) if (AddressSpace->WorkingSetLruLast != 0)
{ {
AddressSpace->WorkingSetLruLast = AddressSpace->WorkingSetLruLast--;
AddressSpace->WorkingSetLruLast --;
} }
else else
{ {
AddressSpace->WorkingSetLruLast = WSET_ADDRESSES_IN_PAGE; AddressSpace->WorkingSetLruLast =
AddressSpace->WorkingSetMaximumLength;
} }
return; return;
} }
j = (j + 1) % WSET_ADDRESSES_IN_PAGE; j = (j + 1) % AddressSpace->WorkingSetMaximumLength;
} }
KeBugCheck(0); KeBugCheck(0);
} }
BOOLEAN MmAddPageToWorkingSet(PEPROCESS Process, VOID
PVOID Address) MmAddPageToWorkingSet(PEPROCESS Process,
PVOID Address)
{ {
PMWORKING_SET WSet; PVOID* WSet;
PMADDRESS_SPACE AddressSpace; PMADDRESS_SPACE AddressSpace;
BOOLEAN Present;
ULONG Current;
PVOID NextAddress;
AddressSpace = &Process->AddressSpace; 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++; AddressSpace->WorkingSetSize++;
return(TRUE);
} }

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -595,7 +595,7 @@ NTSTATUS STDCALL NtClose(HANDLE Handle)
ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle); ObjectBody = ObDeleteHandle(PsGetCurrentProcess(), Handle);
if (ObjectBody == NULL) if (ObjectBody == NULL)
{ {
return(STATUS_HANDLES_CLOSED); return(STATUS_INVALID_HANDLE);
} }
Header = BODY_TO_HEADER(ObjectBody); Header = BODY_TO_HEADER(ObjectBody);

View file

@ -139,6 +139,30 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
KeBugCheck(0); 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 VOID
PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus) PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
/* /*
@ -146,22 +170,26 @@ PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
* NOTES: This function must be called with PiThreadListLock held * NOTES: This function must be called with PiThreadListLock held
*/ */
{ {
DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n", PKAPC Apc;
Thread, ExitStatus);
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 Thread->DeadThread = 1;
* wake it if possible. The thread will then kill itself when it Thread->ExitStatus = ExitStatus;
* next exits kernel mode. Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
*/ KeInitializeApc(Apc,
Thread->DeadThread = 1; &Thread->Tcb,
Thread->ExitStatus = ExitStatus; 0,
if (Thread->Tcb.State == THREAD_STATE_FROZEN && PiTerminateThreadKernelRoutine,
(Thread->Tcb.Alertable || Thread->Tcb.WaitMode == UserMode)) PiTerminateThreadRundownRoutine,
{ PiTerminateThreadNormalRoutine,
KeRemoveAllWaitsThread(Thread, STATUS_ALERTED); KernelMode,
} NULL);
KeInsertQueueApc(Apc,
NULL,
NULL,
KernelMode);
} }
NTSTATUS STDCALL NTSTATUS STDCALL

View file

@ -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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -28,7 +28,6 @@
VOID VOID
PiSuspendThreadRundownRoutine(PKAPC Apc) PiSuspendThreadRundownRoutine(PKAPC Apc)
{ {
ExFreePool(Apc);
} }
VOID VOID
@ -37,13 +36,19 @@ PiSuspendThreadKernelRoutine(PKAPC Apc,
PVOID* NormalContext, PVOID* NormalContext,
PVOID* SystemArgument1, PVOID* SystemArgument1,
PVOID* SystemArguemnt2) PVOID* SystemArguemnt2)
{
}
VOID
PiSuspendThreadNormalRoutine(PVOID NormalContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{ {
KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore, KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore,
0, 0,
UserMode, UserMode,
TRUE, TRUE,
NULL); NULL);
ExFreePool(Apc);
} }
NTSTATUS NTSTATUS
@ -56,45 +61,20 @@ PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
NTSTATUS NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount) PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
{ {
PKAPC Apc; ULONG OldValue;
NTSTATUS Status;
/* OldValue = InterlockedIncrement((PULONG)&Thread->Tcb.SuspendCount);
* If we are suspending ourselves then we can cut out the work in if (OldValue == 0)
* sending an APC
*/
if (Thread == PsGetCurrentThread())
{ {
Status = KeWaitForSingleObject(&Thread->Tcb.SuspendSemaphore, KeInsertQueueApc(&Thread->Tcb.SuspendApc,
0, NULL,
UserMode, NULL,
FALSE, 0);
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
return(Status);
} }
else
Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (Apc == NULL)
{ {
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); return(STATUS_SUCCESS);
} }