jheap.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "jlib.hpp"
  15. #include "jheap.hpp"
  16. #include "jmutex.hpp"
  17. #include "jexcept.hpp"
  18. #include "jheap.ipp"
  19. static Allocator32 * alloc32;
  20. static Allocator32 * alloc24;
  21. static Allocator32 * alloc16;
  22. static Allocator32 * alloc12;
  23. static Allocator32 * alloc8;
  24. static Allocator32 * alloc4;
  25. static Allocator32 * alloc0;
  26. static Allocator32 * subAllocator[CHUNK_MAX+1];
  27. static ChunkAllocator32 * theAllocator;
  28. MODULE_INIT(INIT_PRIORITY_JHEAP)
  29. {
  30. theAllocator = new ChunkAllocator32;
  31. alloc32 = new Allocator32(32, theAllocator);
  32. alloc24 = new Allocator32(24, theAllocator);
  33. alloc16 = new Allocator32(16, theAllocator);
  34. alloc8 = new Allocator32(8, theAllocator);
  35. alloc4 = new Allocator32(4, theAllocator);
  36. alloc0 = new Allocator32(0, theAllocator);
  37. unsigned idx = CHUNK_MAX;
  38. while (idx > 24) subAllocator[idx--] = alloc32;
  39. while (idx > 16) subAllocator[idx--] = alloc24;
  40. while (idx > 8) subAllocator[idx--] = alloc16;
  41. while (idx > 4) subAllocator[idx--] = alloc8;
  42. while (idx > 0) subAllocator[idx--] = alloc4;
  43. subAllocator[0] = alloc0;
  44. return true;
  45. }
  46. MODULE_EXIT()
  47. {
  48. delete alloc32;
  49. delete alloc24;
  50. delete alloc16;
  51. delete alloc8;
  52. delete alloc4;
  53. delete alloc0;
  54. delete theAllocator;
  55. }
  56. CriticalSection crit;
  57. //---------------------------------------------------------------------------
  58. char * ChunkAllocator32::lowerBound;
  59. char * ChunkAllocator32::upperBound;
  60. char * ChunkAllocator32::curAlloc;
  61. ChunkAllocator32::ChunkAllocator32(void)
  62. {
  63. lowerBound = (char *)VirtualAlloc(PREFERRED_HEAP_ADDRESS, MAXCOMMIT, MEM_RESERVE, PAGE_READWRITE);
  64. if (!lowerBound)
  65. lowerBound = (char *)VirtualAlloc(NULL, MAXCOMMIT, MEM_RESERVE, PAGE_READWRITE);
  66. if (!lowerBound)
  67. {
  68. assertThrow(lowerBound);
  69. upperBound = NULL;
  70. curAlloc = NULL;
  71. }
  72. else
  73. {
  74. upperBound = lowerBound + MAXCOMMIT;
  75. curAlloc = lowerBound;
  76. }
  77. }
  78. ChunkAllocator32::~ChunkAllocator32(void)
  79. {
  80. VirtualFree(lowerBound, upperBound-lowerBound, MEM_RELEASE);
  81. }
  82. char * ChunkAllocator32::allocatePage(void)
  83. {
  84. if (curAlloc >= upperBound)
  85. return NULL;
  86. char * ret = curAlloc;
  87. VirtualAlloc(ret, PAGESIZE, MEM_COMMIT, PAGE_READWRITE);
  88. curAlloc += PAGESIZE;
  89. return ret;
  90. }
  91. //---------------------------------------------------------------------------
  92. Allocator32::Allocator32(size32_t _size, ChunkAllocator32 * _allocator)
  93. {
  94. size = _size;
  95. allocator = _allocator;
  96. }
  97. char * Allocator32::allocate(void)
  98. {
  99. if (next)
  100. {
  101. char * ret = next;
  102. next = *(char * *)ret;
  103. return ret;
  104. }
  105. if (more())
  106. return allocate();
  107. return NULL;
  108. }
  109. void Allocator32::deallocate(void * ptr)
  110. {
  111. *(char * *)ptr = next;
  112. next = (char *)ptr;
  113. }
  114. bool Allocator32::more(void)
  115. {
  116. if (size == 0)
  117. return false;
  118. char * cur = ChunkAllocator32::allocatePage();
  119. if (!cur)
  120. return false;
  121. //head of each page has a pointer to the allocator
  122. *(Allocator32 * *)cur = this;
  123. //fill the rest of the block with a linked data structure
  124. char * prev = NULL;
  125. unsigned todo = PAGESIZE - size;
  126. while (todo >= size)
  127. {
  128. cur += size;
  129. *(char * *)cur = prev;
  130. prev = cur;
  131. todo -= size;
  132. }
  133. next = cur;
  134. return true;
  135. }
  136. //---------------------------------------------------------------------------
  137. void * chunkedNew(size32_t size)
  138. {
  139. if (size <= CHUNK_MAX)
  140. {
  141. CriticalBlock block(crit);
  142. void * ret = subAllocator[size]->allocate();
  143. if (ret)
  144. return ret;
  145. if (size == 0)
  146. return NULL;
  147. }
  148. return malloc(size);
  149. }
  150. void chunkedFree(void * ptr)
  151. {
  152. if (ptr)
  153. {
  154. if (ISCHUNKED(ptr))
  155. {
  156. CriticalBlock block(crit);
  157. FREECHUNKED(ptr);
  158. return;
  159. }
  160. free(ptr);
  161. }
  162. }