Subversion Repositories Kolibri OS

Rev

Rev 620 | Rev 663 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 660 $
  9.  
  10.  
  11. struc MEM_BLOCK
  12. {  .next_block  dd ?
  13.    .prev_block  dd ? ;+4
  14.    .list_fd     dd ? ;+8
  15.    .list_bk     dd ? ;+12
  16.    .base        dd ? ;+16
  17.    .size        dd ? ;+20
  18.    .flags       dd ? ;+24
  19.    .handle      dd ? ;+28
  20. }
  21.  
  22. MEM_LIST_OFFSET equ  8
  23. FREE_BLOCK     equ  4
  24. USED_BLOCK     equ  8
  25. DONT_FREE_BLOCK equ  10h
  26.  
  27. virtual at 0
  28.   MEM_BLOCK MEM_BLOCK
  29. end virtual
  30.  
  31. MEM_BLOCK_SIZE equ 8*4
  32.  
  33. block_next   equ MEM_BLOCK.next_block
  34. block_prev   equ MEM_BLOCK.prev_block
  35. list_fd     equ MEM_BLOCK.list_fd
  36. list_bk     equ MEM_BLOCK.list_bk
  37. block_base   equ MEM_BLOCK.base
  38. block_size   equ MEM_BLOCK.size
  39. block_flags equ MEM_BLOCK.flags
  40.  
  41. macro calc_index op
  42. {          shr op, 12
  43.            dec op
  44.            cmp op, 63
  45.            jna @f
  46.            mov op, 63
  47. @@:
  48. }
  49.  
  50. macro remove_from_list op
  51. {          mov edx, [op+list_fd]
  52.            mov ecx, [op+list_bk]
  53.            test edx, edx
  54.            jz @f
  55.            mov [edx+list_bk], ecx
  56. @@:
  57.            test ecx, ecx
  58.            jz @f
  59.            mov [ecx+list_fd], edx
  60. @@:
  61.            mov [op+list_fd],0
  62.            mov [op+list_bk],0
  63. }
  64.  
  65. macro remove_from_free op
  66. {
  67.            remove_from_list op
  68.  
  69.            mov eax, [op+block_size]
  70.            calc_index eax
  71.            cmp [mem_block_list+eax*4], op
  72.            jne @f
  73.            mov [mem_block_list+eax*4], edx
  74. @@:
  75.            cmp [mem_block_list+eax*4], 0
  76.            jne @f
  77.            btr [mem_block_mask], eax
  78. @@:
  79. }
  80.  
  81. macro remove_from_used op
  82. {
  83.            mov edx, [op+list_fd]
  84.            mov ecx, [op+list_bk]
  85.            mov [edx+list_bk], ecx
  86.            mov [ecx+list_fd], edx
  87.            mov [op+list_fd], 0
  88.            mov [op+list_bk], 0
  89. }
  90.  
  91. align 4
  92. proc init_kernel_heap
  93.  
  94.            mov ecx, 64/4
  95.            mov edi, mem_block_list
  96.            xor eax, eax
  97.            cld
  98.            rep stosd
  99.  
  100.            mov ecx, 512/4
  101.            mov edi, mem_block_map
  102.            not eax
  103.            rep stosd
  104.  
  105.            mov [mem_block_start], mem_block_map
  106.            mov [mem_block_end], mem_block_map+512
  107.            mov [mem_block_arr], HEAP_BASE
  108.  
  109.            mov eax, mem_used.fd-MEM_LIST_OFFSET
  110.            mov [mem_used.fd], eax
  111.            mov [mem_used.bk], eax
  112.  
  113.            stdcall alloc_pages, dword 32
  114.            mov ecx, 32
  115.            mov edx, eax
  116.            mov edi, HEAP_BASE
  117. .l1:
  118.            stdcall map_page,edi,edx,PG_SW
  119.            add edi, 0x1000
  120.            add edx, 0x1000
  121.            dec ecx
  122.            jnz .l1
  123.  
  124.            mov edi, HEAP_BASE
  125.            mov ebx, HEAP_BASE+MEM_BLOCK_SIZE
  126.            xor eax, eax
  127.            mov [edi+block_next], ebx
  128.            mov [edi+block_prev], eax
  129.            mov [edi+list_fd], eax
  130.            mov [edi+list_bk], eax
  131.            mov [edi+block_base], HEAP_BASE
  132.            mov [edi+block_size], 4096*MEM_BLOCK_SIZE
  133.            mov [edi+block_flags], USED_BLOCK
  134.  
  135.            mov [ebx+block_next], eax
  136.            mov [ebx+block_prev], eax
  137.            mov [ebx+list_fd], eax
  138.            mov [ebx+list_bk], eax
  139.            mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
  140.  
  141.            mov ecx, [MEM_AMOUNT]
  142.            sub ecx, HEAP_BASE + 4096*MEM_BLOCK_SIZE
  143.            mov [heap_size], ecx
  144.            mov [heap_free], ecx
  145.            mov [ebx+block_size], ecx
  146.            mov [ebx+block_flags], FREE_BLOCK
  147.  
  148.            mov [mem_block_mask], eax
  149.            mov [mem_block_mask+4],0x80000000
  150.  
  151.            mov [mem_block_list+63*4], ebx
  152.            mov byte [mem_block_map], 0xFC
  153.            and [heap_mutex], 0
  154.            mov [heap_blocks], 4095
  155.            mov [free_blocks], 4095
  156.            ret
  157. endp
  158.  
  159. ; param
  160. ;  eax= required size
  161. ;
  162. ; retval
  163. ;  edi= memory block descriptor
  164. ;  ebx= descriptor index
  165.  
  166. align 4
  167. get_block:
  168.            mov ecx, eax
  169.            shr ecx, 12
  170.            dec ecx
  171.            cmp ecx, 63
  172.            jle .get_index
  173.            mov ecx, 63
  174. .get_index:
  175.            lea esi, [mem_block_mask]
  176.            xor ebx, ebx
  177.            or edx, -1
  178.  
  179.            cmp ecx, 32
  180.            jb .bit_test
  181.  
  182.            sub ecx, 32
  183.            add ebx, 32
  184.            add esi, 4
  185. .bit_test:
  186.            shl edx, cl
  187.            and edx, [esi]
  188. .find:
  189.            bsf edi, edx
  190.            jz .high_mask
  191.            add ebx, edi
  192.            mov edi, [mem_block_list+ebx*4]
  193. .check_size:
  194.            cmp eax, [edi+block_size]
  195.            ja .next
  196.            ret
  197.  
  198. .high_mask:
  199.            add esi, 4
  200.            cmp esi, mem_block_mask+8
  201.            jae .err
  202.            add ebx, 32
  203.            mov edx, [esi]
  204.            jmp .find
  205. .next:
  206.            mov edi, [edi+list_fd]
  207.            test edi, edi
  208.            jnz .check_size
  209. .err:
  210.            xor edi, edi
  211.            ret
  212.  
  213. align 4
  214. proc alloc_mem_block
  215.  
  216.            mov ebx, [mem_block_start]
  217.            mov ecx, [mem_block_end]
  218. .l1:
  219.            bsf eax,[ebx];
  220.            jnz found
  221.            add ebx,4
  222.            cmp ebx, ecx
  223.            jb .l1
  224.            xor eax,eax
  225.            ret
  226.  
  227. found:
  228.            btr [ebx], eax
  229.            mov [mem_block_start],ebx
  230.            sub ebx, mem_block_map
  231.            lea eax,[eax+ebx*8]
  232.            shl eax, 5
  233.            add eax, [mem_block_arr]
  234.            dec [free_blocks]
  235.            ret
  236. endp
  237.  
  238. proc free_mem_block
  239.            mov dword [eax], 0
  240.            mov dword [eax+4], 0
  241.            mov dword [eax+8], 0
  242.            mov dword [eax+12], 0
  243.            mov dword [eax+16], 0
  244. ;           mov dword [eax+20], 0
  245.            mov dword [eax+24], 0
  246.            mov dword [eax+28], 0
  247.  
  248.            sub eax, [mem_block_arr]
  249.            shr eax, 5
  250.  
  251.            mov ebx, mem_block_map
  252.            bts [ebx], eax
  253.            inc [free_blocks]
  254.            shr eax, 3
  255.            and eax, not 3
  256.            add eax, ebx
  257.            cmp [mem_block_start], eax
  258.            ja @f
  259.            ret
  260. @@:
  261.            mov [mem_block_start], eax
  262.            ret
  263. .err:
  264.            xor eax, eax
  265.            ret
  266. endp
  267.  
  268. align 4
  269. proc alloc_kernel_space stdcall, size:dword
  270.            local block_ind:DWORD
  271.  
  272.            push ebx
  273.            push esi
  274.            push edi
  275.  
  276.            mov eax, [size]
  277.            add eax, 4095
  278.            and eax, not 4095
  279.            mov [size], eax
  280.  
  281.            mov ebx, heap_mutex
  282.            call wait_mutex    ;ebx
  283.  
  284.            cmp eax, [heap_free]
  285.            ja .error
  286.  
  287.            call get_block ; eax
  288.            test edi, edi
  289.            jz .error
  290.  
  291.            cmp [edi+block_flags], FREE_BLOCK
  292.            jne .error
  293.  
  294.            mov [block_ind], ebx   ;index of allocated block
  295.  
  296.            mov eax, [edi+block_size]
  297.            cmp eax, [size]
  298.            je .m_eq_size
  299.  
  300.            call alloc_mem_block
  301.            and eax, eax
  302.            jz .error
  303.  
  304.            mov esi, eax           ;esi - splitted block
  305.  
  306.            mov [esi+block_next], edi
  307.            mov eax, [edi+block_prev]
  308.            mov [esi+block_prev], eax
  309.            mov [edi+block_prev], esi
  310.            mov [esi+list_fd], 0
  311.            mov [esi+list_bk], 0
  312.            and eax, eax
  313.            jz @f
  314.            mov [eax+block_next], esi
  315. @@:
  316.            mov ebx, [edi+block_base]
  317.            mov [esi+block_base], ebx
  318.            mov edx, [size]
  319.            mov [esi+block_size], edx
  320.            add [edi+block_base], edx
  321.            sub [edi+block_size], edx
  322.  
  323.            mov eax, [edi+block_size]
  324.            shr eax, 12
  325.            sub eax, 1
  326.            cmp eax, 63
  327.            jna @f
  328.            mov eax, 63
  329. @@:
  330.            cmp eax, [block_ind]
  331.            je .m_eq_ind
  332.  
  333.            remove_from_list edi
  334.  
  335.            mov ecx, [block_ind]
  336.            mov [mem_block_list+ecx*4], edx
  337.  
  338.            test edx, edx
  339.            jnz @f
  340.            btr [mem_block_mask], ecx
  341. @@:
  342.            mov edx, [mem_block_list+eax*4]
  343.            mov [edi+list_fd], edx
  344.            test edx, edx
  345.            jz @f
  346.            mov [edx+list_bk], edi
  347. @@:
  348.            mov [mem_block_list+eax*4], edi
  349.            bts [mem_block_mask], eax
  350. .m_eq_ind:
  351.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  352.            mov edx, [ecx+list_fd]
  353.            mov [esi+list_fd], edx
  354.            mov [esi+list_bk], ecx
  355.            mov [ecx+list_fd], esi
  356.            mov [edx+list_bk], esi
  357.  
  358.            mov [esi+block_flags], USED_BLOCK
  359.            mov eax, [esi+block_base]
  360.            mov ebx, [size]
  361.            sub [heap_free], ebx
  362.            and [heap_mutex], 0
  363.            pop edi
  364.            pop esi
  365.            pop ebx
  366.            ret
  367. .m_eq_size:
  368.            remove_from_list edi
  369.            mov [mem_block_list+ebx*4], edx
  370.            and edx, edx
  371.            jnz @f
  372.            btr [mem_block_mask], ebx
  373. @@:
  374.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  375.            mov edx, [ecx+list_fd]
  376.            mov [edi+list_fd], edx
  377.            mov [edi+list_bk], ecx
  378.            mov [ecx+list_fd], edi
  379.            mov [edx+list_bk], edi
  380.  
  381.            mov [edi+block_flags], USED_BLOCK
  382.            mov eax, [edi+block_base]
  383.            mov ebx, [size]
  384.            sub [heap_free], ebx
  385.            and [heap_mutex], 0
  386.            pop edi
  387.            pop esi
  388.            pop ebx
  389.            ret
  390. .error:
  391.            xor eax, eax
  392.            mov [heap_mutex], eax
  393.            pop edi
  394.            pop esi
  395.            pop ebx
  396.            ret
  397. endp
  398.  
  399. align 4
  400. proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
  401.            push ebx
  402.            push esi
  403.            push edi
  404.            mov ebx, heap_mutex
  405.            call wait_mutex    ;ebx
  406.  
  407.            mov eax, [base]
  408.            mov esi, [mem_used.fd]
  409. @@:
  410.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  411.            je .fail
  412.  
  413.            cmp [esi+block_base], eax
  414.            je .found
  415.            mov esi, [esi+list_fd]
  416.            jmp @b
  417. .found:
  418.            cmp [esi+block_flags], USED_BLOCK
  419.            jne .fail
  420.  
  421.            mov eax, [esi+block_size]
  422.            add [heap_free], eax
  423.  
  424.            mov edi, [esi+block_next]
  425.            test edi, edi
  426.            jz .prev
  427.  
  428.            cmp [edi+block_flags], FREE_BLOCK
  429.            jne .prev
  430.  
  431.            remove_from_free edi
  432.  
  433.            mov edx, [edi+block_next]
  434.            mov [esi+block_next], edx
  435.            test edx, edx
  436.            jz @f
  437.  
  438.            mov [edx+block_prev], esi
  439. @@:
  440.            mov ecx, [edi+block_size]
  441.            add [esi+block_size], ecx
  442.  
  443.            mov eax, edi
  444.            call free_mem_block
  445. .prev:
  446.            mov edi, [esi+block_prev]
  447.            test edi, edi
  448.            jz .insert
  449.  
  450.            cmp [edi+block_flags], FREE_BLOCK
  451.            jne .insert
  452.  
  453.            remove_from_used esi
  454.  
  455.            mov edx, [esi+block_next]
  456.            mov [edi+block_next], edx
  457.            test edx, edx
  458.            jz @f
  459.            mov [edx+block_prev], edi
  460. @@:
  461.            mov eax, esi
  462.            call free_mem_block
  463.  
  464.            mov ecx, [edi+block_size]
  465.            mov eax, [esi+block_size]
  466.            add eax, ecx
  467.            mov [edi+block_size], eax
  468.  
  469.            calc_index eax
  470.            calc_index ecx
  471.            cmp eax, ecx
  472.            je .m_eq
  473.  
  474.            push ecx
  475.            remove_from_list edi
  476.            pop ecx
  477.  
  478.            cmp [mem_block_list+ecx*4], edi
  479.            jne @f
  480.            mov [mem_block_list+ecx*4], edx
  481. @@:
  482.            cmp [mem_block_list+ecx*4], 0
  483.            jne @f
  484.            btr [mem_block_mask], ecx
  485. @@:
  486.            mov esi, [mem_block_list+eax*4]
  487.            mov [mem_block_list+eax*4], edi
  488.            mov [edi+list_fd], esi
  489.            test esi, esi
  490.            jz @f
  491.            mov [esi+list_bk], edi
  492. @@:
  493.            bts [mem_block_mask], eax
  494. .m_eq:
  495.            xor eax, eax
  496.            mov [heap_mutex], eax
  497.            dec eax
  498.            pop edi
  499.            pop esi
  500.            pop ebx
  501.            ret
  502. .insert:
  503.            remove_from_used esi
  504.  
  505.            mov eax, [esi+block_size]
  506.            calc_index eax
  507.  
  508.            mov edi, [mem_block_list+eax*4]
  509.            mov [mem_block_list+eax*4], esi
  510.            mov [esi+list_fd], edi
  511.            test edi, edi
  512.            jz @f
  513.            mov [edi+list_bk], esi
  514. @@:
  515.            bts [mem_block_mask], eax
  516.            mov [esi+block_flags],FREE_BLOCK
  517.            xor eax, eax
  518.            mov [heap_mutex], eax
  519.            dec eax
  520.            pop edi
  521.            pop esi
  522.            pop ebx
  523.            ret
  524. .fail:
  525.            xor eax, eax
  526.            mov [heap_mutex], eax
  527.            pop edi
  528.            pop esi
  529.            pop ebx
  530.            ret
  531. endp
  532.  
  533. align 4
  534. proc kernel_alloc stdcall, size:dword
  535.            locals
  536.              lin_addr    dd ?
  537.              pages_count dd ?
  538.            endl
  539.  
  540.            mov eax, [size]
  541.            add eax, 4095
  542.            and eax, not 4095;
  543.            mov [size], eax
  544.            and eax, eax
  545.            jz .err
  546.            mov ebx, eax
  547.            shr ebx, 12
  548.            mov [pages_count], ebx
  549.  
  550.            stdcall alloc_kernel_space, eax
  551.            test eax, eax
  552.            jz .err
  553.            mov [lin_addr], eax
  554.  
  555.            mov ecx, [pages_count]
  556.            mov edx, eax
  557.            mov ebx, ecx
  558.  
  559.            shr ecx, 3
  560.            jz .next
  561.  
  562.            and ebx, not 7
  563.            push ebx
  564.            stdcall alloc_pages, ebx
  565.            pop ecx                   ; yes ecx!!!
  566.            and eax, eax
  567.            jz .err
  568.  
  569.            mov edi, eax
  570.            mov edx, [lin_addr]
  571. @@:
  572.            stdcall map_page,edx,edi,dword PG_SW
  573.            add edx, 0x1000
  574.            add edi, 0x1000
  575.            dec ecx
  576.            jnz @B
  577. .next:
  578.            mov ecx, [pages_count]
  579.            and ecx, 7
  580.            jz .end
  581. @@:
  582.            push ecx
  583.            call alloc_page
  584.            pop ecx
  585.            test eax, eax
  586.            jz .err
  587.  
  588.            stdcall map_page,edx,eax,dword PG_SW
  589.            add edx, 0x1000
  590.            dec ecx
  591.            jnz @B
  592. .end:
  593.            mov eax, [lin_addr]
  594.            ret
  595. .err:
  596.            xor eax, eax
  597.            ret
  598. endp
  599.  
  600. align 4
  601. proc kernel_free stdcall, base:dword
  602.            push ebx esi
  603.  
  604.            mov ebx, heap_mutex
  605.            call wait_mutex    ;ebx
  606.  
  607.            mov eax, [base]
  608.            mov esi, [mem_used.fd]
  609. @@:
  610.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  611.            je .fail
  612.  
  613.            cmp [esi+block_base], eax
  614.            je .found
  615.            mov esi, [esi+list_fd]
  616.            jmp @b
  617. .found:
  618.            cmp [esi+block_flags], USED_BLOCK
  619.            jne .fail
  620.  
  621.            and [heap_mutex], 0
  622.  
  623.            push ecx
  624.            mov ecx, [esi+block_size];
  625.            shr ecx, 12
  626.            call release_pages   ;eax, ecx
  627.            pop ecx
  628.            stdcall free_kernel_space, [base]
  629.            pop esi ebx
  630.            ret
  631. .fail:
  632.            and [heap_mutex], 0
  633.            pop esi ebx
  634.            ret
  635. endp
  636.  
  637. restore block_next
  638. restore block_prev
  639. restore block_list
  640. restore block_base
  641. restore block_size
  642. restore block_flags
  643.  
  644. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  645.  
  646. HEAP_TOP equ 0x5FC00000
  647.  
  648. align 4
  649. proc init_heap
  650.  
  651.            mov ebx,[current_slot]
  652.            mov eax, [ebx+APPDATA.heap_top]
  653.            test eax, eax
  654.            jz @F
  655.            sub eax,[ebx+APPDATA.heap_base]
  656.            sub eax, 4096
  657.            ret
  658. @@:
  659.            mov esi, [ebx+APPDATA.mem_size]
  660.            add esi, 4095
  661.            and esi, not 4095
  662.            mov [ebx+APPDATA.mem_size], esi
  663.            mov eax, HEAP_TOP
  664.            mov [ebx+APPDATA.heap_base], esi
  665.            mov [ebx+APPDATA.heap_top], eax
  666.  
  667.            sub eax, esi
  668.        ;    add esi, new_app_base
  669.            shr esi, 10
  670.            mov ecx, eax
  671.            sub eax, 4096
  672.            or ecx, FREE_BLOCK
  673.            mov [page_tabs+esi], ecx
  674.            ret
  675. endp
  676.  
  677. align 4
  678. proc user_alloc stdcall, alloc_size:dword
  679.  
  680.            mov ecx, [alloc_size]
  681.            add ecx, (4095+4096)
  682.            and ecx, not 4095
  683.  
  684.            mov ebx, [current_slot]
  685.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  686.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  687. l_0:
  688.            cmp esi, edi
  689.            jae m_exit
  690.  
  691.            mov ebx, esi
  692.            shr ebx, 12
  693.            mov eax, [page_tabs+ebx*4]
  694.            test al, FREE_BLOCK
  695.            jz test_used
  696.            and eax, 0xFFFFF000
  697.            cmp eax, ecx    ;alloc_size
  698.            jb  m_next
  699.            jz  @f
  700.  
  701.            lea edx, [esi+ecx]
  702.            sub eax, ecx
  703.            or al, FREE_BLOCK
  704.            shr edx, 12
  705.            mov [page_tabs+edx*4], eax
  706. @@:
  707.            or ecx, USED_BLOCK
  708.            mov [page_tabs+ebx*4], ecx
  709.            shr ecx, 12
  710.            inc ebx
  711.            dec ecx
  712.            jz  .no
  713. @@:
  714.            mov dword [page_tabs+ebx*4], 2
  715.            inc ebx
  716.            dec ecx
  717.            jnz @B
  718. .no:
  719.  
  720.            mov     edx, [current_slot]
  721.            mov     ebx, [alloc_size]
  722.            add     ebx, 0xFFF
  723.            and     ebx, not 0xFFF
  724.            add     ebx, [edx+APPDATA.mem_size]
  725.            call    update_mem_size
  726.  
  727.            lea eax, [esi+4096]
  728.            ret
  729. test_used:
  730.            test al, USED_BLOCK
  731.            jz m_exit
  732.  
  733.            and eax, 0xFFFFF000
  734. m_next:
  735.            add esi, eax
  736.            jmp l_0
  737. m_exit:
  738.            xor eax, eax
  739.            ret
  740. endp
  741.  
  742. align 4
  743. proc user_free stdcall, base:dword
  744.  
  745.            mov esi, [base]
  746.            test esi, esi
  747.            jz .exit
  748.  
  749.            xor ebx, ebx
  750.            shr esi, 12
  751.            mov eax, [page_tabs+(esi-1)*4]
  752.            test al, USED_BLOCK
  753.            jz .cantfree
  754.            test al, DONT_FREE_BLOCK
  755.            jnz .cantfree
  756.  
  757.            and eax, not 4095
  758.            mov ecx, eax
  759.            or al, FREE_BLOCK
  760.            mov [page_tabs+(esi-1)*4], eax
  761.            sub ecx, 4096
  762.            mov ebx, ecx
  763.            shr ecx, 12
  764.            jz .released
  765. .release:
  766.            xor eax, eax
  767.            xchg eax, [page_tabs+esi*4]
  768.            test al, 1
  769.            jz @F
  770.            call free_page
  771.            mov eax, esi
  772.            shl eax, 12
  773.            invlpg [eax]
  774. @@:
  775.            inc esi
  776.            dec ecx
  777.            jnz .release
  778. .released:
  779.            mov edx, [current_slot]
  780.            mov esi, dword [edx+APPDATA.heap_base]
  781.            mov edi, dword [edx+APPDATA.heap_top]
  782.            sub ebx, [edx+APPDATA.mem_size]
  783.            neg ebx
  784.            call update_mem_size
  785.            call user_normalize
  786.            ret
  787. .exit:
  788.            xor eax, eax
  789.            inc eax
  790.            ret
  791. .cantfree:
  792.            xor eax, eax
  793.            ret
  794. endp
  795.  
  796. user_normalize:
  797. ; in: esi=heap_base, edi=heap_top
  798. ; out: eax=0 <=> OK
  799. ; destroys: ebx,edx,esi,edi
  800.            shr esi, 12
  801.            shr edi, 12
  802. @@:
  803.            mov eax, [page_tabs+esi*4]
  804.            test al, USED_BLOCK
  805.            jz .test_free
  806.            shr eax, 12
  807.            add esi, eax
  808.            jmp @B
  809. .test_free:
  810.            test al, FREE_BLOCK
  811.            jz .err
  812.            mov edx, eax
  813.            shr edx, 12
  814.            add edx, esi
  815.            cmp edx, edi
  816.            jae .exit
  817.  
  818.            mov ebx, [page_tabs+edx*4]
  819.            test bl, USED_BLOCK
  820.            jz .next_free
  821.  
  822.            shr ebx, 12
  823.            add edx, ebx
  824.            mov esi, edx
  825.            jmp @B
  826. .next_free:
  827.            test bl, FREE_BLOCK
  828.            jz .err
  829.            and dword [page_tabs+edx*4], 0
  830.            add eax, ebx
  831.            and eax, not 4095
  832.            or eax, FREE_BLOCK
  833.            mov [page_tabs+esi*4], eax
  834.            jmp @B
  835. .exit:
  836.            xor eax, eax
  837.            inc eax
  838.            ret
  839. .err:
  840.            xor eax, eax
  841.            ret
  842.  
  843. user_realloc:
  844. ; in: eax = pointer, ebx = new size
  845. ; out: eax = new pointer or NULL
  846.         test    eax, eax
  847.         jnz     @f
  848. ; realloc(NULL,sz) - same as malloc(sz)
  849.         push    ebx
  850.         call    user_alloc
  851.         ret
  852. @@:
  853.         push    ecx edx
  854.         lea     ecx, [eax - 0x1000]
  855.         shr     ecx, 12
  856.         mov     edx, [page_tabs+ecx*4]
  857.         test    dl, USED_BLOCK
  858.         jnz     @f
  859. ; attempt to realloc invalid pointer
  860. .ret0:
  861.         pop     edx ecx
  862.         xor     eax, eax
  863.         ret
  864. @@:
  865.         test    dl, DONT_FREE_BLOCK
  866.         jnz     .ret0
  867.         add     ebx, 0x1FFF
  868.         shr     edx, 12
  869.         shr     ebx, 12
  870. ; edx = allocated size, ebx = new size
  871.         add     edx, ecx
  872.         add     ebx, ecx
  873.         cmp     edx, ebx
  874.         jb      .realloc_add
  875. ; release part of allocated memory
  876. .loop:
  877.         cmp     edx, ebx
  878.         jz      .release_done
  879.         dec     edx
  880.         xor     eax, eax
  881.         xchg    eax, [page_tabs+edx*4]
  882.         test    al, 1
  883.         jz      .loop
  884.         call    free_page
  885.         mov     eax, edx
  886.         shl     eax, 12
  887.         invlpg  [eax]
  888.         jmp     .loop
  889. .release_done:
  890.         sub     ebx, ecx
  891.         cmp     ebx, 1
  892.         jnz     .nofreeall
  893.         mov     eax, [page_tabs+ecx*4]
  894.         and     eax, not 0xFFF
  895.         mov     edx, [current_slot]
  896.         mov     ebx, [APPDATA.mem_size+edx]
  897.         sub     ebx, eax
  898.         add     ebx, 0x1000
  899.         or      al, FREE_BLOCK
  900.         mov     [page_tabs+ecx*4], eax
  901.         push    esi edi
  902.         mov     esi, [APPDATA.heap_base+edx]
  903.         mov     edi, [APPDATA.heap_top+edx]
  904.         call    update_mem_size
  905.         call    user_normalize
  906.         pop     edi esi
  907.         jmp     .ret0   ; all freed
  908. .nofreeall:
  909.         sub     edx, ecx
  910.         shl     ebx, 12
  911.         or      ebx, USED_BLOCK
  912.         xchg    [page_tabs+ecx*4], ebx
  913.         shr     ebx, 12
  914.         sub     ebx, edx
  915.         push    ebx ecx edx
  916.         mov     edx, [current_slot]
  917.         shl     ebx, 12
  918.         sub     ebx, [APPDATA.mem_size+edx]
  919.         neg     ebx
  920.         call    update_mem_size
  921.         pop     edx ecx ebx
  922.         lea     eax, [ecx+1]
  923.         shl     eax, 12
  924.         push    eax
  925.         add     ecx, ebx
  926.         add     edx, ecx
  927.         shl     ebx, 12
  928.         jz      .ret
  929.         push    esi
  930.         mov     esi, [current_slot]
  931.         mov     esi, [APPDATA.heap_top+esi]
  932.         shr     esi, 12
  933. @@:
  934.         cmp     edx, esi
  935.         jae     .merge_done
  936.         mov     eax, [page_tabs+edx*4]
  937.         test    al, USED_BLOCK
  938.         jz      .merge_done
  939.         and     dword [page_tabs+edx*4], 0
  940.         and     eax, not 0xFFF
  941.         add     ebx, eax
  942.         add     edx, eax
  943.         jmp     @b
  944. .merge_done:
  945.         pop     esi
  946.         or      ebx, FREE_BLOCK
  947.         mov     [page_tabs+ecx*4], ebx
  948. .ret:
  949.         pop     eax edx ecx
  950.         ret
  951. .realloc_add:
  952. ; get some additional memory
  953.         mov     eax, [current_slot]
  954.         mov     eax, [APPDATA.heap_top+eax]
  955.         shr     eax, 12
  956.         cmp     edx, eax
  957.         jae     .cant_inplace
  958.         mov     eax, [page_tabs+edx*4]
  959.         test    al, FREE_BLOCK
  960.         jz      .cant_inplace
  961.         shr     eax, 12
  962.         add     eax, edx
  963.         sub     eax, ebx
  964.         jb      .cant_inplace
  965.         jz      @f
  966.         shl     eax, 12
  967.         or      al, FREE_BLOCK
  968.         mov     [page_tabs+ebx*4], eax
  969. @@:
  970.         mov     eax, ebx
  971.         sub     eax, ecx
  972.         shl     eax, 12
  973.         or      al, USED_BLOCK
  974.         mov     [page_tabs+ecx*4], eax
  975.         lea     eax, [ecx+1]
  976.         shl     eax, 12
  977.         push    eax
  978.         push    edi
  979.         lea     edi, [page_tabs+edx*4]
  980.         mov     eax, 2
  981.         sub     ebx, edx
  982.         mov     ecx, ebx
  983.         cld
  984.         rep     stosd
  985.         pop     edi
  986.         mov     edx, [current_slot]
  987.         shl     ebx, 12
  988.         add     ebx, [APPDATA.mem_size+edx]
  989.         call    update_mem_size
  990.         pop     eax edx ecx
  991.         ret
  992. .cant_inplace:
  993.         push    esi edi
  994.         mov     eax, [current_slot]
  995.         mov     esi, [APPDATA.heap_base+eax]
  996.         mov     edi, [APPDATA.heap_top+eax]
  997.         shr     esi, 12
  998.         shr     edi, 12
  999.         sub     ebx, ecx
  1000. .find_place:
  1001.         cmp     esi, edi
  1002.         jae     .place_not_found
  1003.         mov     eax, [page_tabs+esi*4]
  1004.         test    al, FREE_BLOCK
  1005.         jz      .next_place
  1006.         shr     eax, 12
  1007.         cmp     eax, ebx
  1008.         jae     .place_found
  1009.         add     esi, eax
  1010.         jmp     .find_place
  1011. .next_place:
  1012.         shr     eax, 12
  1013.         add     esi, eax
  1014.         jmp     .find_place
  1015. .place_not_found:
  1016.         pop     edi esi
  1017.         jmp     .ret0
  1018. .place_found:
  1019.         sub     eax, ebx
  1020.         jz      @f
  1021.         push    esi
  1022.         add     esi, ebx
  1023.         shl     eax, 12
  1024.         or      al, FREE_BLOCK
  1025.         mov     [page_tabs+esi*4], eax
  1026.         pop     esi
  1027. @@:
  1028.         mov     eax, ebx
  1029.         shl     eax, 12
  1030.         or      al, USED_BLOCK
  1031.         mov     [page_tabs+esi*4], eax
  1032.         inc     esi
  1033.         mov     eax, esi
  1034.         shl     eax, 12
  1035.         push    eax
  1036.         mov     eax, [page_tabs+ecx*4]
  1037.         and     eax, not 0xFFF
  1038.         or      al, FREE_BLOCK
  1039.         sub     edx, ecx
  1040.         mov     [page_tabs+ecx*4], eax
  1041.         inc     ecx
  1042.         dec     ebx
  1043.         dec     edx
  1044.         jz      .no
  1045. @@:
  1046.         xor     eax, eax
  1047.         xchg    eax, [page_tabs+ecx*4]
  1048.         mov     [page_tabs+esi*4], eax
  1049.         mov     eax, ecx
  1050.         shl     eax, 12
  1051.         invlpg  [eax]
  1052.         inc     esi
  1053.         inc     ecx
  1054.         dec     ebx
  1055.         dec     edx
  1056.         jnz     @b
  1057. .no:
  1058.         push    ebx
  1059.         mov     edx, [current_slot]
  1060.         shl     ebx, 12
  1061.         add     ebx, [APPDATA.mem_size+edx]
  1062.         call    update_mem_size
  1063.         pop     ebx
  1064. @@:
  1065.         mov     dword [page_tabs+esi*4], 2
  1066.         inc     esi
  1067.         dec     ebx
  1068.         jnz     @b
  1069.         pop     eax edi esi edx ecx
  1070.         ret
  1071.  
  1072. if 0
  1073. align 4
  1074. proc alloc_dll
  1075.            pushf
  1076.            cli
  1077.            bsf eax, [dll_map]
  1078.            jnz .find
  1079.            popf
  1080.            xor eax, eax
  1081.            ret
  1082. .find:
  1083.            btr [dll_map], eax
  1084.            popf
  1085.            shl eax, 5
  1086.            add eax, dll_tab
  1087.            ret
  1088. endp
  1089.  
  1090. align 4
  1091. proc alloc_service
  1092.            pushf
  1093.            cli
  1094.            bsf eax, [srv_map]
  1095.            jnz .find
  1096.            popf
  1097.            xor eax, eax
  1098.            ret
  1099. .find:
  1100.            btr [srv_map], eax
  1101.            popf
  1102.            shl eax,0x02
  1103.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1104.            ret
  1105. endp
  1106.  
  1107. end if
  1108.