reactos/ntoskrnl/ex/zone.c
Cameron Gutman c2d0d784c7 [USB-BRINGUP-TRUNK]
- Create a branch to do a proper merge of USB work from a trunk base instead of from cmake-bringup
- In the future, DO NOT under any circumstances branch another branch. This leads to merge problems!

svn path=/branches/usb-bringup-trunk/; revision=55018
2012-01-20 20:58:46 +00:00

157 lines
3.9 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ex/zone.c
* PURPOSE: Implements zone buffers
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* David Welch (welch@mcmail.com)
*/
/* INCLUDES ****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS ***************************************************************/
/*
* @implemented
*/
NTSTATUS
NTAPI
ExExtendZone(PZONE_HEADER Zone,
PVOID Segment,
ULONG SegmentSize)
{
ULONG_PTR Entry;
ULONG i;
/*
* BlockSize and Segment must be 8-byte aligned.
* Blocksize cannot exceed Segment Size.
*/
if (((ULONG_PTR)Segment & 7) ||
(SegmentSize & 7) ||
(Zone->BlockSize > SegmentSize))
{
DPRINT1("Invalid ExExtendZone Alignment and/or Size\n");
return STATUS_INVALID_PARAMETER;
}
/* Link the Zone and Segment */
PushEntryList(&Zone->SegmentList,
&((PZONE_SEGMENT_HEADER)Segment)->SegmentList);
/* Get to the first entry */
Entry = (ULONG_PTR)Segment + sizeof(ZONE_SEGMENT_HEADER);
/* Loop through the segments */
for (i = sizeof(ZONE_SEGMENT_HEADER);
i <= SegmentSize - Zone->BlockSize;
i+= Zone->BlockSize)
{
/* Link the Free and Segment Lists */
PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry);
/* Go to the next entry */
Entry += Zone->BlockSize;
}
/* Update Segment Size */
Zone->TotalSegmentSize += i;
/* Return Success */
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
ExInterlockedExtendZone(PZONE_HEADER Zone,
PVOID Segment,
ULONG SegmentSize,
PKSPIN_LOCK Lock)
{
NTSTATUS Status;
KIRQL OldIrql;
/* Get the lock */
KeAcquireSpinLock(Lock, &OldIrql);
/* Extend the Zone */
Status = ExExtendZone(Zone, Segment, SegmentSize);
/* Release lock and return status */
KeReleaseSpinLock(Lock, OldIrql);
return Status;
}
/*
* FUNCTION: Initalizes a zone header
* ARGUMENTS:
* Zone = zone header to be initialized
* BlockSize = Size (in bytes) of the allocation size of the zone
* InitialSegment = Initial segment of storage allocated by the
* caller
* InitialSegmentSize = Initial size of the segment
*
* @implemented
*/
NTSTATUS
NTAPI
ExInitializeZone(PZONE_HEADER Zone,
ULONG BlockSize,
PVOID InitialSegment,
ULONG InitialSegmentSize)
{
ULONG i;
ULONG_PTR Entry;
/*
* BlockSize and Segment must be 8-byte aligned.
* Blocksize cannot exceed Segment Size.
*/
if (((ULONG_PTR)InitialSegment & 7) ||
(InitialSegmentSize & 7) ||
(BlockSize > InitialSegmentSize))
{
DPRINT1("Invalid ExInitializeZone Alignment and/or Size\n");
return STATUS_INVALID_PARAMETER;
}
/* Set the Zone Header */
Zone->BlockSize = BlockSize;
/* Link empty list */
Zone->FreeList.Next = NULL;
Zone->SegmentList.Next = NULL;
PushEntryList(&Zone->SegmentList,
&((PZONE_SEGMENT_HEADER)InitialSegment)->SegmentList);
((PZONE_SEGMENT_HEADER)InitialSegment)->Reserved = NULL;
/* Get first entry */
Entry = (ULONG_PTR)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);
/* Loop through the segments */
for (i = sizeof(ZONE_SEGMENT_HEADER);
i <= InitialSegmentSize - BlockSize;
i+= BlockSize)
{
/* Link the Free and Segment Lists */
PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry);
/* Go to the next entry */
Entry += Zone->BlockSize;
}
/* Update Segment Size */
Zone->TotalSegmentSize += i;
/* Return success */
return STATUS_SUCCESS;
}
/* EOF */