1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/ex/zone.c 5 * PURPOSE: Implements zone buffers 6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 7 * David Welch (welch@mcmail.com) 8 */ 9 10 /* INCLUDES ****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS ***************************************************************/ 17 18 /* 19 * @implemented 20 */ 21 NTSTATUS 22 NTAPI 23 ExExtendZone(PZONE_HEADER Zone, 24 PVOID Segment, 25 ULONG SegmentSize) 26 { 27 ULONG_PTR Entry; 28 ULONG i; 29 30 /* 31 * BlockSize and Segment must be 8-byte aligned. 32 * Blocksize cannot exceed Segment Size. 33 */ 34 if (((ULONG_PTR)Segment & 7) || 35 (SegmentSize & 7) || 36 (Zone->BlockSize > SegmentSize)) 37 { 38 DPRINT1("Invalid ExExtendZone Alignment and/or Size\n"); 39 return STATUS_INVALID_PARAMETER; 40 } 41 42 /* Link the Zone and Segment */ 43 PushEntryList(&Zone->SegmentList, 44 &((PZONE_SEGMENT_HEADER)Segment)->SegmentList); 45 46 /* Get to the first entry */ 47 Entry = (ULONG_PTR)Segment + sizeof(ZONE_SEGMENT_HEADER); 48 49 /* Loop through the segments */ 50 for (i = sizeof(ZONE_SEGMENT_HEADER); 51 i <= SegmentSize - Zone->BlockSize; 52 i+= Zone->BlockSize) 53 { 54 /* Link the Free and Segment Lists */ 55 PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry); 56 57 /* Go to the next entry */ 58 Entry += Zone->BlockSize; 59 } 60 61 /* Update Segment Size */ 62 Zone->TotalSegmentSize += i; 63 64 /* Return Success */ 65 return STATUS_SUCCESS; 66 } 67 68 /* 69 * @implemented 70 */ 71 NTSTATUS 72 NTAPI 73 ExInterlockedExtendZone(PZONE_HEADER Zone, 74 PVOID Segment, 75 ULONG SegmentSize, 76 PKSPIN_LOCK Lock) 77 { 78 NTSTATUS Status; 79 KIRQL OldIrql; 80 81 /* Get the lock */ 82 KeAcquireSpinLock(Lock, &OldIrql); 83 84 /* Extend the Zone */ 85 Status = ExExtendZone(Zone, Segment, SegmentSize); 86 87 /* Release lock and return status */ 88 KeReleaseSpinLock(Lock, OldIrql); 89 return Status; 90 } 91 92 /* 93 * FUNCTION: Initializes a zone header 94 * ARGUMENTS: 95 * Zone = zone header to be initialized 96 * BlockSize = Size (in bytes) of the allocation size of the zone 97 * InitialSegment = Initial segment of storage allocated by the 98 * caller 99 * InitialSegmentSize = Initial size of the segment 100 * 101 * @implemented 102 */ 103 NTSTATUS 104 NTAPI 105 ExInitializeZone(PZONE_HEADER Zone, 106 ULONG BlockSize, 107 PVOID InitialSegment, 108 ULONG InitialSegmentSize) 109 { 110 ULONG i; 111 ULONG_PTR Entry; 112 113 /* 114 * BlockSize and Segment must be 8-byte aligned. 115 * Blocksize cannot exceed Segment Size. 116 */ 117 if (((ULONG_PTR)InitialSegment & 7) || 118 (InitialSegmentSize & 7) || 119 (BlockSize > InitialSegmentSize)) 120 { 121 DPRINT1("Invalid ExInitializeZone Alignment and/or Size\n"); 122 return STATUS_INVALID_PARAMETER; 123 } 124 125 /* Set the Zone Header */ 126 Zone->BlockSize = BlockSize; 127 128 /* Link empty list */ 129 Zone->FreeList.Next = NULL; 130 Zone->SegmentList.Next = NULL; 131 PushEntryList(&Zone->SegmentList, 132 &((PZONE_SEGMENT_HEADER)InitialSegment)->SegmentList); 133 ((PZONE_SEGMENT_HEADER)InitialSegment)->Reserved = NULL; 134 135 /* Get first entry */ 136 Entry = (ULONG_PTR)InitialSegment + sizeof(ZONE_SEGMENT_HEADER); 137 138 /* Loop through the segments */ 139 for (i = sizeof(ZONE_SEGMENT_HEADER); 140 i <= InitialSegmentSize - BlockSize; 141 i+= BlockSize) 142 { 143 /* Link the Free and Segment Lists */ 144 PushEntryList(&Zone->FreeList, (PSINGLE_LIST_ENTRY)Entry); 145 146 /* Go to the next entry */ 147 Entry += Zone->BlockSize; 148 } 149 150 /* Set Segment Size */ 151 Zone->TotalSegmentSize = i; 152 153 /* Return success */ 154 return STATUS_SUCCESS; 155 } 156 157 /* EOF */ 158