Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. zone.c
  5. Abstract:
  6. This module implements a simple zone buffer manager. The primary
  7. consumer of this module is local LPC.
  8. The zone package provides a fast and efficient memory allocator for
  9. fixed-size 64-bit aligned blocks of storage. The zone package does
  10. not provide any serialization over access to the zone header and
  11. associated free list and segment list. It is the responsibility of
  12. the caller to provide any necessary serialization.
  13. The zone package views a zone as a set of fixed-size blocks of
  14. storage. The block size of a zone is specified during zone
  15. initialization. Storage is assigned to a zone during zone
  16. initialization and when a zone is extended. In both of these cases,
  17. a segment and length are specified.
  18. The zone package uses the first ZONE_SEGMENT_HEADER portion of the
  19. segment for zone overhead. The remainder of the segment is carved
  20. up into fixed-size blocks and each block is added to the free list
  21. maintained in the zone header.
  22. As long as a block is on the free list, the first SINGLE_LIST_ENTRY
  23. (32 bit) sized piece of the block is used as zone overhead. The
  24. rest of the block is not used by the zone package and may be used by
  25. applications to cache information. When a block is not on the free
  26. list, its entire contents are available to the application.
  27. Author:
  28. Mark Lucovsky (markl) 13-May-1989
  29. Revision History:
  30. --*/
  31. #include "exp.h"
  32. NTSTATUS
  33. ExInitializeZone(
  34. IN PZONE_HEADER Zone,
  35. IN ULONG BlockSize,
  36. IN PVOID InitialSegment,
  37. IN ULONG InitialSegmentSize
  38. )
  39. /*++
  40. Routine Description:
  41. This function initializes a zone header. Once successfully
  42. initialized, blocks can be allocated and freed from the zone, and
  43. the zone can be extended.
  44. Arguments:
  45. Zone - Supplies the address of a zone header to be initialized.
  46. BlockSize - Supplies the block size of the allocatable unit within
  47. the zone. The size must be larger that the size of the
  48. initial segment, and must be 64-bit aligned.
  49. InitialSegment - Supplies the address of a segment of storage. The
  50. first ZONE_SEGMENT_HEADER-sized portion of the segment
  51. is used by the zone allocator. The remainder of
  52. the segment is carved up into fixed size
  53. (BlockSize) blocks and is made available for
  54. allocation and deallocation from the zone. The
  55. address of the segment must be aligned on a 64-bit
  56. boundary.
  57. InitialSegmentSize - Supplies the size in bytes of the InitialSegment.
  58. Return Value:
  59. STATUS_UNSUCCESSFUL - BlockSize or InitialSegment was not aligned on
  60. 64-bit boundaries, or BlockSize was larger than
  61. the initial segment size.
  62. STATUS_SUCCESS - The zone was successfully initialized.
  63. --*/
  64. {
  65. ULONG i;
  66. PCH p;
  67. if ( (BlockSize & 7) || ((ULONG_PTR)InitialSegment & 7) ||
  68. (BlockSize > InitialSegmentSize) ) {
  69. #if DBG
  70. DbgPrint( "EX: ExInitializeZone( %x, %x, %x, %x ) - Invalid parameters.\n",
  71. Zone, BlockSize, InitialSegment, InitialSegmentSize
  72. );
  73. DbgBreakPoint();
  74. #endif
  75. return STATUS_INVALID_PARAMETER;
  76. }
  77. Zone->BlockSize = BlockSize;
  78. Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList;
  79. ((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList.Next = NULL;
  80. ((PZONE_SEGMENT_HEADER) InitialSegment)->Reserved = NULL;
  81. Zone->FreeList.Next = NULL;
  82. p = (PCH)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);
  83. for (i = sizeof(ZONE_SEGMENT_HEADER);
  84. i <= InitialSegmentSize - BlockSize;
  85. i += BlockSize
  86. ) {
  87. ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
  88. Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
  89. p += BlockSize;
  90. }
  91. Zone->TotalSegmentSize = i;
  92. #if 0
  93. DbgPrint( "EX: ExInitializeZone( %lx, %lx, %lu, %lu, %lx )\n",
  94. Zone, InitialSegment, InitialSegmentSize,
  95. BlockSize, p
  96. );
  97. #endif
  98. return STATUS_SUCCESS;
  99. }
  100. NTSTATUS
  101. ExExtendZone(
  102. IN PZONE_HEADER Zone,
  103. IN PVOID Segment,
  104. IN ULONG SegmentSize
  105. )
  106. /*++
  107. Routine Description:
  108. This function extends a zone by adding another segment's worth of
  109. blocks to the zone.
  110. Arguments:
  111. Zone - Supplies the address of a zone header to be extended.
  112. Segment - Supplies the address of a segment of storage. The first
  113. ZONE_SEGMENT_HEADER-sized portion of the segment is used by the
  114. zone allocator. The remainder of the segment is carved up
  115. into fixed-size (BlockSize) blocks and is added to the
  116. zone. The address of the segment must be aligned on a 64-
  117. bit boundary.
  118. SegmentSize - Supplies the size in bytes of Segment.
  119. Return Value:
  120. STATUS_UNSUCCESSFUL - BlockSize or Segment was not aligned on
  121. 64-bit boundaries, or BlockSize was larger than
  122. the segment size.
  123. STATUS_SUCCESS - The zone was successfully extended.
  124. --*/
  125. {
  126. ULONG i;
  127. PCH p;
  128. if ( ((ULONG_PTR)Segment & 7) ||
  129. (SegmentSize & 7) ||
  130. (Zone->BlockSize > SegmentSize) ) {
  131. return STATUS_UNSUCCESSFUL;
  132. }
  133. ((PZONE_SEGMENT_HEADER) Segment)->SegmentList.Next = Zone->SegmentList.Next;
  134. Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) Segment)->SegmentList;
  135. p = (PCH)Segment + sizeof(ZONE_SEGMENT_HEADER);
  136. for (i = sizeof(ZONE_SEGMENT_HEADER);
  137. i <= SegmentSize - Zone->BlockSize;
  138. i += Zone->BlockSize
  139. ) {
  140. ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
  141. Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
  142. p += Zone->BlockSize;
  143. }
  144. Zone->TotalSegmentSize += i;
  145. #if 0
  146. DbgPrint( "EX: ExExtendZone( %lx, %lx, %lu, %lu, %lx )\n",
  147. Zone, Segment, SegmentSize, Zone->BlockSize, p
  148. );
  149. #endif
  150. return STATUS_SUCCESS;
  151. }
  152. NTSTATUS
  153. ExInterlockedExtendZone(
  154. IN PZONE_HEADER Zone,
  155. IN PVOID Segment,
  156. IN ULONG SegmentSize,
  157. IN PKSPIN_LOCK Lock
  158. )
  159. /*++
  160. Routine Description:
  161. This function extends a zone by adding another segment's worth of
  162. blocks to the zone.
  163. Arguments:
  164. Zone - Supplies the address of a zone header to be extended.
  165. Segment - Supplies the address of a segment of storage. The first
  166. ZONE_SEGMENT_HEADER-sized portion of the segment is used by the
  167. zone allocator. The remainder of the segment is carved up
  168. into fixed-size (BlockSize) blocks and is added to the
  169. zone. The address of the segment must be aligned on a 64-
  170. bit boundary.
  171. SegmentSize - Supplies the size in bytes of Segment.
  172. Lock - pointer to spinlock to use
  173. Return Value:
  174. STATUS_UNSUCCESSFUL - BlockSize or Segment was not aligned on
  175. 64-bit boundaries, or BlockSize was larger than
  176. the segment size.
  177. STATUS_SUCCESS - The zone was successfully extended.
  178. --*/
  179. {
  180. NTSTATUS Status;
  181. KIRQL OldIrql;
  182. #ifdef NT_UP
  183. UNREFERENCED_PARAMETER (Lock);
  184. #endif
  185. ExAcquireSpinLock( Lock, &OldIrql );
  186. Status = ExExtendZone( Zone, Segment, SegmentSize );
  187. ExReleaseSpinLock( Lock, OldIrql );
  188. return Status;
  189. }