From d26222f31096dd2f76496c38aadd472bfd716fb4 Mon Sep 17 00:00:00 2001 From: David Welch Date: Thu, 6 Jul 2000 14:34:52 +0000 Subject: [PATCH] Added experimental paging out code (wouldn't activate until the system is out of memory) Added stress test application (consumes memory) Corrected mutex implementation Moved csrss startup into kernel32 to avoid ugly messages on startup svn path=/trunk/; revision=1229 --- reactos/Makefile | 4 +- reactos/apps/tests/consume/Makefile | 39 +++ reactos/apps/tests/consume/consume.c | 29 ++ reactos/install.sh | 1 + reactos/lib/kernel32/misc/dllmain.c | 12 +- reactos/lib/ntdll/def/ntdll.def | 4 +- reactos/lib/ntdll/def/ntdll.edf | 4 +- reactos/lib/ntdll/ldr/startup.c | 12 +- reactos/ntoskrnl/ex/fmutex.c | 28 +- reactos/ntoskrnl/include/internal/ke.h | 3 + reactos/ntoskrnl/include/internal/mm.h | 13 +- reactos/ntoskrnl/ke/event.c | 2 +- reactos/ntoskrnl/ke/i386/exp.c | 111 ++----- reactos/ntoskrnl/ke/i386/trap.s | 436 ++++++++++++++++++++++++- reactos/ntoskrnl/ke/mutex.c | 46 +-- reactos/ntoskrnl/ke/wait.c | 24 +- reactos/ntoskrnl/mm/freelist.c | 41 ++- reactos/ntoskrnl/mm/i386/page.c | 76 ++++- reactos/ntoskrnl/mm/marea.c | 5 +- reactos/ntoskrnl/mm/mdl.c | 16 +- reactos/ntoskrnl/mm/pager.c | 56 +++- reactos/ntoskrnl/mm/section.c | 261 +++++++++------ reactos/ntoskrnl/mm/virtual.c | 73 ++++- reactos/ntoskrnl/mm/wset.c | 85 +++-- reactos/ntoskrnl/ps/process.c | 17 +- reactos/ntoskrnl/ps/thread.c | 7 +- reactos/subsys/csrss/api/conio.c | 8 +- 27 files changed, 1070 insertions(+), 343 deletions(-) create mode 100644 reactos/apps/tests/consume/Makefile create mode 100644 reactos/apps/tests/consume/consume.c diff --git a/reactos/Makefile b/reactos/Makefile index 0dd58f39a28..31245fc3e11 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -41,7 +41,7 @@ FS_DRIVERS = vfat minix KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) APPS = args hello shell test cat bench apc shm lpc thread event file gditest \ - pteb + pteb consume # objdir @@ -298,4 +298,4 @@ endif # # etags: - find . -name "*.[ch]" -print | etags --language=c - \ No newline at end of file + find . -name "*.[ch]" -print | etags --language=c - diff --git a/reactos/apps/tests/consume/Makefile b/reactos/apps/tests/consume/Makefile new file mode 100644 index 00000000000..215ce75e571 --- /dev/null +++ b/reactos/apps/tests/consume/Makefile @@ -0,0 +1,39 @@ +# +# +# +OBJECTS = consume.o +PROGS = consume.exe +LIBS = +CLEAN_FILES = consume.o consume.exe + +all: consume.exe + +clean: $(CLEAN_FILES:%=%_clean) + +$(CLEAN_FILES:%=%_clean): %_clean: + - $(RM) $* + +.phony: clean $(CLEAN_FILES:%=%_clean) + +floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%) + +$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: % +ifeq ($(DOSCLI),yes) + $(CP) $* $(FLOPPY_DIR)\apps\$* +else + $(CP) $* $(FLOPPY_DIR)/apps/$* +endif + +dist: $(PROGS:%=../../$(DIST_DIR)/apps/%) + +$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: % +ifeq ($(DOSCLI),yes) + $(CP) $* ..\..\$(DIST_DIR)\apps\$* +else + $(CP) $* ../../$(DIST_DIR)/apps/$* +endif + +consume.exe: $(OBJECTS) + $(CC) $(OBJECTS) -o consume.exe + +include ../../rules.mak diff --git a/reactos/apps/tests/consume/consume.c b/reactos/apps/tests/consume/consume.c new file mode 100644 index 00000000000..05123742574 --- /dev/null +++ b/reactos/apps/tests/consume/consume.c @@ -0,0 +1,29 @@ +#include +#include +#include + +ULONG x[(4 * 1024 * 1024) / 4096]; + +int main() +{ + int i; + PUCHAR BaseAddress; + + BaseAddress = VirtualAlloc(NULL, + 4 * 1024 * 1024, + MEM_COMMIT, + PAGE_READONLY); + if (BaseAddress == NULL) + { + printf("Failed to allocate virtual memory"); + return(1); + } + printf("BaseAddress %p\n", BaseAddress); + for (i = 0; i < ((4 * 1024 * 1024) / 4096); i++) + { + printf("%.6x, ", i*4096); + x[i] = BaseAddress[i*4096]; + } + + return(0); +} diff --git a/reactos/install.sh b/reactos/install.sh index 21c8ebc5a8e..cc4de466e76 100644 --- a/reactos/install.sh +++ b/reactos/install.sh @@ -26,3 +26,4 @@ cp apps/thread/thread.exe $1/reactos/bin cp apps/event/event.exe $1/reactos/bin cp apps/file/file.exe $1/reactos/bin cp apps/pteb/pteb.exe $1/reactos/bin +cp apps/consume/consume.exe $1/reactos/bin diff --git a/reactos/lib/kernel32/misc/dllmain.c b/reactos/lib/kernel32/misc/dllmain.c index f1ae41b6fc1..ee5e9a747bd 100644 --- a/reactos/lib/kernel32/misc/dllmain.c +++ b/reactos/lib/kernel32/misc/dllmain.c @@ -1,4 +1,4 @@ -/* $Id: dllmain.c,v 1.11 2000/03/22 18:35:47 dwelch Exp $ +/* $Id: dllmain.c,v 1.12 2000/07/06 14:34:48 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS system libraries @@ -40,7 +40,17 @@ WINBOOL STDCALL DllMain(HANDLE hInst, case DLL_PROCESS_ATTACH: { NTSTATUS Status; + DPRINT("DLL_PROCESS_ATTACH\n"); + /* + * Connect to the csrss server + */ + Status = CsrClientConnectToServer(); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to connect to csrss.exe: expect trouble\n"); + // ZwTerminateProcess(NtCurrentProcess(), Status); + } break; } case DLL_PROCESS_DETACH: diff --git a/reactos/lib/ntdll/def/ntdll.def b/reactos/lib/ntdll/def/ntdll.def index 77c39a8174b..c3a5a37e612 100644 --- a/reactos/lib/ntdll/def/ntdll.def +++ b/reactos/lib/ntdll/def/ntdll.def @@ -1,4 +1,4 @@ -; $Id: ntdll.def,v 1.56 2000/07/01 17:06:22 ea Exp $ +; $Id: ntdll.def,v 1.57 2000/07/06 14:34:48 dwelch Exp $ ; ; ReactOS Operating System ; @@ -12,7 +12,7 @@ EXPORTS ;CsrCaptureMessageString ;CsrCaptureTimeout CsrClientCallServer@16 -;CsrClientConnectToServer@24 +CsrClientConnectToServer@0 ;CsrFreeCaptureBuffer ;CsrIdentifyAlertableThread ;CrsNewThread diff --git a/reactos/lib/ntdll/def/ntdll.edf b/reactos/lib/ntdll/def/ntdll.edf index 1060ea0bfc4..e560627a2a2 100644 --- a/reactos/lib/ntdll/def/ntdll.edf +++ b/reactos/lib/ntdll/def/ntdll.edf @@ -1,4 +1,4 @@ -; $Id: ntdll.edf,v 1.45 2000/07/01 17:06:22 ea Exp $ +; $Id: ntdll.edf,v 1.46 2000/07/06 14:34:48 dwelch Exp $ ; ; ReactOS Operating System ; @@ -12,7 +12,7 @@ EXPORTS ;CsrCaptureMessageString ;CsrCaptureTimeout CsrClientCallServer=CsrClientCallServer@16 -;CsrClientConnectToServer=CsrClientConnectToServer@24 +CsrClientConnectToServer=CsrClientConnectToServer@0 ;CsrFreeCaptureBuffer ;CsrIdentifyAlertableThread ;CrsNewThread diff --git a/reactos/lib/ntdll/ldr/startup.c b/reactos/lib/ntdll/ldr/startup.c index 6aef5a72d51..ed55f0184d0 100644 --- a/reactos/lib/ntdll/ldr/startup.c +++ b/reactos/lib/ntdll/ldr/startup.c @@ -1,4 +1,4 @@ -/* $Id: startup.c,v 1.25 2000/05/27 12:48:59 dwelch Exp $ +/* $Id: startup.c,v 1.26 2000/07/06 14:34:49 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -120,16 +120,6 @@ VOID LdrStartup(VOID) DbgPrint("Failed to initialize image\n"); ZwTerminateProcess(NtCurrentProcess(),STATUS_UNSUCCESSFUL); } - - /* - * Connect to the csrss server - */ - Status = CsrClientConnectToServer(); - if (!NT_SUCCESS(Status)) - { - DbgPrint("Failed to connect to csrss.exe: expect trouble\n"); -// ZwTerminateProcess(NtCurrentProcess(), Status); - } DbgPrint("Transferring control to image at %x\n",EntryPoint); Status = EntryPoint(Peb); diff --git a/reactos/ntoskrnl/ex/fmutex.c b/reactos/ntoskrnl/ex/fmutex.c index dbec6579c51..13e44a41b81 100644 --- a/reactos/ntoskrnl/ex/fmutex.c +++ b/reactos/ntoskrnl/ex/fmutex.c @@ -1,4 +1,4 @@ -/* $Id: fmutex.c,v 1.6 2000/06/09 20:02:59 ekohl Exp $ +/* $Id: fmutex.c,v 1.7 2000/07/06 14:34:49 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -18,40 +18,30 @@ /* FUNCTIONS *****************************************************************/ -VOID -FASTCALL -EXPORTED -ExAcquireFastMutexUnsafe ( - PFAST_MUTEX FastMutex - ) +VOID FASTCALL EXPORTED ExAcquireFastMutexUnsafe (PFAST_MUTEX FastMutex) { - if (InterlockedDecrement(&(FastMutex->Count))==0) + if (InterlockedDecrement(&FastMutex->Count) == 0) { return; } FastMutex->Contention++; - KeWaitForSingleObject(&(FastMutex->Event), + KeWaitForSingleObject(&FastMutex->Event, Executive, KernelMode, FALSE, NULL); - FastMutex->Owner=KeGetCurrentThread(); + FastMutex->Owner = KeGetCurrentThread(); } -VOID -FASTCALL -EXPORTED -ExReleaseFastMutexUnsafe ( - PFAST_MUTEX FastMutex - ) +VOID FASTCALL EXPORTED ExReleaseFastMutexUnsafe (PFAST_MUTEX FastMutex) { assert(FastMutex->Owner == KeGetCurrentThread()); - FastMutex->Owner=NULL; - if (InterlockedIncrement(&(FastMutex->Count))<=0) + FastMutex->Owner = NULL; + if (InterlockedIncrement(&FastMutex->Count) <= 0) { return; } - KeSetEvent(&(FastMutex->Event),0,FALSE); + KeSetEvent(&FastMutex->Event, 0, FALSE); } /* EOF */ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 03b99751bee..4ebb63e1aec 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -85,6 +85,9 @@ BOOLEAN KiTestAlert(struct _KTHREAD* Thread, PCONTEXT UserContext); VOID KeCallApcsThread(VOID); VOID KeRemoveAllWaitsThread(struct _ETHREAD* Thread, NTSTATUS WaitStatus); PULONG KeGetStackTopThread(struct _ETHREAD* Thread); +LONG STDCALL KePulseEvent (PKEVENT Event, + KPRIORITY Increment, + BOOLEAN Wait); /* INITIALIZATION FUNCTIONS *************************************************/ diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 4b7ce9147ad..579084f0f0a 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -162,7 +162,7 @@ VOID MmDeletePageEntry(struct _EPROCESS* Process, PVOID Address, BOOL FreePage); -VOID MmBuildMdlFromPages(PMDL Mdl); +VOID MmBuildMdlFromPages(PMDL Mdl, PULONG Pages); PVOID MmGetMdlPageAddress(PMDL Mdl, PVOID Offset); VOID MiShutdownMemoryManager(VOID); ULONG MmGetPhysicalAddressForProcess(struct _EPROCESS* Process, @@ -210,10 +210,12 @@ BOOLEAN MmIsPageDirty(struct _EPROCESS* Process, PVOID Address); BOOLEAN MmIsPageTablePresent(PVOID PAddress); ULONG MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, MEMORY_AREA* MemoryArea, - PVOID Address); + PVOID Address, + PBOOLEAN Ul); ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, PMEMORY_AREA MemoryArea, - PVOID Address); + PVOID Address, + PBOOLEAN Ul); MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, PVOID Address, ULONG Length); @@ -246,4 +248,9 @@ NTSTATUS MmInitPagerThread(VOID); VOID MmInitKernelMap(PVOID BaseAddress); unsigned int alloc_pool_region(unsigned int nr_pages); +VOID MmWaitForFreePages(VOID); +PVOID MmMustAllocPage(SWAPENTRY SavedSwapEntry); +PVOID MmAllocPageMaybeSwap(SWAPENTRY SavedSwapEntry); +NTSTATUS MmCreatePageTable(PVOID PAddress); + #endif diff --git a/reactos/ntoskrnl/ke/event.c b/reactos/ntoskrnl/ke/event.c index 094ece93279..598b9c92576 100644 --- a/reactos/ntoskrnl/ke/event.c +++ b/reactos/ntoskrnl/ke/event.c @@ -22,7 +22,7 @@ VOID STDCALL KeClearEvent (PKEVENT Event) { DPRINT("KeClearEvent(Event %x)\n", Event); - Event->Header.SignalState=FALSE; + Event->Header.SignalState = FALSE; } VOID STDCALL KeInitializeEvent (PKEVENT Event, diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 5f24b3cd356..3962f7e0cfd 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -30,103 +30,30 @@ extern void interrupt_handler2e(void); extern void interrupt_handler2d(void); +extern void exception_handler0(void); +extern void exception_handler1(void); +extern void exception_handler2(void); +extern void exception_handler3(void); +extern void exception_handler4(void); +extern void exception_handler5(void); +extern void exception_handler6(void); +extern void exception_handler7(void); +extern void exception_handler8(void); +extern void exception_handler9(void); +extern void exception_handler10(void); +extern void exception_handler11(void); +extern void exception_handler12(void); +extern void exception_handler13(void); +extern void exception_handler14(void); +extern void exception_handler15(void); +extern void exception_handler16(void); +extern void exception_handler_unknown(void); + extern ULONG init_stack; extern ULONG init_stack_top; /* FUNCTIONS ****************************************************************/ -#define EXCEPTION_HANDLER_WITH_ERROR(y) \ - void exception_handler##y (void); \ - void tmp_exception_handler##y (void) { \ - __asm__("\n\t_exception_handler"STR(y)":\n\t" \ - "pushl %gs\n\t" \ - "pushl %fs\n\t" \ - "pushl %es\n\t" \ - "pushl %ds\n\t" \ - "pushl $"STR(y)"\n\t" \ - "pusha\n\t" \ - "movw $"STR(KERNEL_DS)",%ax\n\t" \ - "movw %ax,%ds\n\t" \ - "movw %ax,%es\n\t" \ - "movw %ax,%fs\n\t" \ - "movw %ax,%gs\n\t" \ - "call _exception_handler\n\t" \ - "popa\n\t" \ - "addl $4,%esp\n\t" \ - "popl %ds\n\t" \ - "popl %es\n\t" \ - "popl %fs\n\t" \ - "popl %gs\n\t" \ - "addl $4,%esp\n\t" \ - "iret\n\t"); } - -#define EXCEPTION_HANDLER_WITHOUT_ERROR(y) \ - void exception_handler##y (void); \ - void tmp_exception_handler##y (void) { \ - __asm__("\n\t_exception_handler"STR(y)":\n\t" \ - "pushl $0\n\t" \ - "pushl %gs\n\t" \ - "pushl %fs\n\t" \ - "pushl %es\n\t" \ - "pushl %ds\n\t" \ - "pushl $"STR(y)"\n\t" \ - "pusha\n\t" \ - "movw $"STR(KERNEL_DS)",%ax\n\t" \ - "movw %ax,%ds\n\t" \ - "movw %ax,%es\n\t" \ - "movw %ax,%fs\n\t" \ - "movw %ax,%gs\n\t" \ - "call _exception_handler\n\t" \ - "popa\n\t" \ - "addl $4,%esp\n\t" \ - "popl %ds\n\t" \ - "popl %es\n\t" \ - "popl %fs\n\t" \ - "popl %gs\n\t" \ - "addl $4,%esp\n\t" \ - "iret\n\t"); } - -void exception_handler_unknown(void); -void tmp_exception_handler_unknown(void) -{ - __asm__("\n\t_exception_handler_unknown:\n\t" - "pushl $0\n\t" - "pushl %gs\n\t" - "pushl %fs\n\t" - "pushl %es\n\t" - "pushl %ds\n\t" - "pushl %ds\n\t" - "pushl $0xff\n\t" - "pusha\n\t" - "movw $"STR(KERNEL_DS)",%ax\n\t" - "movw %ax,%ds\n\t" - "movw %ax,%es\n\t" - "movw %ax,%fs\n\t" - "movw %ax,%gs\n\t" - "call _exception_handler\n\t" - "popa\n\t" - "addl $8,%esp\n\t" - "iret\n\t"); -} - -EXCEPTION_HANDLER_WITHOUT_ERROR(0); -EXCEPTION_HANDLER_WITHOUT_ERROR(1); -EXCEPTION_HANDLER_WITHOUT_ERROR(2); -EXCEPTION_HANDLER_WITHOUT_ERROR(3); -EXCEPTION_HANDLER_WITHOUT_ERROR(4); -EXCEPTION_HANDLER_WITHOUT_ERROR(5); -EXCEPTION_HANDLER_WITHOUT_ERROR(6); -EXCEPTION_HANDLER_WITHOUT_ERROR(7); -EXCEPTION_HANDLER_WITH_ERROR(8); -EXCEPTION_HANDLER_WITHOUT_ERROR(9); -EXCEPTION_HANDLER_WITH_ERROR(10); -EXCEPTION_HANDLER_WITH_ERROR(11); -EXCEPTION_HANDLER_WITH_ERROR(12); -EXCEPTION_HANDLER_WITH_ERROR(13); -EXCEPTION_HANDLER_WITH_ERROR(14); -EXCEPTION_HANDLER_WITH_ERROR(15); -EXCEPTION_HANDLER_WITHOUT_ERROR(16); - extern unsigned int stext, etext; static void print_address(PVOID address) diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index efc3739307b..bb303eee008 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -1,4 +1,4 @@ -/* $Id: trap.s,v 1.1 2000/07/04 08:52:41 dwelch Exp $ +/* $Id: trap.s,v 1.2 2000/07/06 14:34:50 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -12,6 +12,10 @@ #include #include +/* + * + */ + .globl _PsBeginThreadWithContextInternal _PsBeginThreadWithContextInternal: @@ -37,6 +41,10 @@ _PsBeginThreadWithContextInternal: popl %ebp iret +/* + * + */ + .globl _interrupt_handler2e _interrupt_handler2e: @@ -195,4 +203,430 @@ done: iret +/* + * + */ + +.globl _exception_handler0 +_exception_handler0: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $0 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler1 +_exception_handler1: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $1 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + + +.globl _exception_handler2 +_exception_handler2: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $2 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler3 +_exception_handler3: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $3 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler4 +_exception_handler4: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $4 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler5 +_exception_handler5: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $5 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler6 +_exception_handler6: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $6 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler7 +_exception_handler7: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $7 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler8 +_exception_handler8: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $8 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler9 +_exception_handler9: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $1 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler10 +_exception_handler10: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $10 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler11 +_exception_handler11: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $1 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler12 +_exception_handler12: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $1 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler13 +_exception_handler13: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $1 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler14 +_exception_handler14: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $14 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler15 +_exception_handler15: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $15 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler16 +_exception_handler16: + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl $16 + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $4,%esp + popl %ds + popl %es + popl %fs + popl %gs + addl $4,%esp + iret + +.globl _exception_handler_unknown +_exception_handler_unknown: + pushl $0 + pushl %gs + pushl %fs + pushl %es + pushl %ds + pushl %ds + pushl $0xff + pusha + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + movw %ax,%fs + movw %ax,%gs + call _exception_handler + popa + addl $8,%esp + iret + + /* EOF */ diff --git a/reactos/ntoskrnl/ke/mutex.c b/reactos/ntoskrnl/ke/mutex.c index c62c0c9c04e..ff7aea79e91 100644 --- a/reactos/ntoskrnl/ke/mutex.c +++ b/reactos/ntoskrnl/ke/mutex.c @@ -1,4 +1,4 @@ -/* $Id: mutex.c,v 1.6 2000/06/29 23:35:38 dwelch Exp $ +/* $Id: mutex.c,v 1.7 2000/07/06 14:34:50 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -19,39 +19,27 @@ /* FUNCTIONS *****************************************************************/ -VOID -STDCALL -KeInitializeMutex ( - PKMUTEX Mutex, - ULONG Level - ) +VOID STDCALL KeInitializeMutex (PKMUTEX Mutex, + ULONG Level) { KeInitializeDispatcherHeader(&Mutex->Header, InternalMutexType, sizeof(KMUTEX) / sizeof(ULONG), - TRUE); + 1); } -LONG -STDCALL -KeReadStateMutex ( - PKMUTEX Mutex - ) +LONG STDCALL KeReadStateMutex (PKMUTEX Mutex) { return(Mutex->Header.SignalState); } -LONG -STDCALL -KeReleaseMutex ( - PKMUTEX Mutex, - BOOLEAN Wait - ) +LONG STDCALL KeReleaseMutex (PKMUTEX Mutex, + BOOLEAN Wait) { KeAcquireDispatcherDatabaseLock(Wait); - Mutex->Header.SignalState--; - assert(Mutex->Header.SignalState >= 0); - if (Mutex->Header.SignalState == 0) + Mutex->Header.SignalState++; + assert(Mutex->Header.SignalState <= 1); + if (Mutex->Header.SignalState == 1) { KeDispatcherObjectWake(&Mutex->Header); } @@ -59,15 +47,11 @@ KeReleaseMutex ( return(0); } -NTSTATUS -STDCALL -KeWaitForMutexObject ( - PKMUTEX Mutex, - KWAIT_REASON WaitReason, - KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, - PLARGE_INTEGER Timeout - ) +NTSTATUS STDCALL KeWaitForMutexObject (PKMUTEX Mutex, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout) { return(KeWaitForSingleObject(Mutex,WaitReason,WaitMode,Alertable,Timeout)); } diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 0139b2d827c..aad3393f3d6 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -83,7 +83,7 @@ VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr, switch (hdr->Type) { case InternalSynchronizationEvent: - hdr->SignalState = FALSE; + hdr->SignalState = 0; break; case InternalSemaphoreType: @@ -113,7 +113,7 @@ VOID KiSideEffectsBeforeWake(DISPATCHER_HEADER* hdr, Mutex = CONTAINING_RECORD(hdr, KMUTEX, Header); - hdr->SignalState++; + hdr->SignalState--; Mutex->OwnerThread = Thread; } break; @@ -137,9 +137,9 @@ static BOOLEAN KiIsObjectSignalled(DISPATCHER_HEADER* hdr, KMUTEX, Header); - if ((hdr->SignalState <= 0 && - Mutex->OwnerThread == Thread) || - hdr->SignalState > 0) + assert(hdr->SignalState <= 1); + if ((hdr->SignalState < 1 && Mutex->OwnerThread == Thread) || + hdr->SignalState == 1) { KiSideEffectsBeforeWake(hdr, Thread); @@ -365,15 +365,11 @@ BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr) } -NTSTATUS -STDCALL -KeWaitForSingleObject ( - PVOID Object, - KWAIT_REASON WaitReason, - KPROCESSOR_MODE WaitMode, - BOOLEAN Alertable, - PLARGE_INTEGER Timeout - ) +NTSTATUS STDCALL KeWaitForSingleObject (PVOID Object, + KWAIT_REASON WaitReason, + KPROCESSOR_MODE WaitMode, + BOOLEAN Alertable, + PLARGE_INTEGER Timeout) /* * FUNCTION: Puts the current thread into a wait state until the * given dispatcher object is set to signalled diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 8d6b893232e..dce327e5d3d 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -236,6 +236,11 @@ VOID MmReferencePage(PVOID PhysicalAddress) DPRINT("MmReferencePage(PhysicalAddress %x)\n", PhysicalAddress); + if (((ULONG)PhysicalAddress) == 0) + { + KeBugCheck(0); + } + KeAcquireSpinLock(&PageListLock, &oldIrql); MmPageArray[Start].ReferenceCount++; KeReleaseSpinLock(&PageListLock, oldIrql); @@ -247,6 +252,11 @@ VOID MmDereferencePage(PVOID PhysicalAddress) KIRQL oldIrql; DPRINT("MmDereferencePage(PhysicalAddress %x)\n", PhysicalAddress); + + if (((ULONG)PhysicalAddress) == 0) + { + KeBugCheck(0); + } if (((ULONG)PhysicalAddress) > 0x400000) { @@ -283,8 +293,8 @@ PVOID MmAllocPage(SWAPENTRY SavedSwapEntry) DPRINT("ListEntry %x\n",ListEntry); if (ListEntry == NULL) { - DbgPrint("MmAllocPage(): Out of memory\n"); - KeBugCheck(0); + DPRINT("MmAllocPage(): Out of memory\n"); + return(NULL); } PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry); DPRINT("PageDescriptor %x\n",PageDescriptor); @@ -313,6 +323,33 @@ PVOID MmAllocPage(SWAPENTRY SavedSwapEntry) return((PVOID)offset); } +PVOID MmMustAllocPage(SWAPENTRY SavedSwapEntry) +{ + PVOID Page; + + Page = MmAllocPage(SavedSwapEntry); + if (Page == NULL) + { + KeBugCheck(0); + return(NULL); + } + + return(Page); +} + +PVOID MmAllocPageMaybeSwap(SWAPENTRY SavedSwapEntry) +{ + PVOID Page; + + Page = MmAllocPage(SavedSwapEntry); + while (Page == NULL) + { + MmWaitForFreePages(); + Page = MmAllocPage(SavedSwapEntry); + }; + return(Page); +} + NTSTATUS MmWaitForPage(PVOID PhysicalAddress) { NTSTATUS Status; diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 85cc13d130d..8dc3769d0d5 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -1,4 +1,4 @@ -/* $Id: page.c,v 1.10 2000/07/04 08:52:46 dwelch Exp $ +/* $Id: page.c,v 1.11 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -140,6 +140,46 @@ ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) return(Entry); } +ULONG MmGetPageEntry1(PVOID PAddress) +/* + * FUNCTION: Get a pointer to the page table entry for a virtual address + */ +{ + PULONG page_tlb; + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + page_dir = ADDR_TO_PDE(Address); + DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); + if ((*page_dir) == 0) + { + return(0); + } + page_tlb = ADDR_TO_PTE(Address); + DPRINT("page_tlb %x\n",page_tlb); + return(*page_tlb); +} + +ULONG MmGetPageEntryForProcess1(PEPROCESS Process, PVOID Address) +{ + ULONG Entry; + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + if (Process != NULL && Process != CurrentProcess) + { + KeAttachProcess(Process); + } + Entry = MmGetPageEntry1(Address); + if (Process != NULL && Process != CurrentProcess) + { + KeDetachProcess(); + } + return(Entry); +} + + ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process, PVOID Address) { @@ -202,6 +242,30 @@ BOOLEAN MmIsPageTablePresent(PVOID PAddress) return((*page_dir) == 0); } +NTSTATUS MmCreatePageTable(PVOID PAddress) +{ + PULONG page_dir; + ULONG Address = (ULONG)PAddress; + ULONG npage; + + DPRINT("MmGetPageEntry(Address %x)\n", Address); + + page_dir = ADDR_TO_PDE(Address); + DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); + if ((*page_dir) == 0) + { + npage = (ULONG)MmAllocPage(0); + if (npage == 0) + { + return(STATUS_UNSUCCESSFUL); + } + (*page_dir) = npage | 0x7; + memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE); + FLUSH_TLB; + } + return(STATUS_SUCCESS); +} + PULONG MmGetPageEntry(PVOID PAddress) /* * FUNCTION: Get a pointer to the page table entry for a virtual address @@ -210,6 +274,7 @@ PULONG MmGetPageEntry(PVOID PAddress) PULONG page_tlb; PULONG page_dir; ULONG Address = (ULONG)PAddress; + ULONG npage; DPRINT("MmGetPageEntry(Address %x)\n", Address); @@ -217,7 +282,12 @@ PULONG MmGetPageEntry(PVOID PAddress) DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir); if ((*page_dir) == 0) { - (*page_dir) = ((ULONG)MmAllocPage(0)) | 0x7; + npage = (ULONG)MmAllocPage(0); + if (npage == 0) + { + KeBugCheck(0); + } + (*page_dir) = npage | 0x7; memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE); FLUSH_TLB; } @@ -233,7 +303,7 @@ BOOLEAN MmIsPageDirty(PEPROCESS Process, PVOID Address) BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address) { - return((MmGetPageEntryForProcess(Process, Address)) & PA_PRESENT); + return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT); } diff --git a/reactos/ntoskrnl/mm/marea.c b/reactos/ntoskrnl/mm/marea.c index 667cd84c67a..79cb17f636c 100644 --- a/reactos/ntoskrnl/mm/marea.c +++ b/reactos/ntoskrnl/mm/marea.c @@ -294,7 +294,10 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace, { PhysicalAddr = MmGetPhysicalAddress(MemoryArea->BaseAddress + (i*PAGESIZE)); - MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart)); + if (PhysicalAddr.u.LowPart != 0) + { + MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart)); + } } } for (i=0; i<=(MemoryArea->Length/PAGESIZE); i++) diff --git a/reactos/ntoskrnl/mm/mdl.c b/reactos/ntoskrnl/mm/mdl.c index 7469dc015d1..992a4cf2d0e 100644 --- a/reactos/ntoskrnl/mm/mdl.c +++ b/reactos/ntoskrnl/mm/mdl.c @@ -1,4 +1,4 @@ -/* $Id: mdl.c,v 1.21 2000/07/04 08:52:42 dwelch Exp $ +/* $Id: mdl.c,v 1.22 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -109,7 +109,7 @@ VOID STDCALL MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl) } -VOID MmBuildMdlFromPages(PMDL Mdl) +VOID MmBuildMdlFromPages(PMDL Mdl, PULONG Pages) { ULONG i; PULONG mdl_pages; @@ -118,19 +118,15 @@ VOID MmBuildMdlFromPages(PMDL Mdl) for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGESIZE);i++) { - mdl_pages[i] = (ULONG)MmAllocPage(0); + mdl_pages[i] = Pages[i]; DPRINT("mdl_pages[i] %x\n",mdl_pages[i]); } } -VOID -STDCALL -MmProbeAndLockPages ( - PMDL Mdl, - KPROCESSOR_MODE AccessMode, - LOCK_OPERATION Operation - ) +VOID STDCALL MmProbeAndLockPages (PMDL Mdl, + KPROCESSOR_MODE AccessMode, + LOCK_OPERATION Operation) /* * FUNCTION: Probes the specified pages, makes them resident and locks them * ARGUMENTS: diff --git a/reactos/ntoskrnl/mm/pager.c b/reactos/ntoskrnl/mm/pager.c index 1a35d95db9a..12b5145deaa 100644 --- a/reactos/ntoskrnl/mm/pager.c +++ b/reactos/ntoskrnl/mm/pager.c @@ -1,4 +1,4 @@ -/* $Id: pager.c,v 1.2 2000/07/04 08:52:45 dwelch Exp $ +/* $Id: pager.c,v 1.3 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -29,17 +30,42 @@ static KEVENT PagerThreadEvent; static PEPROCESS LastProcess; static volatile BOOLEAN PagerThreadShouldTerminate; static volatile ULONG PageCount; +static volatile ULONG WaiterCount; +static KEVENT FreedMemEvent; /* FUNCTIONS *****************************************************************/ -VOID MmTryPageOutFromProcess(PEPROCESS Process) +VOID MmWaitForFreePages(VOID) { + InterlockedIncrement((PULONG)&PageCount); + KeClearEvent(&FreedMemEvent); + KeSetEvent(&PagerThreadEvent, + IO_NO_INCREMENT, + FALSE); + InterlockedIncrement((PULONG)&WaiterCount); + KeWaitForSingleObject(&FreedMemEvent, + 0, + KernelMode, + FALSE, + NULL); + InterlockedDecrement((PULONG)&WaiterCount); +} + +static VOID MmTryPageOutFromProcess(PEPROCESS Process) +{ + ULONG P; + MmLockAddressSpace(&Process->AddressSpace); - PageCount = PageCount - MmTrimWorkingSet(Process, PageCount); + P = MmTrimWorkingSet(Process, PageCount); + if (P > 0) + { + InterlockedExchangeAdd((PULONG)&PageCount, -P); + KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE); + } MmUnlockAddressSpace(&Process->AddressSpace); } -NTSTATUS MmPagerThreadMain(PVOID Ignored) +static NTSTATUS MmPagerThreadMain(PVOID Ignored) { NTSTATUS Status; @@ -54,22 +80,26 @@ NTSTATUS MmPagerThreadMain(PVOID Ignored) { DbgPrint("PagerThread: Wait failed\n"); KeBugCheck(0); - } + } if (PagerThreadShouldTerminate) { DbgPrint("PagerThread: Terminating\n"); return(STATUS_SUCCESS); } - while (PageCount > 0) + while (WaiterCount > 0) { - KeAttachProcess(LastProcess); - MmTryPageOutFromProcess(LastProcess); - KeDetachProcess(); - if (PageCount != 0) + while (PageCount > 0) { - LastProcess = PsGetNextProcess(LastProcess); + KeAttachProcess(LastProcess); + MmTryPageOutFromProcess(LastProcess); + KeDetachProcess(); + if (PageCount != 0) + { + LastProcess = PsGetNextProcess(LastProcess); + } } + KeSetEvent(&FreedMemEvent, IO_NO_INCREMENT, FALSE); } } } @@ -79,11 +109,15 @@ NTSTATUS MmInitPagerThread(VOID) NTSTATUS Status; PageCount = 0; + WaiterCount = 0; LastProcess = PsInitialSystemProcess; PagerThreadShouldTerminate = FALSE; KeInitializeEvent(&PagerThreadEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&FreedMemEvent, + NotificationEvent, + FALSE); Status = PsCreateSystemThread(&PagerThreadHandle, THREAD_ALL_ACCESS, diff --git a/reactos/ntoskrnl/mm/section.c b/reactos/ntoskrnl/mm/section.c index bff9616910e..b48fe43c475 100644 --- a/reactos/ntoskrnl/mm/section.c +++ b/reactos/ntoskrnl/mm/section.c @@ -1,4 +1,4 @@ -/* $Id: section.c,v 1.35 2000/07/04 08:52:45 dwelch Exp $ +/* $Id: section.c,v 1.36 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -122,9 +122,9 @@ NTSTATUS MmUnalignedLoadPageForSection(PMADDRESS_SPACE AddressSpace, MmLockSection(Section); + Page = MmAllocPageMaybeSwap(0); Mdl = MmCreateMdl(NULL, NULL, PAGESIZE); - MmBuildMdlFromPages(Mdl); - Page = MmGetMdlPageAddress(Mdl, 0); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); MmUnlockSection(Section); MmUnlockAddressSpace(AddressSpace); DPRINT("Reading file offset %x\n", Offset.QuadPart); @@ -200,9 +200,11 @@ NTSTATUS MmOldNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, if (Entry == 0) { + Page = MmAllocPageMaybeSwap(0); + + Mdl = MmCreateMdl(NULL, NULL, PAGESIZE); - MmBuildMdlFromPages(Mdl); - Page = MmGetMdlPageAddress(Mdl, 0); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); MmUnlockSection(Section); MmUnlockAddressSpace(AddressSpace); DPRINT("Reading file offset %x\n", Offset.QuadPart); @@ -248,6 +250,103 @@ NTSTATUS MmOldNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, return(STATUS_SUCCESS); } +NTSTATUS MmWaitForPendingOperationSection(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MemoryArea, + PVOID Address, + PSECTION_OBJECT Section, + LARGE_INTEGER Offset, + ULONG Entry) +{ + PVOID Page; + NTSTATUS Status; + + /* + * If a page-in on that section offset is pending that wait for + * it to finish. + */ + + do + { + /* + * Release all our locks and wait for the pending operation + * to complete + */ + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + /* + * FIXME: What if the event is set and cleared after we + * unlock the section but before we wait. + */ + Status = MmWaitForPage((PVOID)(Entry & (~SPE_PAGEIN_PENDING))); + if (!NT_SUCCESS(Status)) + { + /* + * FIXME: What do we do in this case? Maybe the thread + * has terminated. + */ + + DbgPrint("Failed to wait for page\n"); + KeBugCheck(0); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Relock the address space and section + */ + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + + /* + * Get the entry for the section offset. If the entry is still + * pending that means another thread is already trying the + * page-in again so we have to wait again. + */ + Entry = MmGetPageEntrySection(Section, + Offset.u.LowPart); + } while (Entry & SPE_PAGEIN_PENDING); + + /* + * Setting the entry to null means the read failing. + * FIXME: We should retry it (unless that filesystem has gone + * entirely e.g. the network died). + */ + if (Entry == 0) + { + DbgPrint("Entry set to null while we slept\n"); + KeBugCheck(0); + } + + /* + * Maybe the thread did the page-in took the fault on the + * same address-space/address as we did. If so we can just + * return success. + */ + if (MmIsPagePresent(NULL, Address)) + { + MmUnlockSection(Section); + return(STATUS_SUCCESS); + } + + /* + * Get a reference to the page containing the data for the page. + */ + Page = (PVOID)Entry; + MmReferencePage(Page); + + /* + * When we reach here, we have the address space and section locked + * and have a reference to a page containing valid data for the + * section offset. Set the page and return success. + */ + MmSetPage(NULL, + Address, + MemoryArea->Attributes, + (ULONG)Page); + MmUnlockSection(Section); + + return(STATUS_SUCCESS); +} + NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, MEMORY_AREA* MemoryArea, PVOID Address) @@ -317,12 +416,48 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, * locked the section) then we need to load the page. */ + /* + * + */ + Page = MmAllocPage(0); + while (Page == NULL) + { + MmUnlockSection(Section); + MmUnlockAddressSpace(AddressSpace); + MmWaitForFreePages(); + MmLockAddressSpace(AddressSpace); + MmLockSection(Section); + Entry1 = MmGetPageEntrySection(Section, Offset.u.LowPart); + if (Entry1 & SPE_PAGEIN_PENDING) + { + return(MmWaitForPendingOperationSection(AddressSpace, + MemoryArea, + Address, + Section, + Offset, + Entry1)); + } + else if (Entry1 != 0) + { + Page = (PVOID)Entry; + MmReferencePage(Page); + + MmSetPage(NULL, + Address, + MemoryArea->Attributes, + (ULONG)Page); + MmUnlockSection(Section); + + return(STATUS_SUCCESS); + } + Page = MmAllocPage(0); + } + /* * Create an mdl to hold the page we are going to read data into. */ Mdl = MmCreateMdl(NULL, NULL, PAGESIZE); - MmBuildMdlFromPages(Mdl); - Page = MmGetMdlPageAddress(Mdl, 0); + MmBuildMdlFromPages(Mdl, (PULONG)&Page); /* * Clear the wait state (Since we are holding the only reference to @@ -390,80 +525,24 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, * may be waiting know that valid data is now in-memory. */ MmSetWaitPage(Page); + + MmSetPage(NULL, + Address, + MemoryArea->Attributes, + (ULONG)Page); + MmUnlockSection(Section); + + return(STATUS_SUCCESS); + } else if (Entry & SPE_PAGEIN_PENDING) { - /* - * If a page-in on that section offset is pending that wait for - * it to finish. - */ - - do - { - /* - * Release all our locks and wait for the pending operation - * to complete - */ - MmUnlockSection(Section); - MmUnlockAddressSpace(AddressSpace); - /* - * FIXME: What if the event is set and cleared after we - * unlock the section but before we wait. - */ - Status = MmWaitForPage((PVOID)(Entry & (~SPE_PAGEIN_PENDING))); - if (!NT_SUCCESS(Status)) - { - /* - * FIXME: What do we do in this case? Maybe the thread - * has terminated. - */ - - DbgPrint("Failed to wait for page\n"); - KeBugCheck(0); - } - - /* - * Relock the address space and section - */ - MmLockAddressSpace(AddressSpace); - MmLockSection(Section); - - /* - * Get the entry for the section offset. If the entry is still - * pending that means another thread is already trying the - * page-in again so we have to wait again. - */ - Entry = MmGetPageEntrySection(Section, - Offset.u.LowPart); - } while (Entry & SPE_PAGEIN_PENDING); - - /* - * Setting the entry to null means the read failing. - * FIXME: We should retry it (unless that filesystem has gone - * entirely e.g. the network died). - */ - if (Entry == 0) - { - DbgPrint("Entry set to null while we slept\n"); - KeBugCheck(0); - } - - /* - * Maybe the thread did the page-in took the fault on the - * same address-space/address as we did. If so we can just - * return success. - */ - if (MmIsPagePresent(NULL, Address)) - { - MmUnlockSection(Section); - return(STATUS_SUCCESS); - } - - /* - * Get a reference to the page containing the data for the page. - */ - Page = (PVOID)Entry; - MmReferencePage(Page); + return(MmWaitForPendingOperationSection(AddressSpace, + MemoryArea, + Address, + Section, + Offset, + Entry)); } else { @@ -474,27 +553,23 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace, Page = (PVOID)Entry; MmReferencePage(Page); + + MmSetPage(NULL, + Address, + MemoryArea->Attributes, + (ULONG)Page); + MmUnlockSection(Section); + + return(STATUS_SUCCESS); } - - /* - * When we reach here, we have the address space and section locked - * and have a reference to a page containing valid data for the - * section offset. Set the page and return success. - */ - - MmSetPage(NULL, - Address, - MemoryArea->Attributes, - (ULONG)Page); - MmUnlockSection(Section); - - return(STATUS_SUCCESS); } ULONG MmPageOutSectionView(PMADDRESS_SPACE AddressSpace, MEMORY_AREA* MemoryArea, - PVOID Address) + PVOID Address, + PBOOLEAN Ul) { + (*Ul) = FALSE; return(0); } diff --git a/reactos/ntoskrnl/mm/virtual.c b/reactos/ntoskrnl/mm/virtual.c index 085e0b01e8c..8f4cf736967 100644 --- a/reactos/ntoskrnl/mm/virtual.c +++ b/reactos/ntoskrnl/mm/virtual.c @@ -1,4 +1,4 @@ -/* $Id: virtual.c,v 1.30 2000/07/04 08:52:45 dwelch Exp $ +/* $Id: virtual.c,v 1.31 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -29,7 +29,8 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, PMEMORY_AREA MemoryArea, - PVOID Address) + PVOID Address, + PBOOLEAN Ul) { PHYSICAL_ADDRESS PhysicalAddress; @@ -39,30 +40,71 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace, { PhysicalAddress = MmGetPhysicalAddress(Address); - MmDereferencePage((PVOID)PhysicalAddress.u.LowPart); + MmRemovePageFromWorkingSet(AddressSpace->Process, + Address); MmSetPage(PsGetCurrentProcess(), Address, 0, 0); + MmDereferencePage((PVOID)PhysicalAddress.u.LowPart); + *Ul = TRUE; return(1); } + *Ul = FALSE; return(0); } NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace, MEMORY_AREA* MemoryArea, PVOID Address) +/* + * FUNCTION: Move data into memory to satisfy a page not present fault + * ARGUMENTS: + * AddressSpace = Address space within which the fault occurred + * MemoryArea = The memory area within which the fault occurred + * Address = The absolute address of fault + * RETURNS: Status + * NOTES: This function is called with the address space lock held. + */ { + PVOID Page; + NTSTATUS Status; + if (MmIsPagePresent(NULL, Address)) - { - + { return(STATUS_SUCCESS); } + Page = MmAllocPage(0); + while (Page == NULL) + { + MmUnlockAddressSpace(AddressSpace); + MmWaitForFreePages(); + MmLockAddressSpace(AddressSpace); + if (MmIsPagePresent(NULL, Address)) + { + return(STATUS_SUCCESS); + } + Page = MmAllocPage(0); + } + Status = MmCreatePageTable(Address); + while (!NT_SUCCESS(Status)) + { + MmUnlockAddressSpace(AddressSpace); + MmWaitForFreePages(); + MmLockAddressSpace(AddressSpace); + if (MmIsPagePresent(NULL, Address)) + { + MmDereferencePage(Page); + return(STATUS_SUCCESS); + } + Status = MmCreatePageTable(Address); + } + MmAddPageToWorkingSet(PsGetCurrentProcess(), Address); MmSetPage(PsGetCurrentProcess(), Address, MemoryArea->Attributes, - (ULONG)MmAllocPage(0)); + (ULONG)Page); return(STATUS_SUCCESS); } @@ -239,6 +281,7 @@ NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, NTSTATUS Status; PEPROCESS Process; PMADDRESS_SPACE AddressSpace; + ULONG i; DPRINT("NtFreeVirtualMemory(ProcessHandle %x, *BaseAddress %x, " "*RegionSize %x, FreeType %x)\n",ProcessHandle,*BaseAddress, @@ -283,10 +326,26 @@ NTSTATUS STDCALL NtFreeVirtualMemory(IN HANDLE ProcessHandle, { MmDereserveSwapPages(PAGE_ROUND_UP(MemoryArea->Length)); } + + for (i=0; i<=(MemoryArea->Length/PAGESIZE); i++) + { + LARGE_INTEGER PhysicalAddr; + + PhysicalAddr = MmGetPhysicalAddress(MemoryArea->BaseAddress + + (i*PAGESIZE)); + if (PhysicalAddr.u.LowPart != 0) + { + MmRemovePageFromWorkingSet(AddressSpace->Process, + MemoryArea->BaseAddress + + (i*PAGESIZE)); + MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart)); + } + } + MmFreeMemoryArea(&Process->AddressSpace, BaseAddress, 0, - TRUE); + FALSE); MmUnlockAddressSpace(AddressSpace); ObDereferenceObject(Process); return(STATUS_SUCCESS); diff --git a/reactos/ntoskrnl/mm/wset.c b/reactos/ntoskrnl/mm/wset.c index 0dbc3635952..d8541f98231 100644 --- a/reactos/ntoskrnl/mm/wset.c +++ b/reactos/ntoskrnl/mm/wset.c @@ -1,4 +1,4 @@ -/* $Id: wset.c,v 1.1 2000/07/04 08:52:45 dwelch Exp $ +/* $Id: wset.c,v 1.2 2000/07/06 14:34:51 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -42,15 +42,49 @@ VOID MmInitializeWorkingSet(PEPROCESS Process, AddressSpace->WorkingSetPagesAllocated = 1; KeInitializeMutex(&Process->WorkingSetLock, 1); Process->WorkingSetPage = ExAllocatePage(); + memset(Process->WorkingSetPage, 0, 4096); +} + +ULONG MmPageOutPage(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MArea, + PVOID Address, + PBOOLEAN Ul) +{ + ULONG Count; + + switch(MArea->Type) + { + case MEMORY_AREA_SYSTEM: + *Ul = FALSE; + return(0); + + case MEMORY_AREA_SECTION_VIEW_COMMIT: + Count = MmPageOutSectionView(AddressSpace, + MArea, + Address, + Ul); + return(Count); + + case MEMORY_AREA_COMMIT: + Count = MmPageOutVirtualMemory(AddressSpace, + MArea, + Address, + Ul); + return(Count); + + } + *Ul = FALSE; + return(0); } ULONG MmTrimWorkingSet(PEPROCESS Process, ULONG ReduceHint) { - ULONG i; + ULONG i, j; PMADDRESS_SPACE AddressSpace; PMWORKING_SET WSet; ULONG Count; + BOOLEAN Ul; MmLockWorkingSet(Process); @@ -58,41 +92,37 @@ ULONG MmTrimWorkingSet(PEPROCESS Process, AddressSpace = &Process->AddressSpace; Count = 0; + j = AddressSpace->WorkingSetLruFirst; - for (i = 0; i < AddressSpace->WorkingSetSize; i++) + for (i = 0; i < AddressSpace->WorkingSetSize; ) { PVOID Address; PMEMORY_AREA MArea; - Address = WSet->Address[AddressSpace->WorkingSetLruFirst]; - + Address = WSet->Address[j]; + MArea = MmOpenMemoryAreaByAddress(AddressSpace, Address); - switch(MArea->Type) + if (MArea == NULL) { - case MEMORY_AREA_SYSTEM: - break; - - case MEMORY_AREA_SECTION_VIEW_COMMIT: - Count = Count + MmPageOutSectionView(AddressSpace, - MArea, - Address); - break; - - case MEMORY_AREA_COMMIT: - Count = Count + MmPageOutVirtualMemory(AddressSpace, - MArea, - Address); - break; - - default: - break; + KeBugCheck(0); } - - AddressSpace->WorkingSetLruFirst = - ((AddressSpace->WorkingSetLruFirst) + 1) % 1020; + Count = Count + MmPageOutPage(AddressSpace, MArea, Address, &Ul); + if (Ul) + { + MmLockWorkingSet(Process); + + j = AddressSpace->WorkingSetLruFirst; + i = 0; + } + else + { + j = (j + 1) % 1020; + i++; + } + if (Count == ReduceHint) { MmUnlockWorkingSet(Process); @@ -119,7 +149,8 @@ VOID MmRemovePageFromWorkingSet(PEPROCESS Process, { if (WSet->Address[j] == Address) { - WSet->Address[j] = WSet->Address[AddressSpace->WorkingSetLruLast]; + WSet->Address[j] = + WSet->Address[AddressSpace->WorkingSetLruLast - 1]; if (AddressSpace->WorkingSetLruLast != 0) { AddressSpace->WorkingSetLruLast = diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index b8737886b3d..ff5e044c130 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.49 2000/07/04 11:11:04 dwelch Exp $ +/* $Id: process.c,v 1.50 2000/07/06 14:34:52 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -55,9 +55,18 @@ PEPROCESS PsGetNextProcess(PEPROCESS OldProcess) } KeAcquireSpinLock(&PsProcessListLock, &oldIrql); - NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink, - EPROCESS, - ProcessListEntry); + if (OldProcess->ProcessListEntry.Flink == &PsProcessListHead) + { + NextProcess = CONTAINING_RECORD(PsProcessListHead.Flink, + EPROCESS, + ProcessListEntry); + } + else + { + NextProcess = CONTAINING_RECORD(OldProcess->ProcessListEntry.Flink, + EPROCESS, + ProcessListEntry); + } KeReleaseSpinLock(&PsProcessListLock, oldIrql); Status = ObReferenceObjectByPointer(NextProcess, PROCESS_ALL_ACCESS, diff --git a/reactos/ntoskrnl/ps/thread.c b/reactos/ntoskrnl/ps/thread.c index 4683a266559..d20cd2db8ec 100644 --- a/reactos/ntoskrnl/ps/thread.c +++ b/reactos/ntoskrnl/ps/thread.c @@ -1,4 +1,4 @@ -/* $Id: thread.c,v 1.51 2000/07/04 11:11:04 dwelch Exp $ +/* $Id: thread.c,v 1.52 2000/07/06 14:34:52 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -149,7 +149,7 @@ VOID PsDumpThreads(VOID) current = CONTAINING_RECORD(current_entry, ETHREAD, Tcb.ThreadListEntry); t++; - if (t >= PiNrThreads) + if (t > PiNrThreads) { DbgPrint("Too many threads on list\n"); return; @@ -157,7 +157,8 @@ VOID PsDumpThreads(VOID) DbgPrint("current %x current->Tcb.State %d eip %x ", current, current->Tcb.State, current->Tcb.Context.eip); -// KeDumpStackFrames(0, 16); + KeDumpStackFrames((PVOID)current->Tcb.Context.esp0, + 16); DbgPrint("PID %d ", current->ThreadsProcess->UniqueProcessId); DbgPrint("\n"); diff --git a/reactos/subsys/csrss/api/conio.c b/reactos/subsys/csrss/api/conio.c index b66234365a7..e2b391484ea 100644 --- a/reactos/subsys/csrss/api/conio.c +++ b/reactos/subsys/csrss/api/conio.c @@ -1,4 +1,4 @@ -/* $Id: conio.c,v 1.7 2000/05/26 05:40:20 phreak Exp $ +/* $Id: conio.c,v 1.8 2000/07/06 14:34:52 dwelch Exp $ * * reactos/subsys/csrss/api/conio.c * @@ -486,8 +486,10 @@ VOID Console_Api( DWORD Ignored ) NTSTATUS Status; while( 1 ) { - KeyEventRecord = RtlAllocateHeap( CsrssApiHeap, 0, sizeof( ConsoleInput ) ); - if( KeyEventRecord == 0 ) + KeyEventRecord = RtlAllocateHeap(CsrssApiHeap, + 0, + sizeof(ConsoleInput)); + if ( KeyEventRecord == 0 ) { DbgPrint( "CSR: Memory allocation failure!" ); continue;