Refactor process quota return logic and fix atomic exchange operations
Some checks failed
Builds / ExectOS (amd64, release) (push) Failing after 24s
Builds / ExectOS (i686, release) (push) Failing after 27s
Builds / ExectOS (i686, debug) (push) Failing after 38s
Builds / ExectOS (amd64, debug) (push) Failing after 40s

This commit is contained in:
2026-07-11 01:35:51 +02:00
parent 130e797dd9
commit c48cefd463

View File

@@ -54,10 +54,13 @@ PS::Quota::DereferenceQuotaBlock(IN PEPROCESS_QUOTA_BLOCK QuotaBlock)
MM::Quota::ReturnPoolQuota((MMPOOL_TYPE)Index, ReturnAmount); MM::Quota::ReturnPoolQuota((MMPOOL_TYPE)Index, ReturnAmount);
} }
} }
}
/* Unlink the quota block from the global tracking list */ /* Acquire a quota lock */
RTL::LinkedList::RemoveEntryList(&QuotaBlock->QuotaList); KE::SpinLockGuard SpinLock(&QuotaLock);
/* Unlink the quota block from the global tracking list */
RTL::LinkedList::RemoveEntryList(&QuotaBlock->QuotaList);
}
/* Free the physical memory */ /* Free the physical memory */
MM::Allocator::FreePool(QuotaBlock, TAG_PS_QUOTA_BLOCK); MM::Allocator::FreePool(QuotaBlock, TAG_PS_QUOTA_BLOCK);
@@ -98,15 +101,24 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
QuotaEntry = &QuotaBlock->QuotaEntry[QuotaType]; QuotaEntry = &QuotaBlock->QuotaEntry[QuotaType];
CurrentUsage = QuotaEntry->Usage; CurrentUsage = QuotaEntry->Usage;
/* Ensure quota usage does not exceed the limit */ /* Check if process provided */
if((Process != NULLPTR && Process->QuotaUsage[QuotaType] < Amount) || (CurrentUsage < Amount)) if(Process != NULLPTR)
{ {
/* Quota underflow detected, raise kernel panic */ /* Check if this is the system process */
KE::Crash::Panic(0x21, if(Process == PS::Process::GetSystemProcess())
(ULONG_PTR)Process, {
(ULONG_PTR)QuotaType, /* Do not do anything for system processes, return */
Process ? (ULONG_PTR)Process->QuotaUsage[QuotaType] : (ULONG_PTR)CurrentUsage, return;
(ULONG_PTR)Amount); }
else if(Process->QuotaUsage[QuotaType] < Amount || CurrentUsage < Amount)
{
/* Quota underflow detected, raise kernel panic */
KE::Crash::Panic(0x21,
(ULONG_PTR)Process,
(ULONG_PTR)QuotaType,
Process ? (ULONG_PTR)Process->QuotaUsage[QuotaType] : (ULONG_PTR)CurrentUsage,
(ULONG_PTR)Amount);
}
} }
/* Determine the thresholds for returning excess quota limit */ /* Determine the thresholds for returning excess quota limit */
@@ -126,8 +138,8 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
/* Attempt a lock-free update to shrink the quota limit */ /* Attempt a lock-free update to shrink the quota limit */
NewLimit = CurrentLimit - GiveBackAmount; NewLimit = CurrentLimit - GiveBackAmount;
ExpectedLimit = (SIZE_T)RTL::Atomic::CompareExchangePointer((PVOID*)&QuotaEntry->Limit, (PVOID)NewLimit, ExpectedLimit = (SIZE_T)RTL::Atomic::CompareExchange64((PLONG_PTR)&QuotaEntry->Limit, (LONG_PTR)NewLimit,
(PVOID)CurrentLimit); (LONG_PTR)CurrentLimit);
/* Check if the atomic limit update succeeded */ /* Check if the atomic limit update succeeded */
if(ExpectedLimit == CurrentLimit) if(ExpectedLimit == CurrentLimit)
@@ -139,7 +151,7 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
if(AccumulatedGiveBack > GiveBackLimit) if(AccumulatedGiveBack > GiveBackLimit)
{ {
/* Extract the accumulated return amount and reset the counter to zero */ /* Extract the accumulated return amount and reset the counter to zero */
ExtractedReturnAmount = (SIZE_T)RTL::Atomic::ExchangePointer((PVOID*)&QuotaEntry->Return, (PVOID)0); ExtractedReturnAmount = (SIZE_T)RTL::Atomic::Exchange64((PLONG_PTR)&QuotaEntry->Return, (LONG_PTR)0);
/* Check if there is anything to return */ /* Check if there is anything to return */
if(ExtractedReturnAmount > 0) if(ExtractedReturnAmount > 0)
@@ -156,7 +168,7 @@ PS::Quota::ReturnProcessQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
RTL::Atomic::Add64((PLONG_PTR)&QuotaEntry->Usage, (SIZE_T)(-(SSIZE_T)Amount)); RTL::Atomic::Add64((PLONG_PTR)&QuotaEntry->Usage, (SIZE_T)(-(SSIZE_T)Amount));
/* Check if a specific process was provided */ /* Check if a specific process was provided */
if(Process != NULLPTR) if(Process)
{ {
/* Decrease the process's specific usage count */ /* Decrease the process's specific usage count */
RTL::Atomic::Add64((PLONG_PTR)&Process->QuotaUsage[QuotaType], (SIZE_T)(-(SSIZE_T)Amount)); RTL::Atomic::Add64((PLONG_PTR)&Process->QuotaUsage[QuotaType], (SIZE_T)(-(SSIZE_T)Amount));
@@ -186,7 +198,7 @@ PS::Quota::ReturnSharedPoolQuota(IN PEPROCESS_QUOTA_BLOCK QuotaBlock,
IN SIZE_T NonPagedAmount) IN SIZE_T NonPagedAmount)
{ {
/* Check for NULL pointers and bypass markers */ /* Check for NULL pointers and bypass markers */
if(QuotaBlock == NULLPTR || QuotaBlock == (PEPROCESS_QUOTA_BLOCK)1) if(!QuotaBlock || QuotaBlock == PS_QUOTA_BYPASS_MARKER)
{ {
/* No quota tracking is required for the system process or empty blocks, return */ /* No quota tracking is required for the system process or empty blocks, return */
return; return;