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 ***************************************************************/
101 PsInitializeQuotaSystem(VOID
)
103 RtlZeroMemory(&PspDefaultQuotaBlock
, sizeof(PspDefaultQuotaBlock
));
104 PspDefaultQuotaBlock
.QuotaEntry
[PagedPool
].Limit
= (SIZE_T
)-1;
105 PspDefaultQuotaBlock
.QuotaEntry
[NonPagedPool
].Limit
= (SIZE_T
)-1;
106 PspDefaultQuotaBlock
.QuotaEntry
[2].Limit
= (SIZE_T
)-1; /* Page file */
107 PsGetCurrentProcess()->QuotaBlock
= &PspDefaultQuotaBlock
;
112 PspInheritQuota(PEPROCESS Process
, PEPROCESS ParentProcess
)
114 if (ParentProcess
!= NULL
)
116 PEPROCESS_QUOTA_BLOCK QuotaBlock
= ParentProcess
->QuotaBlock
;
118 ASSERT(QuotaBlock
!= NULL
);
120 (void)InterlockedIncrementUL(&QuotaBlock
->ReferenceCount
);
122 Process
->QuotaBlock
= QuotaBlock
;
125 Process
->QuotaBlock
= &PspDefaultQuotaBlock
;
130 PspDestroyQuotaBlock(PEPROCESS Process
)
132 PEPROCESS_QUOTA_BLOCK QuotaBlock
= Process
->QuotaBlock
;
134 if (QuotaBlock
!= &PspDefaultQuotaBlock
&&
135 InterlockedDecrementUL(&QuotaBlock
->ReferenceCount
) == 0)
137 ExFreePool(QuotaBlock
);
143 PsChargeProcessPageFileQuota(IN PEPROCESS Process
,
146 /* Don't do anything for the system process */
147 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
149 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
150 return PspChargeProcessQuotaSpecifiedPool(Process
, 2, Amount
);
152 /* Otherwise, not implemented */
154 return STATUS_SUCCESS
;
163 PsChargePoolQuota(IN PEPROCESS Process
,
164 IN POOL_TYPE PoolType
,
169 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
170 /* MS-documented IRQL requirement. Not yet enabled as it */
171 /* needs verification that it does not break ReactOS, */
172 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL
);
175 /* Don't do anything for the system process */
176 if (Process
== PsInitialSystemProcess
) return;
178 /* Charge the usage */
179 Status
= PsChargeProcessPoolQuota(Process
, PoolType
, Amount
);
180 if (!NT_SUCCESS(Status
)) ExRaiseStatus(Status
);
188 PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process
,
191 /* Call the general function */
192 return PsChargeProcessPoolQuota(Process
, NonPagedPool
, Amount
);
200 PsChargeProcessPagedPoolQuota(IN PEPROCESS Process
,
203 /* Call the general function */
204 return PsChargeProcessPoolQuota(Process
, PagedPool
, Amount
);
212 PsChargeProcessPoolQuota(IN PEPROCESS Process
,
213 IN POOL_TYPE PoolType
,
216 /* Don't do anything for the system process */
217 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
219 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
220 return PspChargeProcessQuotaSpecifiedPool(Process
,
221 (PoolType
& PAGED_POOL_MASK
),
225 return STATUS_SUCCESS
;
234 PsReturnPoolQuota(IN PEPROCESS Process
,
235 IN POOL_TYPE PoolType
,
238 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
239 /* MS-documented IRQL requirement. Not yet enabled as it */
240 /* needs verification that it does not break ReactOS, */
241 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL
);
244 /* Don't do anything for the system process */
245 if (Process
== PsInitialSystemProcess
) return;
247 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
248 PspReturnProcessQuotaSpecifiedPool(Process
,
249 (PoolType
& PAGED_POOL_MASK
),
261 PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process
,
264 /* Don't do anything for the system process */
265 if (Process
== PsInitialSystemProcess
) return;
267 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
268 PsReturnPoolQuota(Process
, NonPagedPool
, Amount
);
279 PsReturnProcessPagedPoolQuota(IN PEPROCESS Process
,
282 /* Don't do anything for the system process */
283 if (Process
== PsInitialSystemProcess
) return;
285 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
286 PsReturnPoolQuota(Process
, PagedPool
, Amount
);
294 PsReturnProcessPageFileQuota(IN PEPROCESS Process
,
297 /* Don't do anything for the system process */
298 if (Process
== PsInitialSystemProcess
) return STATUS_SUCCESS
;
300 #ifdef PS_QUOTA_ENABLE_QUOTA_CODE
301 PspReturnProcessQuotaSpecifiedPool(Process
, 2, Amount
);
303 /* Otherwise, not implemented */
306 return STATUS_SUCCESS
;