Subversion Repositories Kolibri OS

Rev

Rev 5195 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; System allocator.
  2. ; Based on dlmalloc 2.8.6.
  3. ; dlmalloc is written by Doug Lea and released to the public domain.
  4.  
  5. ; Algorithms are the same as in dlmalloc, with the following differences:
  6. ; * segment management uses large segments,
  7. ;   since segments can never be merged;
  8. ; * top chunk is usually large, so the code tries mmap
  9. ;   for chunks with size >= mmap_threshold before allocating from top;
  10. ; * there is additional bookkeeping for releasing physical memory
  11. ;   instead of relying on unmapping entire segments:
  12. ;   tree chunks have additional field in the end,
  13. ;   all recently expanded tree chunks are linked in one list for sys_trim;
  14. ; * there is an additional list of all mmapped chunks,
  15. ;   so that mspace_destroy can free everything, including mmapped chunks;
  16. ; * realloc and memalign can give back a space before a free chunk
  17. ;   (extending that chunk) even if a space is less than minimal chunk size.
  18.  
  19. ; Statistics:
  20. ;   Alignment: 8 bytes
  21. ;   Minimum overhead per allocated chunk: 4 or 8 bytes,
  22. ;     depending on whether FOOTERS is defined.
  23. ;   Minimum allocated size: 16 bytes (including overhead)
  24. ; See details at http://gee.cs.oswego.edu/dl/html/malloc.html.
  25.  
  26. ; The KolibriOS kernel provides functions similar to mmap/mremap/munmap,
  27. ; they are used as base for allocations.
  28.  
  29. FOOTERS = 0
  30. ;  If true, provide extra checking and dispatching by placing
  31. ;  information in the footers of allocated chunks. This adds
  32. ;  space and time overhead, but can be useful for debugging.
  33.  
  34. DEFAULT_MMAP_THRESHOLD = 256*1024
  35. ;  The request size threshold for using MMAP to directly service a
  36. ;  request. Requests of at least this size that cannot be allocated
  37. ;  using already-existing space will be serviced via mmap.  (If enough
  38. ;  normal freed space already exists it is used instead.)  Using mmap
  39. ;  segregates relatively large chunks of memory so that they can be
  40. ;  individually obtained and released from the host system. A request
  41. ;  serviced through mmap is never reused by any other request (at least
  42. ;  not directly; the system may just so happen to remap successive
  43. ;  requests to the same locations).  Segregating space in this way has
  44. ;  the benefits that: Mmapped space can always be individually released
  45. ;  back to the system, which helps keep the system level memory demands
  46. ;  of a long-lived program low.  Also, mapped memory doesn't become
  47. ;  `locked' between other chunks, as can happen with normally allocated
  48. ;  chunks, which means that even trimming via malloc_trim would not
  49. ;  release them.  However, it has the disadvantage that the space
  50. ;  cannot be reclaimed, consolidated, and then used to service later
  51. ;  requests, as happens with normal chunks.  The advantages of mmap
  52. ;  nearly always outweigh disadvantages for "large" chunks, but the
  53. ;  value of "large" may vary across systems.  The default is an
  54. ;  empirically derived value that works well in most systems. You can
  55. ;  disable mmap by setting to 0xFFFFFFFF.
  56.  
  57. RELEASE_CHECK_RATE = 64
  58. ;  The number of consolidated frees between checks to release
  59. ;  unused segments when freeing. When using non-contiguous segments,
  60. ;  especially with multiple mspaces, checking only for topmost space
  61. ;  doesn't always suffice to trigger trimming. To compensate for this,
  62. ;  free() will, with a period of MAX_RELEASE_CHECK_RATE (or the
  63. ;  current number of segments, if greater) try to release unused
  64. ;  segments to the OS when freeing chunks that result in
  65. ;  consolidation. The best value for this parameter is a compromise
  66. ;  between slowing down frees with relatively costly checks that
  67. ;  rarely trigger versus holding on to unused memory. To effectively
  68. ;  disable, set to MAX_SIZE_T. This may lead to a very slight speed
  69. ;  improvement at the expense of carrying around more memory.
  70.  
  71. DEFAULT_MSPACE_SIZE = 1024*1024
  72.  
  73. include 'malloc_internal.inc'
  74.  
  75. prologue@proc equ fpo_prologue
  76. epilogue@proc equ fpo_epilogue
  77.  
  78. ;  void* create_mspace(size_t capacity, int locked)
  79. ;  create_mspace creates and returns a new independent space with the
  80. ;  given initial capacity, or, if 0, the default mspace size.  It
  81. ;  returns null if there is no system memory available to create the
  82. ;  space.  If argument locked is non-zero, the space uses a separate
  83. ;  lock to control access. The capacity of the space will grow
  84. ;  dynamically as needed to service mspace_malloc requests.
  85. proc create_mspace stdcall uses ebx, capacity, locked
  86.         do_create_mspace
  87. endp
  88.  
  89. ;  void destroy_mspace(mspace msp)
  90. ;  destroy_mspace destroys the given space, and attempts to return all
  91. ;  of its memory back to the system, returning the total number of
  92. ;  bytes freed. After destruction, the results of access to all memory
  93. ;  used by the space become undefined.
  94. proc destroy_mspace stdcall uses ebx, msp
  95.         do_destroy_mspace
  96. endp
  97.  
  98.  
  99. macro set_default_heap
  100. {
  101.         mov     ebp, [default_heap]
  102. .got_mspace:
  103. }
  104.  
  105. macro set_explicit_heap
  106. {
  107.         mov     ebp, [msp]
  108. }
  109.  
  110. macro mspace_adapter common_label
  111. {
  112.         mov     eax, [esp]
  113.         mov     [esp], ebp
  114.         mov     ebp, [esp+4]
  115.         mov     [esp+4], eax
  116.         push    ebx
  117.         push    esi
  118.         jmp     common_label
  119. }
  120.  
  121. ;  void* malloc(size_t bytes)
  122. ;  Returns a pointer to a newly allocated chunk of at least n bytes, or
  123. ;  null if no space is available, in which case errno is set to ENOMEM
  124. ;  on ANSI C systems.
  125. ;
  126. ;  If n is zero, malloc returns a minimum-sized chunk. (The minimum
  127. ;  size is 16 bytes on most 32bit systems, and 32 bytes on 64bit
  128. ;  systems.)  Note that size_t is an unsigned type, so calls with
  129. ;  arguments that would be negative if signed are interpreted as
  130. ;  requests for huge amounts of space, which will often fail. The
  131. ;  maximum supported value of n differs across systems, but is in all
  132. ;  cases less than the maximum representable value of a size_t.
  133. align 16
  134. proc malloc stdcall uses ebp ebx esi, bytes
  135.         set_default_heap
  136.         do_malloc
  137. endp
  138.  
  139. ;  void free(void* mem)
  140. ;  Releases the chunk of memory pointed to by mem, that had been previously
  141. ;  allocated using malloc or a related routine such as realloc.
  142. ;  It has no effect if mem is null. If mem was not malloced or already
  143. ;  freed, free(mem) will by default cause the current program to abort.
  144. align 16
  145. proc free stdcall uses ebp ebx esi, mem
  146.         set_default_heap
  147.         do_free
  148. endp
  149.  
  150. ;  void* calloc(size_t n_elements, size_t elem_size);
  151. ;  Returns a pointer to n_elements * elem_size bytes, with all locations
  152. ;  set to zero.
  153. align 16
  154. proc calloc stdcall, n_elements, elem_size
  155.         do_calloc <stdcall malloc,eax>
  156. endp
  157.  
  158. ;  void* realloc(void* oldmem, size_t bytes)
  159. ;  Returns a pointer to a chunk of size bytes that contains the same data
  160. ;  as does chunk oldmem up to the minimum of (bytes, oldmem's size) bytes, or null
  161. ;  if no space is available.
  162. ;
  163. ;  The returned pointer may or may not be the same as oldmem. The algorithm
  164. ;  prefers extending oldmem in most cases when possible, otherwise it
  165. ;  employs the equivalent of a malloc-copy-free sequence.
  166. ;
  167. ;  If oldmem is null, realloc is equivalent to malloc.
  168. ;
  169. ;  If space is not available, realloc returns null, errno is set (if on
  170. ;  ANSI) and oldmem is NOT freed.
  171. ;
  172. ;  if bytes is for fewer bytes than already held by oldmem, the newly unused
  173. ;  space is lopped off and freed if possible.  realloc with a size
  174. ;  argument of zero (re)allocates a minimum-sized chunk.
  175. ;
  176. ;  The old unix realloc convention of allowing the last-free'd chunk
  177. ;  to be used as an argument to realloc is not supported.
  178. align 16
  179. proc realloc stdcall uses ebp ebx esi, oldmem, bytes
  180.         set_default_heap
  181. if used mspace_realloc
  182.         do_realloc <stdcall mspace_malloc,ebp,>, <stdcall mspace_free,ebp,>
  183. else
  184.         do_realloc <stdcall malloc,>, <stdcall free,>
  185. end if
  186. endp
  187.  
  188. ;  void* realloc_in_place(void* oldmem, size_t bytes)
  189. ;  Resizes the space allocated for oldmem to size bytes, only if this can be
  190. ;  done without moving oldmem (i.e., only if there is adjacent space
  191. ;  available if bytes is greater than oldmem's current allocated size, or bytes is
  192. ;  less than or equal to oldmem's size). This may be used instead of plain
  193. ;  realloc if an alternative allocation strategy is needed upon failure
  194. ;  to expand space; for example, reallocation of a buffer that must be
  195. ;  memory-aligned or cleared. You can use realloc_in_place to trigger
  196. ;  these alternatives only when needed.
  197. ;
  198. ;  Returns oldmem if successful; otherwise null.
  199. align 16
  200. proc realloc_in_place stdcall uses ebp ebx esi, oldmem, bytes
  201.         set_default_heap
  202.         do_realloc_in_place
  203. endp
  204.  
  205. ;  void* memalign(size_t alignment, size_t bytes);
  206. ;  Returns a pointer to a newly allocated chunk of bytes argument, aligned
  207. ;  in accord with the alignment argument.
  208. ;
  209. ;  The alignment argument should be a power of two. If the argument is
  210. ;  not a power of two, the nearest greater power is used.
  211. ;  8-byte alignment is guaranteed by normal malloc calls, so don't
  212. ;  bother calling memalign with an argument of 8 or less.
  213. ;
  214. ;  Overreliance on memalign is a sure way to fragment space.
  215. align 16
  216. proc memalign stdcall uses ebp ebx esi, alignment, bytes
  217.         set_default_heap
  218. if used mspace_memalign
  219.         do_memalign <stdcall mspace_malloc,ebp,>
  220. else
  221.         do_memalign <stdcall malloc,>
  222. end if
  223. endp
  224.  
  225. ;  void* mspace_malloc(mspace msp, size_t bytes)
  226. ;  mspace_malloc behaves as malloc, but operates within
  227. ;  the given space.
  228. align 16
  229. proc mspace_malloc ;stdcall uses ebp ebx esi, msp, bytes
  230. ;       set_explicit_heap
  231. ;       do_malloc
  232.         mspace_adapter malloc.got_mspace
  233. endp
  234.  
  235. ;  void mspace_free(mspace msp, void* mem)
  236. ;  mspace_free behaves as free, but operates within
  237. ;  the given space.
  238. align 16
  239. proc mspace_free ;stdcall uses ebp ebx esi, msp, mem
  240. ;       set_explicit_heap
  241. ;       do_free
  242.         mspace_adapter free.got_mspace
  243. endp
  244.  
  245. ;  void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size)
  246. ;  mspace_calloc behaves as calloc, but operates within
  247. ;  the given space.
  248. align 16
  249. proc mspace_calloc stdcall, msp, n_elements, elem_size
  250.         do_calloc <stdcall mspace_malloc,[msp+4],eax>
  251. endp
  252.  
  253. ;  void* mspace_realloc(mspace msp, void* oldmem, size_t bytes)
  254. ;  mspace_realloc behaves as realloc, but operates within
  255. ;  the given space.
  256. align 16
  257. proc mspace_realloc ;stdcall uses ebp ebx esi, msp, oldmem, bytes
  258. ;       set_explicit_heap
  259. ;       do_realloc <stdcall mspace_malloc,ebp,>, <stdcall mspace_free,ebp,>
  260.         mspace_adapter realloc.got_mspace
  261. endp
  262.  
  263. ;  void* mspace_realloc_in_place(mspace msp, void* oldmem, size_t bytes)
  264. align 16
  265. proc mspace_realloc_in_place ;stdcall uses ebp ebx esi, msp, oldmem, bytes
  266. ;       set_explicit_heap
  267. ;       do_realloc_in_place
  268.         mspace_adapter realloc_in_place.got_mspace
  269. endp
  270.  
  271. ;  void* mspace_memalign(mspace msp, size_t alignment, size_t bytes)
  272. ;  mspace_memalign behaves as memalign, but operates within
  273. ;  the given space.
  274. align 16
  275. proc mspace_memalign ;stdcall uses ebp ebx esi, msp, alignment, bytes
  276. ;       set_explicit_heap
  277. ;       do_memalign <stdcall mspace_malloc,ebp,>
  278.         mspace_adapter memalign.got_mspace
  279. endp
  280.  
  281. assert MALLOC_ALIGNMENT >= 8
  282. assert MALLOC_ALIGNMENT and (MALLOC_ALIGNMENT - 1) = 0
  283. assert MCHUNK_SIZE and (MCHUNK_SIZE - 1) = 0
  284. ; in: edx = initial size of the process heap
  285. macro malloc_init
  286. {
  287. if FOOTERS
  288.         mov     eax, 26
  289.         mov     ebx, 9
  290.         call    FS_SYSCALL_PTR
  291.         xor     eax, 0x55555555
  292.         or      eax, 8
  293.         and     eax, not 7
  294.         mov     [malloc_magic], eax
  295. end if
  296.         stdcall create_mspace, edx, 1
  297.         mov     [default_heap], eax
  298. }
  299.  
  300. proc heap_corrupted
  301.         sub     esp, 400h
  302.         mov     eax, 9
  303.         mov     ebx, esp
  304.         or      ecx, -1
  305.         call    FS_SYSCALL_PTR
  306.         lea     esi, [ebx+10]
  307.         lea     edx, [ebx+10+11]
  308.         mov     eax, 63
  309.         mov     ebx, 1
  310.         mov     cl, '['
  311.         call    FS_SYSCALL_PTR
  312. @@:
  313.         mov     cl, [esi]
  314.         test    cl, cl
  315.         jz      @f
  316.         call    FS_SYSCALL_PTR
  317.         inc     esi
  318.         cmp     esi, edx
  319.         jb      @b
  320. @@:
  321.         mov     esi, heap_corrupted_msg
  322. @@:
  323.         mov     cl, [esi]
  324.         inc     esi
  325.         test    cl, cl
  326.         jz      @f
  327.         mov     eax, 63
  328.         mov     ebx, 1
  329.         call    FS_SYSCALL_PTR
  330.         jmp     @b
  331. @@:
  332.         or      eax, -1
  333.         or      ebx, -1
  334.         call    FS_SYSCALL_PTR
  335. endp
  336.  
  337. heap_corrupted_msg      db      '] Heap corrupted, aborting',13,10,0
  338.