2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ps/quota.c
5 * PURPOSE: Process Pool Quotas
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
11 /* INCLUDES **************************************************************/
17 EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock
;
20 /* Define this macro to enable quota code testing. Once quota code is */
21 /* stable and verified, remove this macro and checks for it. */
22 /*#define PS_QUOTA_ENABLE_QUOTA_CODE*/
25 /* PRIVATE FUNCTIONS *******************************************************/
27 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
30 * Private helper to charge the specified process quota.
31 * ReturnsSTATUS_QUOTA_EXCEEDED on quota limit check failure.
32 * Updates QuotaPeak as needed for specified PoolIndex.
33 * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
34 * to replace UCHAR for 'PoolIndex'.
35 * Notes: Conceptually translation unit local/private.
39 PspChargeProcessQuotaSpecifiedPool(IN PEPROCESS Process
,
44 ASSERT(Process
!= PsInitialSystemProcess
);
45 ASSERT(PoolIndex
<= 2);
46 ASSERT(Process
->QuotaBlock
);
48 /* Note: Race warning. TODO: Needs to add/use lock for this */
49 if (Process
->QuotaUsage
[PoolIndex
] + Amount
>
50 Process
->QuotaBlock
->QuotaEntry
[PoolIndex
].Limit
)
52 return STATUS_QUOTA_EXCEEDED
; /* caller raises the exception */
55 InterlockedExchangeAdd((LONG
*)&Process
->QuotaUsage
[PoolIndex
], Amount
);
57 /* Note: Race warning. TODO: Needs to add/use lock for this */
58 if (Process
->QuotaPeak
[PoolIndex
] < Process
->QuotaUsage
[PoolIndex
])
60 Process
->QuotaPeak
[PoolIndex
] = Process
->QuotaUsage
[PoolIndex
];
63 return STATUS_SUCCESS
;
68 * Private helper to remove quota charge from the specified process quota.
69 * TODO: Research and possibly add (the undocumented) enum type PS_QUOTA_TYPE
70 * to replace UCHAR for 'PoolIndex'.
71 * Notes: Conceptually translation unit local/private.
75 PspReturnProcessQuotaSpecifiedPool(IN PEPROCESS Process
,
80 ASSERT(Process
!= PsInitialSystemProcess
);
81 ASSERT(PoolIndex
<= 2);
82 ASSERT(!(Amount
& 0x80000000)); /* we need to be able to negate it */
83 if (Process
->QuotaUsage
[PoolIndex
] < Amount
)
85 DPRINT1("WARNING: Process->QuotaUsage sanity check failed.\n");
89 InterlockedExchangeAdd((LONG
*)&Process
->QuotaUsage
[PoolIndex
],
94 #endif /* PS_QUOTA_ENABLE_QUOTA_CODE */
97 /* FUNCTIONS ***************************************************************/
102 PsInitializeQuotaSystem(VOID
)
104 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
105 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
106 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
107 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
108 PsGetCurrentProcess()->QuotaBlock
= &PspDefaultQuotaBlock
;
113 PspInheritQuota(PEPROCESS Process
, PEPROCESS ParentProcess
)
115 if (ParentProcess
!= NULL
)
117 PEPROCESS_QUOTA_BLOCK QuotaBlock
= ParentProcess
->QuotaBlock
;
119 ASSERT(QuotaBlock
!= NULL
);
121 (void)InterlockedIncrementUL(&QuotaBlock
->ReferenceCount
);
123 Process
->QuotaBlock
= QuotaBlock
;
126 Process
->QuotaBlock
= &PspDefaultQuotaBlock
;
131 PspDestroyQuotaBlock(PEPROCESS Process
)
133 PEPROCESS_QUOTA_BLOCK QuotaBlock
= Process
->QuotaBlock
;
135 if (QuotaBlock
!= &PspDefaultQuotaBlock
&&
136 InterlockedDecrementUL(&QuotaBlock
->ReferenceCount
) == 0)
138 ExFreePool(QuotaBlock
);
144 PsChargeProcessPageFileQuota(IN PEPROCESS Process
,
147 /* Don't do anything for the system process */
148 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
150 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
151 return PspChargeProcessQuotaSpecifiedPool(Process
, 2, Amount
);
153 /* Otherwise, not implemented */
155 return STATUS_SUCCESS
;
164 PsChargePoolQuota(IN PEPROCESS Process
,
165 IN POOL_TYPE PoolType
,
170 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
171 /* MS-documented IRQL requirement. Not yet enabled as it */
172 /* needs verification that it does not break ReactOS, */
173 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL
);
176 /* Don't do anything for the system process */
177 if (Process
== PsInitialSystemProcess
) return;
179 /* Charge the usage */
180 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
181 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
189 PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process
,
192 /* Call the general function */
193 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
201 PsChargeProcessPagedPoolQuota(IN PEPROCESS Process
,
204 /* Call the general function */
205 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
213 PsChargeProcessPoolQuota(IN PEPROCESS Process
,
214 IN POOL_TYPE PoolType
,
217 /* Don't do anything for the system process */
218 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
220 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
221 return PspChargeProcessQuotaSpecifiedPool(Process
,
222 (PoolType
& PAGED_POOL_MASK
),
226 return STATUS_SUCCESS
;
235 PsReturnPoolQuota(IN PEPROCESS Process
,
236 IN POOL_TYPE PoolType
,
239 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
240 /* MS-documented IRQL requirement. Not yet enabled as it */
241 /* needs verification that it does not break ReactOS, */
242 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL
);
245 /* Don't do anything for the system process */
246 if (Process
== PsInitialSystemProcess
) return;
248 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
249 PspReturnProcessQuotaSpecifiedPool(Process
,
250 (PoolType
& PAGED_POOL_MASK
),
262 PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process
,
265 /* Don't do anything for the system process */
266 if (Process
== PsInitialSystemProcess
) return;
268 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
269 PsReturnPoolQuota(Process
, NonPagedPool
, Amount
);
280 PsReturnProcessPagedPoolQuota(IN PEPROCESS Process
,
283 /* Don't do anything for the system process */
284 if (Process
== PsInitialSystemProcess
) return;
286 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
287 PsReturnPoolQuota(Process
, PagedPool
, Amount
);
295 PsReturnProcessPageFileQuota(IN PEPROCESS Process
,
298 /* Don't do anything for the system process */
299 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
301 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
302 PspReturnProcessQuotaSpecifiedPool(Process
, 2, Amount
);
304 /* Otherwise, not implemented */
307 return STATUS_SUCCESS
;