Advertisement
Guest User

Untitled

a guest
May 3rd, 2016
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.52 KB | None | 0 0
  1. enum {
  2. PAGE_SIZE = 4096,
  3. MINIMUM_RANGE_SIZE = PAGE_SIZE
  4. };
  5.  
  6. void *AllocateRange(uint32_t *size) {
  7. *size = (*size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
  8. if (*size < MINIMUM_RANGE_SIZE) {
  9. *size = MINIMUM_RANGE_SIZE;
  10. }
  11. return VirtualAlloc(0, *size, MEM_COMMIT, PAGE_READWRITE);
  12. }
  13.  
  14. void FreeRange(void *pointer, uint32_t size) {
  15. VirtualFree(pointer, size, MEM_RELEASE);
  16. }
  17.  
  18. struct Block {
  19. uint32_t free : 1;
  20. uint32_t size : 31;
  21. uint32_t previous_size;
  22. };
  23.  
  24. struct FreeBlock {
  25. uint32_t free : 1;
  26. uint32_t size : 31;
  27. uint32_t previous_size;
  28. FreeBlock *previous_free;
  29. FreeBlock *next_free;
  30. };
  31.  
  32. enum {
  33. LOG2_MINIMUM_BLOCK_SIZE = 5,
  34. MINIMUM_BLOCK_SIZE = 1 << LOG2_MINIMUM_BLOCK_SIZE,
  35. LOG2_CLASSES_PER_EXPONENT = 3,
  36. CLASSES_PER_EXPONENT = 1 << LOG2_CLASSES_PER_EXPONENT,
  37. MAX_CLASSES = (32 - LOG2_MINIMUM_BLOCK_SIZE) * CLASSES_PER_EXPONENT
  38. };
  39.  
  40. FreeBlock *free_blocks[MAX_CLASSES];
  41.  
  42. uint32_t GetFreeBlockIndex(uint32_t size) {
  43. Assert(size >= MINIMUM_BLOCK_SIZE);
  44. DWORD exponent;
  45. _BitScanReverse(&exponent, size);
  46. uint32_t remainder = size - (1 << exponent);
  47. int32_t shift = exponent - LOG2_CLASSES_PER_EXPONENT;
  48. if (shift < 0) {
  49. shift = 0;
  50. }
  51. uint32_t offset = remainder >> shift;
  52. Assert(offset < CLASSES_PER_EXPONENT);
  53. return (exponent - LOG2_MINIMUM_BLOCK_SIZE) * CLASSES_PER_EXPONENT + offset;
  54. }
  55.  
  56. void InsertFreeBlock(FreeBlock *block) {
  57. uint32_t index = GetFreeBlockIndex(block->size);
  58. FreeBlock *first_free = free_blocks[index];
  59. if (first_free) {
  60. first_free->previous_free = block;
  61. }
  62. block->previous_free = 0;
  63. block->next_free = first_free;
  64. free_blocks[index] = block;
  65. }
  66.  
  67. void RemoveFreeBlock(FreeBlock *block) {
  68. if (block->previous_free) {
  69. block->previous_free->next_free = block->next_free;
  70. } else {
  71. uint32_t index = GetFreeBlockIndex(block->size);
  72. Assert(free_blocks[index] == block);
  73. free_blocks[index] = block->next_free;
  74. }
  75. if (block->next_free) {
  76. block->next_free->previous_free = block->previous_free;
  77. }
  78. }
  79.  
  80. void AllocateFreeBlock(FreeBlock *block, uint32_t size) {
  81. Assert(block->free);
  82. Assert(size >= MINIMUM_BLOCK_SIZE);
  83. Assert(size <= block->size);
  84. RemoveFreeBlock(block);
  85. if (block->size - size >= MINIMUM_BLOCK_SIZE) {
  86. uint32_t new_size = block->size - size;
  87. FreeBlock *new_block = (FreeBlock *)((char *)block + size);
  88. Block *next_block = (Block *)((char*)block + block->size);
  89. next_block->previous_size = new_size;
  90. block->size = size;
  91. new_block->free = 1;
  92. new_block->size = new_size;
  93. new_block->previous_size = size;
  94. new_block->next_free = block->next_free;
  95. InsertFreeBlock(new_block);
  96. }
  97. block->free = 0;
  98. }
  99.  
  100. void *TryAllocate(uint32_t size) {
  101. size += sizeof(Block);
  102. if (size < MINIMUM_BLOCK_SIZE) {
  103. size = MINIMUM_BLOCK_SIZE;
  104. }
  105. bool retried = false;
  106. for (uint32_t index = GetFreeBlockIndex(size); index < MAX_CLASSES; index++) {
  107. FreeBlock *free_block = free_blocks[index];
  108. if (free_block) {
  109. if (free_block->size >= size) {
  110. AllocateFreeBlock(free_block, size);
  111. return (char *)free_block + sizeof(Block);
  112. } else {
  113. Assert(!retried);
  114. retried = true;
  115. }
  116. }
  117. }
  118. return 0;
  119. }
  120.  
  121. void FreeAllocatedBlock(Block *block) {
  122. Block *previous_block = (Block *)((char *)block - block->previous_size);
  123. Block *next_block = (Block *)((char *)block + block->size);
  124. if (previous_block->free) {
  125. RemoveFreeBlock((FreeBlock *)previous_block);
  126. previous_block->size += block->size;
  127. next_block->previous_size = previous_block->size;
  128. Block *previous_previous_block = (Block *)((char *)previous_block - previous_block->previous_size);
  129. block = previous_block;
  130. previous_block = previous_previous_block;
  131. }
  132. if (next_block->free) {
  133. RemoveFreeBlock((FreeBlock *)next_block);
  134. block->size += next_block->size;
  135. Block *next_next_block = (Block *)((char *)next_block + next_block->size);
  136. next_next_block->previous_size = block->size;
  137. }
  138. block->free = 1;
  139. InsertFreeBlock((FreeBlock *)block);
  140. }
  141.  
  142. void Free(void *pointer) {
  143. if (pointer) {
  144. Block *block = (Block *)((char *)pointer - sizeof(Block));
  145. Assert(block->free == 0);
  146. FreeAllocatedBlock(block);
  147. }
  148. }
  149.  
  150. void InsertFreeRange(void *base, uint32_t size) {
  151. Assert(size % PAGE_SIZE == 0);
  152. Assert(size >= 3 * PAGE_SIZE);
  153. Block *head = (Block *)base;
  154. head->free = 0;
  155. head->size = PAGE_SIZE;
  156. head->previous_size = 0;
  157. FreeBlock *block = (FreeBlock *)((char *)base + PAGE_SIZE);
  158. block->free = 1;
  159. block->size = size - 2 * PAGE_SIZE;
  160. block->previous_size = head->size;
  161. Block *tail = (Block *)((char *)base + size - PAGE_SIZE);
  162. tail->free = 0;
  163. tail->size = PAGE_SIZE;
  164. tail->previous_size = block->size;
  165. uint32_t index = GetFreeBlockIndex(block->size);
  166. block->previous_free = 0;
  167. block->next_free = free_blocks[index];
  168. free_blocks[index] = block;
  169. }
  170.  
  171. void *Allocate(uint32_t size) {
  172. void *pointer = TryAllocate(size);
  173. if (!pointer) {
  174. uint32_t range_size = (size + 4 * PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
  175. void *range_base = AllocateRange(&range_size);
  176. Printf("Allocating new range.\n");
  177. InsertFreeRange(range_base, range_size);
  178. pointer = TryAllocate(size);
  179. Assert(pointer);
  180. }
  181. return pointer;
  182. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement