Author: mnordell
Date: Thu Oct 25 16:31:55 2007
New Revision: 29875
URL:
http://svn.reactos.org/svn/reactos?rev=29875&view=rev
Log:
Quota cleanup. IRQL verfications for public functions. Still macro-protected and defaults
to disabled.
Modified:
trunk/reactos/ntoskrnl/ps/quota.c
Modified: trunk/reactos/ntoskrnl/ps/quota.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/quota.c?rev=29…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/quota.c (original)
+++ trunk/reactos/ntoskrnl/ps/quota.c Thu Oct 25 16:31:55 2007
@@ -5,6 +5,7 @@
* PURPOSE: Process Pool Quotas
*
* PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ * Mike Nordell
*/
/* INCLUDES **************************************************************/
@@ -19,6 +20,78 @@
/* Define this macro to enable quota code testing. Once quota code is */
/* stable and verified, remove this macro and checks for it. */
/*#define PS_QUOTA_ENABLE_QUOTA_CODE*/
+
+
+/* PRIVATE FUNCTIONS *******************************************************/
+
+#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
+
+/*
+ * Private helper to charge the specified process quota.
+ * ReturnsSTATUS_QUOTA_EXCEEDED on quota limit check failure.
+ * Updates QuotaPeak as needed for specified PoolIndex.
+ * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
+ * to replace UCHAR for 'PoolIndex'.
+ * Notes: Conceptually translation unit local/private.
+ */
+NTSTATUS
+NTAPI
+PspChargeProcessQuotaSpecifiedPool(IN PEPROCESS Process,
+ IN UCHAR PoolIndex,
+ IN ULONG Amount)
+{
+ ASSERT(Process);
+ ASSERT(Process != PsInitialSystemProcess);
+ ASSERT(PoolIndex <= 2);
+ ASSERT(Process->QuotaBlock);
+
+ /* Note: Race warning. TODO: Needs to add/use lock for this */
+ if (Process->QuotaUsage[PoolIndex] + Amount >
+ Process->QuotaBlock->QuotaEntry[PoolIndex].Limit)
+ {
+ return STATUS_QUOTA_EXCEEDED; /* caller raises the exception */
+ }
+
+ InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex], Amount);
+
+ /* Note: Race warning. TODO: Needs to add/use lock for this */
+ if (Process->QuotaPeak[PoolIndex] < Process->QuotaUsage[PoolIndex])
+ {
+ Process->QuotaPeak[PoolIndex] = Process->QuotaUsage[PoolIndex];
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+/*
+ * Private helper to remove quota charge from the specified process quota.
+ * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
+ * to replace UCHAR for 'PoolIndex'.
+ * Notes: Conceptually translation unit local/private.
+ */
+VOID
+NTAPI
+PspReturnProcessQuotaSpecifiedPool(IN PEPROCESS Process,
+ IN UCHAR PoolIndex,
+ IN ULONG Amount)
+{
+ ASSERT(Process);
+ ASSERT(Process != PsInitialSystemProcess);
+ ASSERT(PoolIndex <= 2);
+ ASSERT(!(Amount & 0x80000000)); /* we need to be able to negate it */
+ if (Process->QuotaUsage[PoolIndex] < Amount)
+ {
+ DPRINT1("WARNING: Process->QuotaUsage sanity check failed.\n");
+ }
+ else
+ {
+ InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex],
+ -(LONG)Amount);
+ }
+}
+
+#endif /* PS_QUOTA_ENABLE_QUOTA_CODE */
/* FUNCTIONS ***************************************************************/
@@ -74,33 +147,17 @@
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- if (Process)
- {
- /* TODO: Check with Process->QuotaBlock if this can be satisfied, */
- /* assuming this indeed is the place to check it. */
- /* Probably something like:
- if (Process->QuotaUsage[2] + Amount >
- Process->QuotaBlock->QuotaEntry[2].Limit)
- {
- refuse
- }
- */
- InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[2], Amount);
- /* Note: possibility for race. */
- if (Process->QuotaPeak[2] < Process->QuotaUsage[2])
- {
- Process->QuotaPeak[2] = Process->QuotaUsage[2];
- }
- }
+ return PspChargeProcessQuotaSpecifiedPool(Process, 2, Amount);
#else
/* Otherwise, not implemented */
UNIMPLEMENTED;
-#endif
return STATUS_SUCCESS;
+#endif
}
/*
* @implemented
+ * Publically documented and exported.
*/
VOID
STDCALL
@@ -110,9 +167,15 @@
{
NTSTATUS Status;
+#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
+ /* MS-documented IRQL requirement. Not yet enabled as it */
+ /* needs verification that it does not break ReactOS, */
+ ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
+#endif
+
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return;
-
+
/* Charge the usage */
Status = PsChargeProcessPoolQuota(Process, PoolType, Amount);
if (!NT_SUCCESS(Status)) ExRaiseStatus(Status);
@@ -142,38 +205,6 @@
return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
}
-#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
-/*
- * Internal helper function.
- * Returns the index of the Quota* member in EPROCESS for
- * a specified pool type, or -1 on failure.
- */
-static
-INT
-PspPoolQuotaIndexFromPoolType(POOL_TYPE PoolType)
-{
- switch (PoolType)
- {
- case NonPagedPool:
- case NonPagedPoolMustSucceed:
- case NonPagedPoolCacheAligned:
- case NonPagedPoolCacheAlignedMustS:
- case NonPagedPoolSession:
- case NonPagedPoolMustSucceedSession:
- case NonPagedPoolCacheAlignedSession:
- case NonPagedPoolCacheAlignedMustSSession:
- return 1;
- case PagedPool:
- case PagedPoolCacheAligned:
- case PagedPoolSession:
- case PagedPoolCacheAlignedSession:
- return 0;
- default:
- return -1;
- }
-}
-#endif
-
/*
* @implemented
*/
@@ -183,41 +214,22 @@
IN POOL_TYPE PoolType,
IN ULONG Amount)
{
-#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- INT PoolIndex;
-#endif
-
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- PoolIndex = PspPoolQuotaIndexFromPoolType(PoolType);
- if (Process && PoolIndex != -1)
- {
- /* TODO: Check with Process->QuotaBlock if this can be satisfied, */
- /* assuming this indeed is the place to check it. */
- /* Probably something like:
- if (Process->QuotaUsage[PoolIndex] + Amount >
- Process->QuotaBlock->QuotaEntry[PoolIndex].Limit)
- {
- refuse
- }
- */
- InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex], Amount);
- /* Note: possibility for race. */
- if (Process->QuotaPeak[PoolIndex] < Process->QuotaUsage[PoolIndex])
- {
- Process->QuotaPeak[PoolIndex] = Process->QuotaUsage[PoolIndex];
- }
- }
-#else
- UNIMPLEMENTED;
-#endif
+ return PspChargeProcessQuotaSpecifiedPool(Process,
+ (PoolType & PAGED_POOL_MASK),
+ Amount);
+#else
+ UNIMPLEMENTED;
return STATUS_SUCCESS;
+#endif
}
/*
* @unimplemented
+ * Publically documented and exported.
*/
VOID
STDCALL
@@ -226,25 +238,18 @@
IN ULONG_PTR Amount)
{
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- INT PoolIndex;
+ /* MS-documented IRQL requirement. Not yet enabled as it */
+ /* needs verification that it does not break ReactOS, */
+ ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
#endif
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- PoolIndex = PspPoolQuotaIndexFromPoolType(PoolType);
- if (Process && PoolIndex != -1)
- {
- if (Process->QuotaUsage[PoolIndex] < Amount)
- {
- DPRINT1("WARNING: Process->QuotaUsage sanity check failed.\n");
- }
- else
- {
- InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[PoolIndex],
-Amount);
- }
- }
+ PspReturnProcessQuotaSpecifiedPool(Process,
+ (PoolType & PAGED_POOL_MASK),
+ Amount);
#else
UNIMPLEMENTED;
#endif
@@ -295,17 +300,7 @@
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
- if (Process)
- {
- if (Process->QuotaUsage[2] < Amount)
- {
- DPRINT1("WARNING: Process PageFileQuotaUsage sanity check
failed.\n");
- }
- else
- {
- InterlockedExchangeAdd((LONG*)&Process->QuotaUsage[2], -Amount);
- }
- }
+ PspReturnProcessQuotaSpecifiedPool(Process, 2, Amount);
#else
/* Otherwise, not implemented */
UNIMPLEMENTED;