[NTOSKRNL:CC] Implement Extarnal Cache Directives
Implemented:: CcDeductDirtyPagesFromExternalCache CcAddDirtyPagesToExternalCache:: Exported CcAddExternalCache CcRegisterExternalCache:: Exported CcRemoveExternalCache CcUnregisterExternalCache :: Exported
This commit is contained in:
parent
d0d6097d57
commit
08d017171d
210
NTOSKRNL/CC/ccexternalcache.cpp
Normal file
210
NTOSKRNL/CC/ccexternalcache.cpp
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/*
|
||||||
|
* PROJECT: Alcyone System Kernel
|
||||||
|
* LICENSE: BSD Clause 3
|
||||||
|
* PURPOSE: Cache Controller:: External Cache Compatibility Layer
|
||||||
|
* NT KERNEL: 5.11.9360
|
||||||
|
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
|
||||||
|
*/
|
||||||
|
|
||||||
|
NOTE::Alcyone will not notify,in case of Empty External Cache at the moment, feature is planned for threadpool revamp
|
||||||
|
|
||||||
|
/* Move Typedef later cctypes.hpp */
|
||||||
|
typedef struct alignas(24) _DIRTY_PAGE_STATISTICS {
|
||||||
|
ULONGLONG DirtyPages; // 0x0
|
||||||
|
ULONGLONG DirtyPagesLastScan; // 0x8
|
||||||
|
ULONG DirtyPagesScheduledLastScan; // 0x10
|
||||||
|
} DIRTY_PAGE_STATISTICS, *PDIRTY_PAGE_STATISTICS; // 0x18 bytes (sizeof)
|
||||||
|
|
||||||
|
typedef struct alignas(30) _CC_EXTERNAL_CACHE_INFO {
|
||||||
|
VOID (*Callback)(VOID* arg1, ULONGLONG arg2, ULONG arg3); // 0x0
|
||||||
|
struct _DIRTY_PAGE_STATISTICS DirtyPageStatistics; // 0x8
|
||||||
|
struct _LIST_ENTRY Links; // 0x20
|
||||||
|
} CC_EXTERNAL_CACHE_INFO, *PCC_EXTERNAL_CACHE_INFO; // 0x30 bytes (sizeof)
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcDeductDirtyPagesFromExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
||||||
|
IN ULONG Pages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql ={0};
|
||||||
|
ULONG PagesToDeduct = {0};
|
||||||
|
|
||||||
|
|
||||||
|
if (Pages > 0)
|
||||||
|
{
|
||||||
|
/* Acquire the master lock */
|
||||||
|
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
||||||
|
|
||||||
|
/* Calculate the number of pages to deduct */
|
||||||
|
PagesToDeduct = min(Pages, ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
||||||
|
|
||||||
|
/* Deduct the pages from the external cache context */
|
||||||
|
ExternalCacheContext->DirtyPageStatistics.DirtyPages -= PagesToDeduct;
|
||||||
|
|
||||||
|
/* Deduct the pages from the global statistics */
|
||||||
|
CcTotalDirtyPages -= PagesToDeduct;
|
||||||
|
|
||||||
|
/* Release the master lock */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there are any deferred writes and post them if necessary */
|
||||||
|
if (!IsListEmpty(&CcDeferredWrites))
|
||||||
|
{
|
||||||
|
CcPostDeferredWrites();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcAddExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
||||||
|
|
||||||
|
/* Acquire the external cache list lock */
|
||||||
|
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
||||||
|
|
||||||
|
/* Insert the new cache info at the end of the list */
|
||||||
|
InsertTailList(&CcExternalCacheList, &CacheInfo->Links);
|
||||||
|
|
||||||
|
/* Increment the number of external caches */
|
||||||
|
if (_InterlockedIncrement(&CcNumberOfExternalCaches) <= 0)
|
||||||
|
{
|
||||||
|
/* Overflow occurred, bug check */
|
||||||
|
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the external cache list lock */
|
||||||
|
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcRemoveExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_INFO CacheInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
KLOCK_QUEUE_HANDLE LockHandle ={0};
|
||||||
|
|
||||||
|
/* Acquire the external cache list lock */
|
||||||
|
KeAcquireInStackQueuedSpinLock(&CcExternalCacheListLock,&LockHandle);
|
||||||
|
|
||||||
|
/* Remove the entry from the list */
|
||||||
|
RemoveTailList(&CacheInfo->Links.Blink);
|
||||||
|
|
||||||
|
/* Decrement the number of external caches */
|
||||||
|
if (_InterlockedDecrement(&CcNumberOfExternalCaches) < 0)
|
||||||
|
{
|
||||||
|
/* Underflow occurred, bug check */
|
||||||
|
KeBugCheckEx(CACHE_MANAGER,0,STATUS_INTEGER_OVERFLOW,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the external cache list lock */
|
||||||
|
KeReleaseInStackQueuedSpinLock(&LockHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*Exported */
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcAddDirtyPagesToExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext,
|
||||||
|
IN ULONG Pages
|
||||||
|
)
|
||||||
|
{
|
||||||
|
KIRQL OldIrql ={0};
|
||||||
|
|
||||||
|
|
||||||
|
/* Only proceed if there are pages to add */
|
||||||
|
if (Pages == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acquire the master lock */
|
||||||
|
KeAcquireQueuedSpinLock(LockQueueMasterLock, &OldIrql);
|
||||||
|
|
||||||
|
/* If this is the first dirty page, schedule a lazy write scan */
|
||||||
|
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages == 0)
|
||||||
|
{
|
||||||
|
CcScheduleLazyWriteScan(FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the dirty page count */
|
||||||
|
ExternalCacheContext->DirtyPageStatistics.DirtyPages += Pages;
|
||||||
|
|
||||||
|
/* Charge the dirty pages */
|
||||||
|
CcChargeDirtyPages(NULL, NULL, NULL, Pages);
|
||||||
|
|
||||||
|
/* Release the master lock */
|
||||||
|
KeReleaseQueuedSpinLock(LockQueueMasterLock, OldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CcUnregisterExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_INFO ExternalCacheContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove the external cache from the list */
|
||||||
|
CcRemoveExternalCache(ExternalCacheContext);
|
||||||
|
|
||||||
|
/* Deduct any remaining dirty pages */
|
||||||
|
if (ExternalCacheContext->DirtyPageStatistics.DirtyPages > 0)
|
||||||
|
{
|
||||||
|
CcDeductDirtyPagesFromExternalCache(ExternalCacheContext,ExternalCacheContext->DirtyPageStatistics.DirtyPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free the external cache context */
|
||||||
|
ExFreePoolWithTag(ExternalCacheContext, CC_EXTERNAL_CACHE_INFO_TAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
CcRegisterExternalCache(
|
||||||
|
IN PCC_EXTERNAL_CACHE_CALLBACK Callback,
|
||||||
|
OUT PVOID *ExternalCacheContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
PCC_EXTERNAL_CACHE_INFO CacheInfo;
|
||||||
|
|
||||||
|
|
||||||
|
/* Ensure the Cache Manager is initialized */
|
||||||
|
if (!CcInitializationComplete)
|
||||||
|
{
|
||||||
|
KeBugCheckEx(CACHE_MANAGER,0,STATUS_UNSUCCESSFUL,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate memory for the external cache info structure */
|
||||||
|
CacheInfo = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(CC_EXTERNAL_CACHE_INFO),
|
||||||
|
CC_EXTERNAL_CACHE_INFO_TAG);
|
||||||
|
if (CacheInfo == NULL)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the cache info structure */
|
||||||
|
RtlZeroMemory(CacheInfo, sizeof(CC_EXTERNAL_CACHE_INFO));
|
||||||
|
CacheInfo->Callback = Callback;
|
||||||
|
|
||||||
|
/* Add the external cache to the list */
|
||||||
|
CcAddExternalCache(CacheInfo);
|
||||||
|
|
||||||
|
/* Return the cache info as the context */
|
||||||
|
*ExternalCacheContext = CacheInfo;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user