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
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

View file

@ -1,14 +1,14 @@
#include <stdio.h>
#include <windows.h>
#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;
}

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
// 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);

View file

@ -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 */

View file

@ -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

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/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/

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
* 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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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

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
* 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

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
* PROJECT: ReactOS kernel
@ -25,10 +25,6 @@
#include <ddk/defines.h>
#include <internal/ps.h>
/* 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);
}

View file

@ -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;

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
* 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;

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
* 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));
}

View file

@ -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);
}

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
* 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;

View file

@ -12,6 +12,9 @@
#include <ddk/ntddk.h>
#include <internal/mm.h>
#include <internal/ke.h>
#include <internal/i386/segment.h>
#include <internal/ps.h>
#define NDEBUG
#include <internal/debug.h>
@ -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))

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
* 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;

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
* 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);
}

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
* PROJECT: ReactOS kernel
@ -14,6 +14,7 @@
#include <ddk/ntddk.h>
#include <internal/mm.h>
#include <internal/ps.h>
#include <ntos/minmax.h>
#include <internal/debug.h>
@ -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);
}

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
* 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);

View file

@ -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

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
* 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);
}