[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