Leaked source code of windows server 2003
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.

187 lines
5.8 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. heap.c
  5. Abstract:
  6. Contains a heap allocator function.
  7. Author:
  8. Dan Lafferty (danl) 10-Jul-1991
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 10-Jul-1991 danl
  13. Ported from LM2.0
  14. --*/
  15. // static char *SCCSID = "@(#)heap.c 9.1 86/10/12";
  16. //
  17. // Simple heap allocator for small heaps in shared memory areas.
  18. //
  19. #include <windef.h> // USHORT definitions
  20. #include <heap.h> // Constants, macros, etc.
  21. #include <align.h> // ROUND_UP_COUNT
  22. LPBYTE heap = 0; // Pointer to start of heap
  23. DWORD heapln = 0; // Length of heap
  24. /*
  25. * Msgheapalloc - simple heap allocator
  26. *
  27. * This function allocates blocks out of a far heap.
  28. * It assumes that when it is called the static variable
  29. * heap points to the far heap and the static variable heapln
  30. * contains the length of the far heap.
  31. *
  32. * Msgheapalloc (cb)
  33. *
  34. * ENTRY
  35. * cb - number of bytes to allocate including header
  36. *
  37. * RETURN
  38. * index in far heap to start of block of length cb, or
  39. * INULL if no such block can be found or if cb < sizeof(HEAPHDR).
  40. *
  41. * This function maintains a heap in which all
  42. * blocks are implicitly linked. The header of a block is
  43. * three bytes long. It contains the size of the block including
  44. * the header and a one-byte flag which indicates whether the block
  45. * is allocated or not. Any non-zero value indicates that a block
  46. * is allocated. Note: Msgheapalloc() does NOT set the flag when it
  47. * returns a block. It is up to the caller to mark a block as
  48. * allocated. Unlike most heap allocators, Msgheapalloc() returns a
  49. * pointer (index) to the header rather than just past the header.
  50. * It does this because the message logging routines will need to
  51. * know the lengths of blocks they process. Also, in addition to
  52. * indicating that a block is allocated, the flag byte will be used
  53. * to indicate the type of the block (i.e. single block message,
  54. * multi-block message header, etc.). Since the logging routines
  55. * will use the size of a block, it must be exactly the size
  56. * requested.
  57. *
  58. * The algorithm used was chosen to minimize the size of the
  59. * heap managing routines and to conform to the requirements
  60. * of the logging routines.
  61. *
  62. * SIDE EFFECTS
  63. *
  64. * Changes the structure of the heap.
  65. */
  66. DWORD
  67. Msgheapalloc(
  68. IN DWORD NumBytes // No. of bytes to allocate
  69. )
  70. {
  71. DWORD i; // Index to return
  72. DWORD newi; // New block index
  73. DWORD nexti; // Next block index
  74. DWORD numBytesNew; // New block size
  75. //
  76. // Must request at least siz bytes
  77. //
  78. if(NumBytes < sizeof(HEAPHDR)) {
  79. return(INULL);
  80. }
  81. //
  82. // *ALIGNMENT*
  83. // If necessary, increase the requested size to cause the allocated
  84. // block to fall on a 4-byte aligned boundary.
  85. //
  86. NumBytes = ROUND_UP_COUNT(NumBytes,4);
  87. //
  88. // This loop is used to traverse the heap by following the
  89. // chain of blocks until either the end of the heap is reached
  90. // or a free block of suitable size is found. Coalescing of
  91. // adjacent free blocks is performed herein also.
  92. //
  93. //
  94. // Loop to allocate block
  95. //
  96. for(i = 0; i < heapln; i += HP_SIZE(*HPTR(i))) {
  97. //
  98. // If free block found (hp_flag=0 indicates free),
  99. //
  100. if(HP_FLAG(*HPTR(i)) == 0) {
  101. //
  102. // A free block was found.
  103. // At this point, check to see if the current block can be
  104. // coalesced with the next block. We start with the offset of
  105. // the current block.
  106. nexti = i;
  107. //
  108. // Add to it the size of the next consecutive
  109. // free blocks until we reach the end of the heap, or an
  110. // allocated block is found.
  111. //
  112. while( (nexti < heapln) && (HP_FLAG(*HPTR(nexti))==0) ) {
  113. nexti += HP_SIZE(*HPTR(nexti));
  114. }
  115. //
  116. // Coalesce blocks all free blocks found thus far
  117. //
  118. HP_SIZE(*HPTR(i)) = nexti - i;
  119. //
  120. // At this point, attempt to allocate from the current
  121. // free block. The current free block must be exactly
  122. // the size we want or large enough to split, since we
  123. // must return a block whose size is EXACTLY the size
  124. // requested.
  125. //
  126. if(HP_SIZE(*HPTR(i)) == NumBytes) {
  127. //
  128. // Size is perfect
  129. //
  130. return(i);
  131. }
  132. if(HP_SIZE(*HPTR(i)) >= NumBytes + sizeof(HEAPHDR)) {
  133. //
  134. // If block is splittable, then get the index and size of
  135. // the block that is left over after taking out what is
  136. // needed from this allocate request.
  137. //
  138. newi = i + NumBytes;
  139. numBytesNew = HP_SIZE(*HPTR(i)) - NumBytes;
  140. //
  141. // Create a header for the left-over block by marking
  142. // it as free, and inserting the size.
  143. //
  144. HP_SIZE(*HPTR(newi)) = numBytesNew;
  145. HP_FLAG(*HPTR(newi)) = 0;
  146. //
  147. // Update the header for the allocated block and
  148. // return its index to the caller.
  149. // NOTE: The caller is responsible for marking this block
  150. // as allocated.
  151. //
  152. HP_SIZE(*HPTR(i)) = NumBytes;
  153. return(i);
  154. }
  155. }
  156. }
  157. return(INULL); // Heap full
  158. }
  159.