Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. format ELF
  2. section '.text' executable
  3. public malloc
  4. public free
  5. public realloc
  6. public mf_init
  7. ;multithread:  ;uncomment this for thread-safe version
  8. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  9. ;; Memory allocator for MenuetOS                         ;;
  10. ;; Halyavin Andrey halyavin@land.ru, 2006                ;;
  11. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  12.  
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14. ;; allocated mem block structure                         ;;
  15. ;; +0:   bit 0 - used flag                               ;;
  16. ;;       bits 31..1 - block size                         ;;
  17. ;; +4: address of prev block                             ;;
  18. ;; +8 .. +(blocksize) - allocated memory                 ;;
  19. ;; +(blocksize) - next block                             ;;
  20. ;;                                                       ;;
  21. ;; free mem block structure                              ;;
  22. ;; +0:   bit 0 - used flag                               ;;
  23. ;;       bits 31..1 - block size                         ;;
  24. ;; +4:  address of prev block                            ;;
  25. ;; +8:  prev free block                                  ;;
  26. ;; +12: next free block                                  ;;
  27. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  28. memblock.size=0
  29. memblock.prevblock=4
  30. memblock.prevfreeblock=8
  31. memblock.nextfreeblock=12
  32.  
  33.  
  34. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  35. ;; mf_init                                               ;;
  36. ;; Initialize memory map for dynamic use                 ;;
  37. ;; input: eax: starting address or 0                     ;;
  38. ;; output: none                                          ;;
  39. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  40. mf_init:
  41.   push  ebx
  42.   push  ecx
  43.   test  eax,eax
  44.   jnz   .noautodet
  45.   sub   esp,1024
  46.   mov   ebx,esp
  47.   mov   ecx,-1
  48.   mov   eax,9
  49.   int   0x40
  50.   mov   eax,[esp+26]
  51.   add   esp,1024
  52. .noautodet:
  53.   add   eax,15
  54.   and   eax,not 15
  55.   mov   [heapsmallblocks],eax
  56.   add   eax,2048
  57.   mov   [heapstart],eax
  58.   mov   [heapfreelist],eax
  59.   mov   [heaplastblock],eax
  60.  
  61.   mov   ecx,eax
  62. if defined heapstartsize
  63.   add   ecx,heapstartsize
  64. else
  65.   add   ecx,4096
  66. end if
  67.   add   ecx,4095
  68.   and   ecx,not 4095
  69.   push  eax
  70.   mov   eax,64
  71.   mov   ebx,1
  72.   int   0x40
  73.   pop   eax
  74.   mov   [eax+memblock.prevblock],dword 0  
  75.   mov   [heapend],ecx
  76.   mov   [eax+memblock.size],ecx
  77.   sub   [eax+memblock.size],eax
  78.   xor   ebx,ebx
  79.   mov   dword [eax+memblock.prevfreeblock],heapfreelist-memblock.nextfreeblock
  80.   mov   [eax+memblock.nextfreeblock],ebx
  81.   mov   [heapmutex],ebx
  82.   push  edi
  83.   mov   edi,[heapsmallblocks]
  84.   mov   ecx,512
  85.   xor   eax,eax
  86.   rep   stosd
  87.   pop   edi
  88.   pop   ecx
  89.   pop   ebx
  90.   ret
  91.  
  92. if defined multithread
  93. heaplock:
  94.   push  eax
  95.   push  ebx
  96.   push  ecx
  97.   mov   eax,68
  98.   mov   ebx,1
  99. .loop:
  100.   xchg  ecx,[heapmutex]
  101.   test  ecx,ecx
  102.   jz    .endloop
  103.   int   0x40    ;change task
  104.   jmp   .loop
  105. .endloop:
  106.   pop   ecx
  107.   pop   ebx
  108.   pop   eax
  109.   ret
  110.  
  111. heapunlock:
  112.   mov   [heapmutex],dword 0
  113.   ret
  114. end if
  115.  
  116. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  117. ;; heap_split_block                                      ;;
  118. ;; Split free block to allocated block and free one.     ;;
  119. ;; input:                                                ;;
  120. ;;   eax - size of allocated block                       ;;
  121. ;;   ebx - block                                         ;;
  122. ;; output:                                               ;;
  123. ;;   eax - real size of allocated block                  ;;
  124. ;;   ebx - pointer to new block                          ;;
  125. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  126. heap_split_block:
  127.   push  ecx
  128.   mov   ecx,[ebx+memblock.size]
  129.   sub   ecx,16
  130.   cmp   ecx,eax
  131.   jge   .norm
  132.   inc   dword [ebx+memblock.size]
  133.   mov   eax,ecx
  134.   xor   ebx,ebx
  135.   pop   ecx
  136.   ret
  137. .norm:
  138.   add   ecx,16
  139.   mov   [ebx+memblock.size],eax
  140.   inc   dword [ebx+memblock.size]
  141.   mov   [ebx+eax+memblock.prevblock],ebx
  142.   add   ebx,eax
  143.   sub   ecx,eax
  144.   mov   [ebx+memblock.size],ecx
  145.   mov   ecx,eax
  146.   mov   eax,ebx
  147.   call  heap_fix_right
  148.   mov   eax,ecx
  149.   pop   ecx
  150.   ret
  151.  
  152. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  153. ;; heap_add_free_block                                   ;;
  154. ;; Add free block to one of free block lists.            ;;
  155. ;; input:                                                ;;
  156. ;;   eax - address of free block                         ;;
  157. ;; output:                                               ;;
  158. ;;   none                                                ;;
  159. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  160. heap_add_free_block:
  161.   cmp   dword [eax+memblock.size],4096
  162.   push  ebx
  163.   jge   .bigblock
  164.   mov   ebx,[eax+memblock.size]
  165.   shr   ebx,1
  166.   add   ebx,[heapsmallblocks]
  167.   push  dword [ebx]
  168.   pop   dword [eax+memblock.nextfreeblock]
  169.   mov   [ebx],eax
  170.   mov   dword [eax+memblock.prevfreeblock],ebx
  171.   sub   dword [eax+memblock.prevfreeblock],memblock.nextfreeblock
  172.   mov   ebx,[eax+memblock.nextfreeblock]
  173.   test  ebx,ebx
  174.   jz    .no_next_block
  175.   mov   [ebx+memblock.prevfreeblock],eax
  176. .no_next_block:
  177.   pop   ebx
  178.   ret
  179. .bigblock:
  180.   mov   ebx,[heapfreelist]
  181.   mov   [eax+memblock.nextfreeblock],ebx
  182.   mov   [heapfreelist],eax
  183.   mov   dword [eax+memblock.prevfreeblock],heapfreelist-memblock.nextfreeblock
  184. ;  mov   ebx,[eax+memblock.nextfreeblock]
  185.   test  ebx,ebx
  186.   jz    .no_next_big_block
  187.   mov   [ebx+memblock.prevfreeblock],eax
  188. .no_next_big_block:
  189.   pop   ebx
  190.   ret
  191.  
  192. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  193. ;; heap_remove_block                                     ;;
  194. ;; Remove free block from the list of free blocks.       ;;
  195. ;; input:                                                ;;
  196. ;;   eax - free block                                    ;;
  197. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  198. heap_remove_block:
  199.   push   ebx
  200.   push   ecx
  201.   mov    ecx,[eax+memblock.prevfreeblock]
  202.   mov    ebx,[eax+memblock.nextfreeblock]
  203.   mov    [ecx+memblock.nextfreeblock],ebx
  204.   test   ebx,ebx
  205.   jz     .no_next_block
  206.   mov    [ebx+memblock.prevfreeblock],ecx
  207. .no_next_block:
  208.   pop    ecx
  209.   pop    ebx
  210.   ret
  211.  
  212. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  213. ;; mf_alloc
  214. ;; allocates a block of memory in heap
  215. ;; intput: eax: size of block
  216. ;; output: eax: address of allocated memory block or 0 if there's no mem.
  217. ;; allocator will not create new nodes that contain less that 8b of space,
  218. ;; and minimal allocation is actually 16 bytes - 8 for node and 8 for user.
  219. ;; allocator will never create non-aligned memory blocks.
  220. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  221. mf_alloc:
  222.   test  eax,eax
  223.   jg    .not_null  ; test that we are not allocating null size block
  224.   xor   eax,eax
  225.   ret
  226. .not_null:
  227. if defined multithread
  228.   call  heaplock
  229. end if
  230.   push  edi
  231. ;  push  edx
  232.   push  ecx
  233.   push  ebx
  234.   add   eax,7
  235.   and   eax,not 7   ; make sure that block size is aligned
  236.  
  237.   lea   edi,[eax+8] ; desired block size
  238.   cmp   edi,4096
  239.   jge   .general_cycle
  240.  
  241.   mov   ebx,[heapsmallblocks]
  242.   xor   ecx,ecx
  243.   shr   edi,1
  244.  
  245. .smallloop:
  246.   cmp   [ebx+edi],ecx
  247.   jnz   .smallblockfound
  248.   add   edi,4
  249.   cmp   edi,2048
  250.   jl    .smallloop
  251.   lea   edi,[eax+8]
  252.   jmp   .general_cycle
  253.  
  254. .smallblockfound:
  255.   lea   ecx,[eax+8]
  256.   mov   eax,[ebx+edi]
  257.   call  heap_remove_block
  258.   mov   ebx,eax
  259.   xchg  eax,ecx
  260.   call  heap_split_block
  261.   test  ebx,ebx
  262.   jz    .perfect_small_block
  263.   mov   eax,ebx
  264.   call  heap_add_free_block
  265. .perfect_small_block:
  266.   lea   eax,[ecx+8]
  267.   jmp   .ret
  268.  
  269. .general_cycle:
  270. ;edi - size needed
  271.   mov   eax,[heapfreelist]
  272.  
  273. .loop:
  274.   test  eax,eax
  275.   jz    .new_mem
  276.   cmp   [eax+memblock.size],edi
  277.   jge   .blockfound
  278.   mov   eax,[eax+memblock.nextfreeblock]
  279.   jmp   .loop
  280.  
  281. .blockfound:
  282.   call  heap_remove_block
  283.   mov   ebx,eax
  284.   mov   ecx,eax
  285.   mov   eax,edi
  286.   call  heap_split_block
  287.   test  ebx,ebx
  288.   jz    .perfect_block
  289.   mov   eax,ebx
  290.   call  heap_add_free_block
  291. .perfect_block:
  292.   lea   eax,[ecx+8]
  293. .ret:
  294. if defined multithread
  295.   call  heapunlock
  296. end if
  297.   pop   ebx
  298.   pop   ecx
  299. ;  pop   edx
  300.   pop   edi
  301.   ret
  302.  
  303. .new_mem:
  304.   mov   eax,edi
  305.   add   eax,4095
  306.   and   eax,not 4095
  307.   mov   ecx,[heapend]
  308.   add   [heapend],eax
  309.   push  eax
  310.   mov   eax,64
  311.   push  ebx
  312.   push  ecx
  313.   mov   ecx,[heapend]
  314.   mov   ebx,1
  315.   int   0x40
  316.   pop   ecx
  317.   pop   ebx
  318.   pop   eax
  319.   mov   [ecx+memblock.size],eax
  320.   mov   eax,[heaplastblock]
  321.   mov   [ecx+memblock.prevblock],eax
  322.   mov   [heaplastblock],ecx
  323.   mov   eax,ecx
  324.   call  heap_add_free_block
  325.   jmp   .general_cycle
  326.  
  327. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  328. ;; heap_fix_right                                        ;;
  329. ;; input:                                                ;;
  330. ;;   eax - pointer to free block                         ;;
  331. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  332. heap_fix_right:
  333.   push  ebx
  334.   mov   ebx,eax
  335.   add   ebx,[eax+memblock.size]
  336.   cmp   ebx,[heapend]
  337.   jz    .endblock
  338.   mov   [ebx+memblock.prevblock],eax
  339.   pop   ebx
  340.   ret
  341. .endblock:
  342.   mov   [heaplastblock],eax
  343.   pop   ebx
  344.   ret
  345.  
  346. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  347. ;; heap_merge_left                                       ;;
  348. ;; input:                                                ;;
  349. ;;   eax - pointer to free block                         ;;
  350. ;; output:                                               ;;
  351. ;;   eax - pointer to merged block                       ;;
  352. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  353. heap_merge_left:
  354.   push  ebx
  355.   mov   ebx,[eax+memblock.prevblock]
  356.   test  ebx,ebx
  357.   jz    .ret
  358.   test  byte [ebx+memblock.size],1
  359.   jnz   .ret
  360.   xchg  eax,ebx
  361.   call  heap_remove_block
  362.   mov   ebx,[ebx+memblock.size]
  363.   add   [eax+memblock.size],ebx
  364.   call  heap_fix_right
  365. .ret:
  366.   pop   ebx
  367.   ret
  368.  
  369. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  370. ;; heap_merge_right                                      ;;
  371. ;; input:                                                ;;
  372. ;;   eax - pointer to free block                         ;;
  373. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  374. heap_merge_right:
  375.   push  ebx
  376.   mov   ebx,eax
  377.   add   ebx,[eax+memblock.size]
  378.   cmp   ebx,[heapend]
  379.   jz    .ret
  380.   test  byte [ebx+memblock.size],1
  381.   jnz   .ret
  382.   xchg  eax,ebx
  383.   call  heap_remove_block
  384.   xchg  eax,ebx
  385.   mov   ebx,[ebx+memblock.size]
  386.   add   [eax+memblock.size],ebx
  387.   call  heap_fix_right
  388. .ret:
  389.   pop   ebx
  390.   ret
  391.  
  392. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  393. ;; mf_free                                               ;;
  394. ;; input:                                                ;;
  395. ;;   eax - pointer                                       ;;
  396. ;; output:                                               ;;
  397. ;;   eax=1 - ok                                          ;;
  398. ;;   eax=0 - failed                                      ;;
  399. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  400. mf_free:
  401.   test  eax,eax
  402.   jnz   .no_null
  403.   inc   eax
  404.   ret
  405. .no_null:
  406. if defined multithread
  407.   call  heaplock
  408. end if
  409.   sub   eax,8
  410.   dec   dword [eax+memblock.size]
  411.   call  heap_merge_left
  412.   call  heap_merge_right
  413.   call  heap_add_free_block
  414. .ret:
  415. if defined multithread
  416.   call  heapunlock
  417. end if
  418.   ret
  419.  
  420. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  421. ;; heap_try_reloc
  422. ;; input:
  423. ;;   eax - address
  424. ;;   ebx - new size
  425. ;; output:
  426. ;;   ebx=1 - ok
  427. ;;   ebx=0 - failed
  428. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  429. heap_try_reloc:
  430.   push  eax
  431.   sub   eax,8
  432.   add   ebx,15
  433.   dec   dword [eax+memblock.size]
  434.   and   ebx,not 7
  435.   cmp   [eax+memblock.size],ebx
  436.   jge   .truncate
  437.   push  ebx
  438.   mov   ebx,eax
  439.   add   ebx,[eax+memblock.size]
  440.   cmp   ebx,[heapend]
  441.   jz    .fail  ;todo: we can allocate new mem here
  442.   test  [ebx+memblock.size],byte 1
  443.   jnz   .fail
  444.   xchg  eax,ebx
  445.   call  heap_remove_block
  446.   mov   eax,[eax+memblock.size]
  447.   add   [ebx+memblock.size],eax
  448.   mov   eax,ebx
  449.   call  heap_fix_right
  450.   pop   ebx
  451. .truncate:
  452.   xchg  eax,ebx
  453.   call  heap_split_block
  454.   test  ebx,ebx
  455.   jz    .no_last_block
  456.   mov   eax,ebx
  457.   call  heap_add_free_block
  458.   call  heap_merge_right
  459. .no_last_block:
  460.   xor   ebx,ebx
  461.   pop   eax
  462.   inc   ebx
  463.   ret
  464. .fail:
  465.   pop   ebx
  466.   xor   ebx,ebx
  467.   pop   eax
  468.   inc   dword [eax-8+memblock.size]
  469.   ret
  470.  
  471. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  472. ;; mf_realloc
  473. ;; input:
  474. ;;   eax - pointer
  475. ;;   ebx - new size
  476. ;; output:
  477. ;;   eax - new pointer
  478. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  479. mf_realloc:
  480.   push  ebx
  481. if defined multithread
  482.   call  heaplock
  483. end if
  484.   call  heap_try_reloc
  485.   test  ebx,ebx
  486.   jnz   .ret
  487. ;allocate new memory
  488.   push  eax
  489.   mov   eax,[esp+4]
  490.   call  mf_alloc
  491.   test  eax,eax
  492.   jz    .fail
  493.   push  esi
  494.   push  edi
  495.   push  ecx
  496.   mov   edi,eax
  497.   mov   esi,[esp+12]
  498.   mov   ecx,[esi-8+memblock.size]
  499.   shr   ecx,2
  500.   rep   movsd
  501.   pop   ecx
  502.   pop   edi
  503.   pop   esi
  504.   xchg  eax,[esp]
  505.   call  mf_free
  506. .fail:
  507.   pop   eax
  508. .ret:
  509. if defined multithread
  510.   call  heapunlock
  511. end if
  512.   pop   ebx
  513.   ret
  514. ;C entries
  515. malloc:
  516.   mov   eax,[esp+4]
  517.   call  mf_alloc
  518.   ret
  519. free:
  520.   mov   eax,[esp+4]
  521.   call  mf_free
  522.   ret
  523. realloc:
  524.   mov   edx,ebx
  525.   mov   eax,[esp+4]
  526.   mov   ebx,[esp+8]
  527.   call  mf_realloc
  528.   mov   ebx,edx
  529.   ret    
  530. section '.bss' writeable
  531. heapsmallblocks rd 1
  532. heapstart       rd 1
  533. heapend         rd 1
  534. heapfreelist    rd 1
  535. heapmutex       rd 1
  536. heaplastblock   rd 1