diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 8f8a88f69b9..61143a30a15 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.58 2001/11/25 15:21:10 dwelch Exp $ +# $Id: Makefile,v 1.59 2001/12/27 23:56:41 dwelch Exp $ # # ReactOS Operating System # @@ -149,7 +149,8 @@ OBJECTS_MM = \ mm/mminit.o \ mm/kmap.o \ mm/mpw.o \ - mm/pageop.o + mm/pageop.o \ + mm/balance.o # I/O Subsystem (Io) OBJECTS_IO = \ diff --git a/reactos/ntoskrnl/cc/cacheman.c b/reactos/ntoskrnl/cc/cacheman.c index 820b13904a1..5592f1c0409 100644 --- a/reactos/ntoskrnl/cc/cacheman.c +++ b/reactos/ntoskrnl/cc/cacheman.c @@ -35,10 +35,8 @@ /* FUNCTIONS *****************************************************************/ -NTSTATUS +VOID CcInit(VOID) { CcInitView(); - - return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/cc/copy.c b/reactos/ntoskrnl/cc/copy.c index 37c435c34b4..bd803d8bc7d 100644 --- a/reactos/ntoskrnl/cc/copy.c +++ b/reactos/ntoskrnl/cc/copy.c @@ -1,4 +1,4 @@ -/* $Id: copy.c,v 1.1 2001/10/10 21:46:13 hbirr Exp $ +/* $Id: copy.c,v 1.2 2001/12/27 23:56:41 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -118,10 +118,10 @@ CcCopyRead ( if (!Wait) { KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); - current_entry = Bcb->CacheSegmentListHead.Flink; - while (current_entry != &Bcb->CacheSegmentListHead) + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) { - current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbListEntry); + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); if (!current->Valid && current->FileOffset < ReadOffset + Length && current->FileOffset + Bcb->CacheSegmentSize > ReadOffset) { @@ -231,10 +231,10 @@ CcCopyWrite ( { // testing, if the requested datas are available KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); - current_entry = Bcb->CacheSegmentListHead.Flink; - while (current_entry != &Bcb->CacheSegmentListHead) + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) { - CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbListEntry); + CacheSeg = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); if (!CacheSeg->Valid) { if ((WriteOffset >= CacheSeg->FileOffset && WriteOffset < CacheSeg->FileOffset + Bcb->CacheSegmentSize) diff --git a/reactos/ntoskrnl/cc/misc.c b/reactos/ntoskrnl/cc/misc.c index 43df08b9317..b5546a60135 100644 --- a/reactos/ntoskrnl/cc/misc.c +++ b/reactos/ntoskrnl/cc/misc.c @@ -15,6 +15,56 @@ /* FUNCTIONS *****************************************************************/ +/********************************************************************** + * NAME INTERNAL + * CcMdlReadCompleteDev@8 + * + * DESCRIPTION + * + * ARGUMENTS + * MdlChain + * DeviceObject + * + * RETURN VALUE + * None. + * + * NOTE + * Used by CcMdlReadComplete@8 and FsRtl + */ +VOID STDCALL +CcMdlReadCompleteDev (IN PMDL MdlChain, + IN PDEVICE_OBJECT DeviceObject) +{ + UNIMPLEMENTED; +} + + +/********************************************************************** + * NAME EXPORTED + * CcMdlReadComplete@8 + * + * DESCRIPTION + * + * ARGUMENTS + * + * RETURN VALUE + * None. + * + * NOTE + * From Bo Branten's ntifs.h v13. + */ +VOID STDCALL +CcMdlReadComplete (IN PFILE_OBJECT FileObject, + IN PMDL MdlChain) +{ + PDEVICE_OBJECT DeviceObject = NULL; + + DeviceObject = IoGetRelatedDeviceObject (FileObject); + /* FIXME: try fast I/O first */ + CcMdlReadCompleteDev (MdlChain, + DeviceObject); +} + VOID STDCALL CcSetFileSizes ( IN PFILE_OBJECT FileObject, @@ -37,10 +87,10 @@ CcSetFileSizes ( if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart) { - current_entry = Bcb->CacheSegmentListHead.Flink; - while (current_entry != &Bcb->CacheSegmentListHead) + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) { - current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbListEntry); + current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); current_entry = current_entry->Flink; if (current->FileOffset > FileSizes->AllocationSize.QuadPart) { diff --git a/reactos/ntoskrnl/cc/view.c b/reactos/ntoskrnl/cc/view.c index a490fd2b606..2bde154eac8 100644 --- a/reactos/ntoskrnl/cc/view.c +++ b/reactos/ntoskrnl/cc/view.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: view.c,v 1.29 2001/10/10 21:50:15 hbirr Exp $ +/* $Id: view.c,v 1.30 2001/12/27 23:56:41 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -69,27 +69,13 @@ #define TAG_CSEG TAG('C', 'S', 'E', 'G') #define TAG_BCB TAG('B', 'C', 'B', ' ') -static LIST_ENTRY BcbListHead; -static KSPIN_LOCK BcbListLock; +static LIST_ENTRY DirtySegmentListHead; +static LIST_ENTRY CacheSegmentListHead; + +static FAST_MUTEX ViewLock; /* FUNCTIONS *****************************************************************/ -NTSTATUS STDCALL -CcRosFlushCacheSegment(PCACHE_SEGMENT CacheSeg) -/* - * FUNCTION: Asks the FSD to flush the contents of the page back to disk - */ -{ - KeWaitForSingleObject(&CacheSeg->Lock, - Executive, - KernelMode, - FALSE, - NULL); - /* FIXME: Build an IRP_MJ_WRITE and send it to the filesystem */ - KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, 0); - return(STATUS_NOT_IMPLEMENTED); -} - NTSTATUS STDCALL CcRosReleaseCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg, @@ -100,7 +86,7 @@ CcRosReleaseCacheSegment(PBCB Bcb, CacheSeg->ReferenceCount--; CacheSeg->Valid = Valid; - KeSetEvent(&CacheSeg->Lock, IO_NO_INCREMENT, FALSE); + ExReleaseFastMutex(&CacheSeg->Lock); DPRINT("CcReleaseCachePage() finished\n"); @@ -109,54 +95,63 @@ CcRosReleaseCacheSegment(PBCB Bcb, NTSTATUS CcRosGetCacheSegment(PBCB Bcb, - ULONG FileOffset, - PULONG BaseOffset, - PVOID* BaseAddress, - PBOOLEAN UptoDate, - PCACHE_SEGMENT* CacheSeg) + ULONG FileOffset, + PULONG BaseOffset, + PVOID* BaseAddress, + PBOOLEAN UptoDate, + PCACHE_SEGMENT* CacheSeg) { - KIRQL oldirql; PLIST_ENTRY current_entry; PCACHE_SEGMENT current; ULONG i; NTSTATUS Status; + KIRQL oldIrql; - KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); - - current_entry = Bcb->CacheSegmentListHead.Flink; - while (current_entry != &Bcb->CacheSegmentListHead) + /* + * Acquire the global lock. + */ + ExAcquireFastMutex(&ViewLock); + + /* + * Look for a cache segment already mapping the same data. + */ + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) { current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, - BcbListEntry); + BcbSegmentListEntry); if (current->FileOffset <= FileOffset && (current->FileOffset + Bcb->CacheSegmentSize) > FileOffset) { - current->ReferenceCount++; - KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - KeWaitForSingleObject(¤t->Lock, - Executive, - KernelMode, - FALSE, - NULL); - *UptoDate = current->Valid; - *BaseAddress = current->BaseAddress; - *CacheSeg = current; - *BaseOffset = current->FileOffset; - return(STATUS_SUCCESS); + /* + * Make sure the cache segment can't go away outside of our control. + */ + current->ReferenceCount++; + /* + * Release the global lock and lock the cache segment. + */ + ExReleaseFastMutex(&ViewLock); + ExAcquireFastMutex(¤t->Lock); + /* + * Return information about the segment to the caller. + */ + *UptoDate = current->Valid; + *BaseAddress = current->BaseAddress; + *CacheSeg = current; + *BaseOffset = current->FileOffset; + return(STATUS_SUCCESS); } current_entry = current_entry->Flink; } - DPRINT("Creating new segment\n"); - - KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - + /* + * Otherwise create a new segment. + */ current = ExAllocatePoolWithTag(NonPagedPool, sizeof(CACHE_SEGMENT), TAG_CSEG); MmLockAddressSpace(MmGetKernelAddressSpace()); current->BaseAddress = NULL; - Status = MmCreateMemoryArea(KernelMode, MmGetKernelAddressSpace(), MEMORY_AREA_CACHE_SEGMENT, @@ -172,11 +167,18 @@ CcRosGetCacheSegment(PBCB Bcb, } current->Valid = FALSE; + current->Dirty = FALSE; current->FileOffset = ROUND_DOWN(FileOffset, Bcb->CacheSegmentSize); current->Bcb = Bcb; - KeInitializeEvent(¤t->Lock, SynchronizationEvent, FALSE); + ExInitializeFastMutex(¤t->Lock); current->ReferenceCount = 1; - InsertTailList(&Bcb->CacheSegmentListHead, ¤t->BcbListEntry); + KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); + InsertTailList(&Bcb->BcbSegmentListHead, ¤t->BcbSegmentListEntry); + KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); + InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry); + current->DirtySegmentListEntry.Flink = current->DirtySegmentListEntry.Blink = NULL; + ExAcquireFastMutex(¤t->Lock); + ExReleaseFastMutex(&ViewLock); *UptoDate = current->Valid; *BaseAddress = current->BaseAddress; *CacheSeg = current; @@ -240,6 +242,7 @@ CcRosFreeCacheSegment(PBCB Bcb, PCACHE_SEGMENT CacheSeg) */ { DPRINT("Freeing cache segment %x\n", CacheSeg); + RemoveEntryList(&CacheSeg->CacheSegmentListEntry); MmFreeMemoryArea(MmGetKernelAddressSpace(), CacheSeg->BaseAddress, Bcb->CacheSegmentSize, @@ -262,20 +265,21 @@ CcRosReleaseFileCache(PFILE_OBJECT FileObject, PBCB Bcb) MmFreeSectionSegments(Bcb->FileObject); - current_entry = Bcb->CacheSegmentListHead.Flink; - while (current_entry != &Bcb->CacheSegmentListHead) + /* + * Release all cache segments. + */ + current_entry = Bcb->BcbSegmentListHead.Flink; + while (current_entry != &Bcb->BcbSegmentListHead) { current = - CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbListEntry); + CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry); current_entry = current_entry->Flink; CcRosFreeCacheSegment(Bcb, current); } ObDereferenceObject (Bcb->FileObject); ExFreePool(Bcb); - - DPRINT("CcRosReleaseFileCache() finished\n"); - + return(STATUS_SUCCESS); } @@ -286,9 +290,7 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject, /* * FUNCTION: Initializes a BCB for a file object */ -{ - DPRINT("CcRosInitializeFileCache(FileObject %x)\n",FileObject); - +{ (*Bcb) = ExAllocatePoolWithTag(NonPagedPool, sizeof(BCB), TAG_BCB); if ((*Bcb) == NULL) { @@ -300,76 +302,34 @@ CcRosInitializeFileCache(PFILE_OBJECT FileObject, NULL, KernelMode); (*Bcb)->FileObject = FileObject; - InitializeListHead(&(*Bcb)->CacheSegmentListHead); - KeInitializeSpinLock(&(*Bcb)->BcbLock); (*Bcb)->CacheSegmentSize = CacheSegmentSize; if (FileObject->FsContext) - { - (*Bcb)->AllocationSize = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize; - (*Bcb)->FileSize = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize; - } - - DPRINT("Finished CcRosInitializeFileCache() = %x\n", *Bcb); + { + (*Bcb)->AllocationSize = + ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->AllocationSize; + (*Bcb)->FileSize = ((REACTOS_COMMON_FCB_HEADER*)FileObject->FsContext)->FileSize; + } + KeInitializeSpinLock(&(*Bcb)->BcbLock); + InitializeListHead(&(*Bcb)->BcbSegmentListHead); return(STATUS_SUCCESS); } - -/********************************************************************** - * NAME INTERNAL - * CcMdlReadCompleteDev@8 - * - * DESCRIPTION - * - * ARGUMENTS - * MdlChain - * DeviceObject - * - * RETURN VALUE - * None. - * - * NOTE - * Used by CcMdlReadComplete@8 and FsRtl - */ -VOID STDCALL -CcMdlReadCompleteDev (IN PMDL MdlChain, - IN PDEVICE_OBJECT DeviceObject) -{ - UNIMPLEMENTED; -} - - -/********************************************************************** - * NAME EXPORTED - * CcMdlReadComplete@8 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * None. - * - * NOTE - * From Bo Branten's ntifs.h v13. - */ -VOID STDCALL -CcMdlReadComplete (IN PFILE_OBJECT FileObject, - IN PMDL MdlChain) -{ - PDEVICE_OBJECT DeviceObject = NULL; - - DeviceObject = IoGetRelatedDeviceObject (FileObject); - /* FIXME: try fast I/O first */ - CcMdlReadCompleteDev (MdlChain, - DeviceObject); -} - VOID CcInitView(VOID) { - InitializeListHead(&BcbListHead); - KeInitializeSpinLock(&BcbListLock); + DPRINT1("CcInitView()\n"); + InitializeListHead(&CacheSegmentListHead); + InitializeListHead(&DirtySegmentListHead); + ExInitializeFastMutex(&ViewLock); } /* EOF */ + + + + + + + + diff --git a/reactos/ntoskrnl/ex/fmutex.c b/reactos/ntoskrnl/ex/fmutex.c index 213b8e87a58..890926de290 100644 --- a/reactos/ntoskrnl/ex/fmutex.c +++ b/reactos/ntoskrnl/ex/fmutex.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: fmutex.c,v 1.11 2001/12/20 03:56:09 dwelch Exp $ +/* $Id: fmutex.c,v 1.12 2001/12/27 23:56:42 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ex/fmutex.c @@ -39,17 +39,17 @@ VOID FASTCALL ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex) { + InterlockedIncrement(&FastMutex->Contention); while (InterlockedExchange(&FastMutex->Count, 0) == 0) - { - FastMutex->Contention++; + { KeWaitForSingleObject(&FastMutex->Event, Executive, KernelMode, FALSE, - NULL); - FastMutex->Contention--; + NULL); } - FastMutex->Owner = KeGetCurrentThread(); + InterlockedDecrement(&FastMutex->Contention); + FastMutex->Owner = KeGetCurrentThread(); } VOID FASTCALL @@ -57,8 +57,11 @@ ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex) { assert(FastMutex->Owner == KeGetCurrentThread()); FastMutex->Owner = NULL; + if (FastMutex->Contention > 0) + { + KeSetEvent(&FastMutex->Event, 0, FALSE); + } InterlockedExchange(&FastMutex->Count, 1); - KeSetEvent(&FastMutex->Event, 0, FALSE); } /* EOF */ diff --git a/reactos/ntoskrnl/include/internal/cc.h b/reactos/ntoskrnl/include/internal/cc.h index 49df4d11dca..c44b30fef30 100644 --- a/reactos/ntoskrnl/include/internal/cc.h +++ b/reactos/ntoskrnl/include/internal/cc.h @@ -1,28 +1,41 @@ #ifndef __INCLUDE_INTERNAL_CC_H #define __INCLUDE_INTERNAL_CC_H -/* $Id: cc.h,v 1.6 2001/10/10 21:55:13 hbirr Exp $ */ +/* $Id: cc.h,v 1.7 2001/12/27 23:56:42 dwelch Exp $ */ #include typedef struct _BCB { - LIST_ENTRY CacheSegmentListHead; + LIST_ENTRY BcbSegmentListHead; PFILE_OBJECT FileObject; - KSPIN_LOCK BcbLock; ULONG CacheSegmentSize; LARGE_INTEGER AllocationSize; LARGE_INTEGER FileSize; + KSPIN_LOCK BcbLock; } BCB; typedef struct _CACHE_SEGMENT { + /* Base address of the region where the cache segment data is mapped. */ PVOID BaseAddress; + /* Memory area representing the region where the cache segment data is mapped. */ struct _MEMORY_AREA* MemoryArea; + /* Are the contents of the cache segment data valid. */ BOOLEAN Valid; - LIST_ENTRY BcbListEntry; + /* Are the contents of the cache segment data newer than those on disk. */ + BOOLEAN Dirty; + /* Entry in the list of segments for this BCB. */ + LIST_ENTRY BcbSegmentListEntry; + /* Entry in the list of segments which are dirty. */ LIST_ENTRY DirtySegmentListEntry; + /* Entry in the list of segments. */ + LIST_ENTRY CacheSegmentListEntry; + /* Offset in the file which this cache segment maps. */ ULONG FileOffset; - KEVENT Lock; + /* Lock. */ + FAST_MUTEX Lock; + /* Number of references. */ ULONG ReferenceCount; + /* Pointer to the BCB for the file which this cache segment maps data for. */ PBCB Bcb; } CACHE_SEGMENT; @@ -46,4 +59,6 @@ NTSTATUS ReadCacheSegment(PCACHE_SEGMENT CacheSeg); NTSTATUS WriteCacheSegment(PCACHE_SEGMENT CacheSeg); +VOID CcInit(VOID); + #endif diff --git a/reactos/ntoskrnl/ke/i386/multiboot.S b/reactos/ntoskrnl/ke/i386/multiboot.S index 1f589943e4c..d350be4f404 100644 --- a/reactos/ntoskrnl/ke/i386/multiboot.S +++ b/reactos/ntoskrnl/ke/i386/multiboot.S @@ -188,10 +188,10 @@ _multiboot_entry: movl %eax, %cr3 /* - * Enable paging + * Enable paging and set write protect */ movl %cr0, %eax - orl $0x80000000, %eax + orl $0x80010000, %eax movl %eax, %cr0 /* diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 03836aa503a..504c5b3aad8 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.109 2001/11/25 15:21:10 dwelch Exp $ +/* $Id: main.c,v 1.110 2001/12/27 23:56:42 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -39,6 +39,7 @@ #include #include #include +#include //#include #include #include @@ -1026,6 +1027,7 @@ ExpInitializeExecutive(VOID) CmInitializeRegistry(); NtInit(); MmInit3(); + CcInit(); /* Report all resources used by hal */ HalReportResourceUsage(); diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 9e208d833ed..2e35efb2243 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mm.c,v 1.50 2001/12/20 03:56:09 dwelch Exp $ +/* $Id: mm.c,v 1.51 2001/12/27 23:56:42 dwelch Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -249,7 +249,7 @@ NTSTATUS MmCommitPagedPoolAddress(PVOID Address) Status = MmCreateVirtualMapping(NULL, (PVOID)PAGE_ROUND_DOWN(Address), - PAGE_READONLY, + PAGE_READWRITE, (ULONG)AllocatedPage); return(Status); }