reactos/ntoskrnl/ps/quota.c

311 lines
7.9 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ps/quota.c
* PURPOSE: Process Pool Quotas
*
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Mike Nordell
*/
/* INCLUDES **************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
- Fix one of the oldest hacks in ReactOS: KeGetCurrentThread() and PsGetcurrentProcess used to be NULL during early boot stage. We also didn't have an official idle therad/process. Also system intialization was not in its sepearte thread. Changes: - Implemented SeAssignPrimaryToken. - Setup Boot/System Token for Idle Process in SeInit2. - Remove ROS hack in SeCaptureSubjectContextEx. - Call SeAssignPrimaryToken in PspInitializeProcessSecurty when called for the Initial Process creation. - Implement PsInitiailizeQuotaSystem and set PspDefauptQuotaBlock for the idle process so that it can be used for the initial process. - Rewrite Process Manager Phase 0 initialization from scratch, to create a new initial system process and thread which will be used for Phase 1 (in ROS, phase 2) initialization of the executive. - Fix a bug in PspCreateProcess which was using an uninitialized value of SectionObject in some cases, instead of NULL. - Call PsInitailizeQuotaSystem from ObInit, and also create the system handle table inside the idle process, and make it the ObpKernelHandleTable. - Do Executive Phase 0 Initialization at APC_LEVEL. - Start idle thread at HIGH_PRIORITY then lower it to 0 once the Initial Thread is setup, so that it can run, then keep priority to 0 at DISPATCH_LEVEL and jump into idle loop code. - Add NtYieldExecution to idle loop code since it's now being used. - Fix IoGetCurrentProcess which was previously hacked. - Remove some checks for Thread == NULL in ke_x.h, since this is now impossible. - Split Phase 0/1 initialization in ex\init.c, since one runs in a separate thread now. Also don't lower IRQL to PASSIVE_LEVEL anymore (run at APC_LEVEL). svn path=/trunk/; revision=24148
2006-09-16 20:37:49 +00:00
EPROCESS_QUOTA_BLOCK PspDefaultQuotaBlock;
/* 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 SIZE_T 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 SIZE_T 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 ***************************************************************/
- Fix one of the oldest hacks in ReactOS: KeGetCurrentThread() and PsGetcurrentProcess used to be NULL during early boot stage. We also didn't have an official idle therad/process. Also system intialization was not in its sepearte thread. Changes: - Implemented SeAssignPrimaryToken. - Setup Boot/System Token for Idle Process in SeInit2. - Remove ROS hack in SeCaptureSubjectContextEx. - Call SeAssignPrimaryToken in PspInitializeProcessSecurty when called for the Initial Process creation. - Implement PsInitiailizeQuotaSystem and set PspDefauptQuotaBlock for the idle process so that it can be used for the initial process. - Rewrite Process Manager Phase 0 initialization from scratch, to create a new initial system process and thread which will be used for Phase 1 (in ROS, phase 2) initialization of the executive. - Fix a bug in PspCreateProcess which was using an uninitialized value of SectionObject in some cases, instead of NULL. - Call PsInitailizeQuotaSystem from ObInit, and also create the system handle table inside the idle process, and make it the ObpKernelHandleTable. - Do Executive Phase 0 Initialization at APC_LEVEL. - Start idle thread at HIGH_PRIORITY then lower it to 0 once the Initial Thread is setup, so that it can run, then keep priority to 0 at DISPATCH_LEVEL and jump into idle loop code. - Add NtYieldExecution to idle loop code since it's now being used. - Fix IoGetCurrentProcess which was previously hacked. - Remove some checks for Thread == NULL in ke_x.h, since this is now impossible. - Split Phase 0/1 initialization in ex\init.c, since one runs in a separate thread now. Also don't lower IRQL to PASSIVE_LEVEL anymore (run at APC_LEVEL). svn path=/trunk/; revision=24148
2006-09-16 20:37:49 +00:00
VOID
NTAPI
INIT_FUNCTION
- Fix one of the oldest hacks in ReactOS: KeGetCurrentThread() and PsGetcurrentProcess used to be NULL during early boot stage. We also didn't have an official idle therad/process. Also system intialization was not in its sepearte thread. Changes: - Implemented SeAssignPrimaryToken. - Setup Boot/System Token for Idle Process in SeInit2. - Remove ROS hack in SeCaptureSubjectContextEx. - Call SeAssignPrimaryToken in PspInitializeProcessSecurty when called for the Initial Process creation. - Implement PsInitiailizeQuotaSystem and set PspDefauptQuotaBlock for the idle process so that it can be used for the initial process. - Rewrite Process Manager Phase 0 initialization from scratch, to create a new initial system process and thread which will be used for Phase 1 (in ROS, phase 2) initialization of the executive. - Fix a bug in PspCreateProcess which was using an uninitialized value of SectionObject in some cases, instead of NULL. - Call PsInitailizeQuotaSystem from ObInit, and also create the system handle table inside the idle process, and make it the ObpKernelHandleTable. - Do Executive Phase 0 Initialization at APC_LEVEL. - Start idle thread at HIGH_PRIORITY then lower it to 0 once the Initial Thread is setup, so that it can run, then keep priority to 0 at DISPATCH_LEVEL and jump into idle loop code. - Add NtYieldExecution to idle loop code since it's now being used. - Fix IoGetCurrentProcess which was previously hacked. - Remove some checks for Thread == NULL in ke_x.h, since this is now impossible. - Split Phase 0/1 initialization in ex\init.c, since one runs in a separate thread now. Also don't lower IRQL to PASSIVE_LEVEL anymore (run at APC_LEVEL). svn path=/trunk/; revision=24148
2006-09-16 20:37:49 +00:00
PsInitializeQuotaSystem(VOID)
{
RtlZeroMemory(&PspDefaultQuotaBlock, sizeof(PspDefaultQuotaBlock));
PspDefaultQuotaBlock.QuotaEntry[PagedPool].Limit = (SIZE_T)-1;
PspDefaultQuotaBlock.QuotaEntry[NonPagedPool].Limit = (SIZE_T)-1;
PspDefaultQuotaBlock.QuotaEntry[2].Limit = (SIZE_T)-1; /* Page file */
PsGetCurrentProcess()->QuotaBlock = &PspDefaultQuotaBlock;
}
VOID
NTAPI
PspInheritQuota(PEPROCESS Process, PEPROCESS ParentProcess)
{
if (ParentProcess != NULL)
{
PEPROCESS_QUOTA_BLOCK QuotaBlock = ParentProcess->QuotaBlock;
ASSERT(QuotaBlock != NULL);
(void)InterlockedIncrementUL(&QuotaBlock->ReferenceCount);
Process->QuotaBlock = QuotaBlock;
}
else
Process->QuotaBlock = &PspDefaultQuotaBlock;
}
VOID
NTAPI
PspDestroyQuotaBlock(PEPROCESS Process)
{
PEPROCESS_QUOTA_BLOCK QuotaBlock = Process->QuotaBlock;
if (QuotaBlock != &PspDefaultQuotaBlock &&
InterlockedDecrementUL(&QuotaBlock->ReferenceCount) == 0)
{
ExFreePool(QuotaBlock);
}
}
NTSTATUS
NTAPI
PsChargeProcessPageFileQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
return PspChargeProcessQuotaSpecifiedPool(Process, 2, Amount);
#else
/* Otherwise, not implemented */
UNIMPLEMENTED;
return STATUS_SUCCESS;
#endif
}
/*
* @implemented
*/
VOID
NTAPI
PsChargePoolQuota(IN PEPROCESS Process,
IN POOL_TYPE PoolType,
IN SIZE_T Amount)
{
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);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PsChargeProcessNonPagedPoolQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Call the general function */
return PsChargeProcessPoolQuota(Process, NonPagedPool, Amount);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PsChargeProcessPagedPoolQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Call the general function */
return PsChargeProcessPoolQuota(Process, PagedPool, Amount);
}
/*
* @implemented
*/
NTSTATUS
NTAPI
PsChargeProcessPoolQuota(IN PEPROCESS Process,
IN POOL_TYPE PoolType,
IN SIZE_T Amount)
{
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
return PspChargeProcessQuotaSpecifiedPool(Process,
(PoolType & PAGED_POOL_MASK),
Amount);
#else
UNIMPLEMENTED;
return STATUS_SUCCESS;
#endif
}
/*
* @unimplemented
*/
VOID
NTAPI
PsReturnPoolQuota(IN PEPROCESS Process,
IN POOL_TYPE PoolType,
IN SIZE_T Amount)
{
#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;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
PspReturnProcessQuotaSpecifiedPool(Process,
(PoolType & PAGED_POOL_MASK),
Amount);
#else
UNIMPLEMENTED;
#endif
}
/*
* @unimplemented
*/
VOID
NTAPI
PsReturnProcessNonPagedPoolQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
PsReturnPoolQuota(Process, NonPagedPool, Amount);
#else
UNIMPLEMENTED;
#endif
}
/*
* @unimplemented
*/
VOID
NTAPI
PsReturnProcessPagedPoolQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
PsReturnPoolQuota(Process, PagedPool, Amount);
#else
UNIMPLEMENTED;
#endif
}
NTSTATUS
NTAPI
PsReturnProcessPageFileQuota(IN PEPROCESS Process,
IN SIZE_T Amount)
{
/* Don't do anything for the system process */
if (Process == PsInitialSystemProcess) return STATUS_SUCCESS;
#ifdef PS_QUOTA_ENABLE_QUOTA_CODE
PspReturnProcessQuotaSpecifiedPool(Process, 2, Amount);
#else
/* Otherwise, not implemented */
UNIMPLEMENTED;
#endif
return STATUS_SUCCESS;
}
/* EOF */