Subversion Repositories Kolibri OS

Rev

Rev 546 | Rev 660 | 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: 593 $
  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.            mov eax, [size]
  273.            add eax, 4095
  274.            and eax, not 4095
  275.            mov [size], eax
  276.  
  277.            mov ebx, heap_mutex
  278.            call wait_mutex    ;ebx
  279.  
  280.            cmp eax, [heap_free]
  281.            ja .error
  282.  
  283.            call get_block ; eax
  284.            test edi, edi
  285.            jz .error
  286.  
  287.            cmp [edi+block_flags], FREE_BLOCK
  288.            jne .error
  289.  
  290.            mov [block_ind], ebx   ;index of allocated block
  291.  
  292.            mov eax, [edi+block_size]
  293.            cmp eax, [size]
  294.            je .m_eq_size
  295.  
  296.            call alloc_mem_block
  297.            and eax, eax
  298.            jz .error
  299.  
  300.            mov esi, eax           ;esi - splitted block
  301.  
  302.            mov [esi+block_next], edi
  303.            mov eax, [edi+block_prev]
  304.            mov [esi+block_prev], eax
  305.            mov [edi+block_prev], esi
  306.            mov [esi+list_fd], 0
  307.            mov [esi+list_bk], 0
  308.            and eax, eax
  309.            jz @f
  310.            mov [eax+block_next], esi
  311. @@:
  312.            mov ebx, [edi+block_base]
  313.            mov [esi+block_base], ebx
  314.            mov edx, [size]
  315.            mov [esi+block_size], edx
  316.            add [edi+block_base], edx
  317.            sub [edi+block_size], edx
  318.  
  319.            mov eax, [edi+block_size]
  320.            shr eax, 12
  321.            sub eax, 1
  322.            cmp eax, 63
  323.            jna @f
  324.            mov eax, 63
  325. @@:
  326.            cmp eax, [block_ind]
  327.            je .m_eq_ind
  328.  
  329.            remove_from_list edi
  330.  
  331.            mov ecx, [block_ind]
  332.            mov [mem_block_list+ecx*4], edx
  333.  
  334.            test edx, edx
  335.            jnz @f
  336.            btr [mem_block_mask], ecx
  337. @@:
  338.            mov edx, [mem_block_list+eax*4]
  339.            mov [edi+list_fd], edx
  340.            test edx, edx
  341.            jz @f
  342.            mov [edx+list_bk], edi
  343. @@:
  344.            mov [mem_block_list+eax*4], edi
  345.            bts [mem_block_mask], eax
  346. .m_eq_ind:
  347.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  348.            mov edx, [ecx+list_fd]
  349.            mov [esi+list_fd], edx
  350.            mov [esi+list_bk], ecx
  351.            mov [ecx+list_fd], esi
  352.            mov [edx+list_bk], esi
  353.  
  354.            mov [esi+block_flags], USED_BLOCK
  355.            mov eax, [esi+block_base]
  356.            mov ebx, [size]
  357.            sub [heap_free], ebx
  358.            and [heap_mutex], 0
  359.            ret
  360. .m_eq_size:
  361.            remove_from_list edi
  362.            mov [mem_block_list+ebx*4], edx
  363.            and edx, edx
  364.            jnz @f
  365.            btr [mem_block_mask], ebx
  366. @@:
  367.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  368.            mov edx, [ecx+list_fd]
  369.            mov [edi+list_fd], edx
  370.            mov [edi+list_bk], ecx
  371.            mov [ecx+list_fd], edi
  372.            mov [edx+list_bk], edi
  373.  
  374.            mov [edi+block_flags], USED_BLOCK
  375.            mov eax, [edi+block_base]
  376.            mov ebx, [size]
  377.            sub [heap_free], ebx
  378.            and [heap_mutex], 0
  379.            ret
  380. .error:
  381.            xor eax, eax
  382.            mov [heap_mutex], eax
  383.            ret
  384. endp
  385.  
  386. align 4
  387. proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
  388.  
  389.            mov ebx, heap_mutex
  390.            call wait_mutex    ;ebx
  391.  
  392.            mov eax, [base]
  393.            mov esi, [mem_used.fd]
  394. @@:
  395.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  396.            je .fail
  397.  
  398.            cmp [esi+block_base], eax
  399.            je .found
  400.            mov esi, [esi+list_fd]
  401.            jmp @b
  402. .found:
  403.            cmp [esi+block_flags], USED_BLOCK
  404.            jne .fail
  405.  
  406.            mov eax, [esi+block_size]
  407.            add [heap_free], eax
  408.  
  409.            mov edi, [esi+block_next]
  410.            test edi, edi
  411.            jz .prev
  412.  
  413.            cmp [edi+block_flags], FREE_BLOCK
  414.            jne .prev
  415.  
  416.            remove_from_free edi
  417.  
  418.            mov edx, [edi+block_next]
  419.            mov [esi+block_next], edx
  420.            test edx, edx
  421.            jz @f
  422.  
  423.            mov [edx+block_prev], esi
  424. @@:
  425.            mov ecx, [edi+block_size]
  426.            add [esi+block_size], ecx
  427.  
  428.            mov eax, edi
  429.            call free_mem_block
  430. .prev:
  431.            mov edi, [esi+block_prev]
  432.            test edi, edi
  433.            jz .insert
  434.  
  435.            cmp [edi+block_flags], FREE_BLOCK
  436.            jne .insert
  437.  
  438.            remove_from_used esi
  439.  
  440.            mov edx, [esi+block_next]
  441.            mov [edi+block_next], edx
  442.            test edx, edx
  443.            jz @f
  444.            mov [edx+block_prev], edi
  445. @@:
  446.            mov eax, esi
  447.            call free_mem_block
  448.  
  449.            mov ecx, [edi+block_size]
  450.            mov eax, [esi+block_size]
  451.            add eax, ecx
  452.            mov [edi+block_size], eax
  453.  
  454.            calc_index eax
  455.            calc_index ecx
  456.            cmp eax, ecx
  457.            je .m_eq
  458.  
  459.            push ecx
  460.            remove_from_list edi
  461.            pop ecx
  462.  
  463.            cmp [mem_block_list+ecx*4], edi
  464.            jne @f
  465.            mov [mem_block_list+ecx*4], edx
  466. @@:
  467.            cmp [mem_block_list+ecx*4], 0
  468.            jne @f
  469.            btr [mem_block_mask], ecx
  470. @@:
  471.            mov esi, [mem_block_list+eax*4]
  472.            mov [mem_block_list+eax*4], edi
  473.            mov [edi+list_fd], esi
  474.            test esi, esi
  475.            jz @f
  476.            mov [esi+list_bk], edi
  477. @@:
  478.            bts [mem_block_mask], eax
  479. .m_eq:
  480.            xor eax, eax
  481.            mov [heap_mutex], eax
  482.            dec eax
  483.            ret
  484. .insert:
  485.            remove_from_used esi
  486.  
  487.            mov eax, [esi+block_size]
  488.            calc_index eax
  489.  
  490.            mov edi, [mem_block_list+eax*4]
  491.            mov [mem_block_list+eax*4], esi
  492.            mov [esi+list_fd], edi
  493.            test edi, edi
  494.            jz @f
  495.            mov [edi+list_bk], esi
  496. @@:
  497.            bts [mem_block_mask], eax
  498.            mov [esi+block_flags],FREE_BLOCK
  499.            xor eax, eax
  500.            mov [heap_mutex], eax
  501.            dec eax
  502.            ret
  503. .fail:
  504.            xor eax, eax
  505.            mov [heap_mutex], eax
  506.            ret
  507. endp
  508.  
  509. align 4
  510. proc kernel_alloc stdcall, size:dword
  511.            locals
  512.              lin_addr    dd ?
  513.              pages_count dd ?
  514.            endl
  515.  
  516.            mov eax, [size]
  517.            add eax, 4095
  518.            and eax, not 4095;
  519.            mov [size], eax
  520.            and eax, eax
  521.            jz .err
  522.            mov ebx, eax
  523.            shr ebx, 12
  524.            mov [pages_count], ebx
  525.  
  526.            stdcall alloc_kernel_space, eax
  527.            test eax, eax
  528.            jz .err
  529.            mov [lin_addr], eax
  530.  
  531.            mov ecx, [pages_count]
  532.            mov edx, eax
  533.            mov ebx, ecx
  534.  
  535.            shr ecx, 3
  536.            jz .next
  537.  
  538.            and ebx, not 7
  539.            push ebx
  540.            stdcall alloc_pages, ebx
  541.            pop ecx                   ; yes ecx!!!
  542.            and eax, eax
  543.            jz .err
  544.  
  545.            mov edi, eax
  546.            mov edx, [lin_addr]
  547. @@:
  548.            stdcall map_page,edx,edi,dword PG_SW
  549.            add edx, 0x1000
  550.            add edi, 0x1000
  551.            dec ecx
  552.            jnz @B
  553. .next:
  554.            mov ecx, [pages_count]
  555.            and ecx, 7
  556.            jz .end
  557. @@:
  558.            push ecx
  559.            call alloc_page
  560.            pop ecx
  561.            test eax, eax
  562.            jz .err
  563.  
  564.            stdcall map_page,edx,eax,dword PG_SW
  565.            add edx, 0x1000
  566.            dec ecx
  567.            jnz @B
  568. .end:
  569.            mov eax, [lin_addr]
  570.            ret
  571. .err:
  572.            xor eax, eax
  573.            ret
  574. endp
  575.  
  576. align 4
  577. proc kernel_free stdcall, base:dword
  578.            push ebx esi
  579.  
  580.            mov ebx, heap_mutex
  581.            call wait_mutex    ;ebx
  582.  
  583.            mov eax, [base]
  584.            mov esi, [mem_used.fd]
  585. @@:
  586.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  587.            je .fail
  588.  
  589.            cmp [esi+block_base], eax
  590.            je .found
  591.            mov esi, [esi+list_fd]
  592.            jmp @b
  593. .found:
  594.            cmp [esi+block_flags], USED_BLOCK
  595.            jne .fail
  596.  
  597.            and [heap_mutex], 0
  598.  
  599.            push ecx
  600.            mov ecx, [esi+block_size];
  601.            shr ecx, 12
  602.            call release_pages   ;eax, ecx
  603.            pop ecx
  604.            stdcall free_kernel_space, [base]
  605.            pop esi ebx
  606.            ret
  607. .fail:
  608.            and [heap_mutex], 0
  609.            pop esi ebx
  610.            ret
  611. endp
  612.  
  613. restore block_next
  614. restore block_prev
  615. restore block_list
  616. restore block_base
  617. restore block_size
  618. restore block_flags
  619.  
  620. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  621.  
  622. HEAP_TOP  equ 0x5FC00000
  623.  
  624. align 4
  625. proc init_heap
  626.  
  627.            mov ebx,[current_slot]
  628.            mov eax, [ebx+APPDATA.heap_top]
  629.            test eax, eax
  630.            jz @F
  631.            sub eax,[ebx+APPDATA.heap_base]
  632.            sub eax, 4096
  633.            ret
  634. @@:
  635.            mov esi, [ebx+APPDATA.mem_size]
  636.            add esi, 4095
  637.            and esi, not 4095
  638.            mov [ebx+APPDATA.mem_size], esi
  639.            mov eax, HEAP_TOP
  640.            mov [ebx+APPDATA.heap_base], esi
  641.            mov [ebx+APPDATA.heap_top], eax
  642.  
  643.            sub eax, esi
  644.        ;    add esi, new_app_base
  645.            shr esi, 10
  646.            mov ecx, eax
  647.            sub eax, 4096
  648.            or ecx, FREE_BLOCK
  649.            mov [page_tabs+esi], ecx
  650.            ret
  651. .exit:
  652.            xor eax, eax
  653.            ret
  654. endp
  655.  
  656. align 4
  657. proc user_alloc stdcall, alloc_size:dword
  658.  
  659.            mov ecx, [alloc_size]
  660.            add ecx, (4095+4096)
  661.            and ecx, not 4095
  662.  
  663.            mov ebx, [current_slot]
  664.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  665.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  666. l_0:
  667.            cmp esi, edi
  668.            jae m_exit
  669.  
  670.            mov ebx, esi
  671.            shr ebx, 12
  672.            mov eax, [page_tabs+ebx*4]
  673.            test eax, FREE_BLOCK
  674.            jz test_used
  675.            and eax, 0xFFFFF000
  676.            cmp eax, ecx    ;alloc_size
  677.            jb  m_next
  678.            jz  @f
  679.  
  680.            mov edx, esi
  681.            add edx, ecx
  682.            sub eax, ecx;
  683.            or eax, FREE_BLOCK
  684.            shr edx, 12
  685.            mov [page_tabs+edx*4], eax
  686. @@:
  687.            or ecx, USED_BLOCK
  688.            mov [page_tabs+ebx*4], ecx
  689.            shr ecx, 12
  690.            dec ecx
  691.            inc ebx
  692. @@:
  693.            mov dword [page_tabs+ebx*4], 2
  694.            inc ebx
  695.            dec ecx
  696.            jnz @B
  697.  
  698.            mov     edx, [current_slot]
  699.            mov     ebx, [alloc_size]
  700.            add     ebx, 0xFFF
  701.            and     ebx, not 0xFFF
  702.            add     ebx, [edx+APPDATA.mem_size]
  703.            call    update_mem_size
  704.  
  705.            mov eax, esi
  706.            add eax, 4096
  707.            ret
  708. m_next:
  709.            add esi, eax
  710.            jmp l_0
  711. test_used:
  712.            test eax, USED_BLOCK
  713.            jz m_exit
  714.  
  715.            and eax, 0xFFFFF000
  716.            add esi, eax
  717.            jmp l_0
  718. m_exit:
  719.            xor eax, eax
  720.            ret
  721. endp
  722.  
  723. align 4
  724. proc user_free stdcall, base:dword
  725.  
  726.            mov esi, [base]
  727.            test esi, esi
  728.            jz .exit
  729.  
  730.            xor ebx, ebx
  731.            sub esi, 4096
  732.            shr esi, 12
  733.            mov eax, [page_tabs+esi*4]
  734.            test al, USED_BLOCK
  735.            jz .not_used
  736.            test al, DONT_FREE_BLOCK
  737.            jnz .cantfree
  738.  
  739.            and eax, not 4095
  740.            mov ecx, eax
  741.            or eax, FREE_BLOCK
  742.            mov [page_tabs+esi*4], eax
  743.            inc esi
  744.            sub ecx, 4096
  745.            shr ecx, 12
  746.            mov ebx, ecx
  747. .release:
  748.            xor eax, eax
  749.            xchg eax, [page_tabs+esi*4]
  750.            test eax, 1
  751.            jz @F
  752.            call free_page
  753.            mov eax, esi
  754.            shl eax, 12
  755.            invlpg [eax]
  756. @@:
  757.            inc esi
  758.            dec ecx
  759.            jnz .release
  760. .not_used:
  761.            mov edx, [current_slot]
  762.            mov esi, dword [edx+APPDATA.heap_base]
  763.            mov edi, dword [edx+APPDATA.heap_top]
  764.            sub ebx, [edx+APPDATA.mem_size]
  765.            neg ebx
  766.            call update_mem_size
  767.            call user_normalize
  768.            ret
  769. .exit:
  770.            xor eax, eax
  771.            inc eax
  772.            ret
  773. .cantfree:
  774.            xor eax, eax
  775.            ret
  776. endp
  777.  
  778. user_normalize:
  779. ; in: esi=heap_base, edi=heap_top
  780. ; out: eax=0 <=> OK
  781. ; destroys: ebx,edx,esi,edi
  782.            shr esi, 12
  783.            shr edi, 12
  784. @@:
  785.            mov eax, [page_tabs+esi*4]
  786.            test eax, USED_BLOCK
  787.            jz .test_free
  788.            shr eax, 12
  789.            add esi, eax
  790.            jmp @B
  791. .test_free:
  792.            test eax, FREE_BLOCK
  793.            jz .err
  794.            mov edx, eax
  795.            shr edx, 12
  796.            add edx, esi
  797.            cmp edx, edi
  798.            jae .exit
  799.  
  800.            mov ebx, [page_tabs+edx*4]
  801.            test ebx, USED_BLOCK
  802.            jz .next_free
  803.  
  804.            shr ebx, 12
  805.            add edx, ebx
  806.            mov esi, edx
  807.            jmp @B
  808. .next_free:
  809.            test ebx, FREE_BLOCK
  810.            jz .err
  811.            and dword [page_tabs+edx*4], 0
  812.            add eax, ebx
  813.            and eax, not 4095
  814.            or eax, FREE_BLOCK
  815.            mov [page_tabs+esi*4], eax
  816.            jmp @B
  817. .exit:
  818.            xor eax, eax
  819.            inc eax
  820.            ret
  821. .err:
  822.            xor eax, eax
  823.            ret
  824.  
  825. user_realloc:
  826. ; in: eax = pointer, ebx = new size
  827. ; out: eax = new pointer or NULL
  828.         test    eax, eax
  829.         jnz     @f
  830. ; realloc(NULL,sz) - same as malloc(sz)
  831.         push    ebx
  832.         call    user_alloc
  833.         ret
  834. @@:
  835.         push    ecx edx
  836.         lea     ecx, [eax - 0x1000]
  837.         shr     ecx, 12
  838.         mov     edx, [page_tabs+ecx*4]
  839.         test    edx, USED_BLOCK
  840.         jnz     @f
  841. ; attempt to realloc invalid pointer
  842. .ret0:
  843.         pop     edx ecx
  844.         xor     eax, eax
  845.         ret
  846. @@:
  847.         test    edx, DONT_FREE_BLOCK
  848.         jnz     .ret0
  849.         add     ebx, 0x1FFF
  850.         shr     edx, 12
  851.         shr     ebx, 12
  852. ; edx = allocated size, ebx = new size
  853.         add     edx, ecx
  854.         add     ebx, ecx
  855.         cmp     edx, ebx
  856.         jb      .realloc_add
  857. ; release part of allocated memory
  858. .loop:
  859.         cmp     edx, ebx
  860.         jz      .release_done
  861.         dec     edx
  862.         xor     eax, eax
  863.         xchg    eax, [page_tabs+edx*4]
  864.         test    al, 1
  865.         jz      .loop
  866.         call    free_page
  867.         mov     eax, edx
  868.         shl     eax, 12
  869.         invlpg  [eax]
  870.         jmp     .loop
  871. .release_done:
  872.         sub     ebx, ecx
  873.         cmp     ebx, 1
  874.         jnz     .nofreeall
  875.         mov     eax, [page_tabs+ecx*4]
  876.         and     eax, not 0xFFF
  877.         mov     edx, [current_slot]
  878.         mov     ebx, [APPDATA.mem_size+edx]
  879.         sub     ebx, eax
  880.         add     ebx, 0x1000
  881.         or      al, FREE_BLOCK
  882.         mov     [page_tabs+ecx*4], eax
  883.         push    esi edi
  884.         mov     esi, [APPDATA.heap_base+edx]
  885.         mov     edi, [APPDATA.heap_top+edx]
  886.         call    update_mem_size
  887.         call    user_normalize
  888.         pop     edi esi
  889.         jmp     .ret0   ; all freed
  890. .nofreeall:
  891.         sub     edx, ecx
  892.         shl     ebx, 12
  893.         or      ebx, USED_BLOCK
  894.         xchg    [page_tabs+ecx*4], ebx
  895.         shr     ebx, 12
  896.         sub     ebx, edx
  897.         push    ebx ecx edx
  898.         mov     edx, [current_slot]
  899.         shl     ebx, 12
  900.         sub     ebx, [APPDATA.mem_size+edx]
  901.         neg     ebx
  902.         call    update_mem_size
  903.         pop     edx ecx ebx
  904.         lea     eax, [ecx+1]
  905.         shl     eax, 12
  906.         push    eax
  907.         add     ecx, ebx
  908.         add     edx, ecx
  909.         shl     ebx, 12
  910.         jz      .ret
  911.         push    esi
  912.         mov     esi, [current_slot]
  913.         mov     esi, [APPDATA.heap_top+esi]
  914.         shr     esi, 12
  915. @@:
  916.         cmp     edx, esi
  917.         jae     .merge_done
  918.         mov     eax, [page_tabs+edx*4]
  919.         test    al, USED_BLOCK
  920.         jz      .merge_done
  921.         and     dword [page_tabs+edx*4], 0
  922.         and     eax, not 0xFFF
  923.         add     ebx, eax
  924.         add     edx, eax
  925.         jmp     @b
  926. .merge_done:
  927.         pop     esi
  928.         or      ebx, FREE_BLOCK
  929.         mov     [page_tabs+ecx*4], ebx
  930. .ret:
  931.         pop     eax edx ecx
  932.         ret
  933. .realloc_add:
  934. ; get some additional memory
  935.         mov     eax, [current_slot]
  936.         mov     eax, [APPDATA.heap_top+eax]
  937.         shr     eax, 12
  938.         cmp     edx, eax
  939.         jae     .cant_inplace
  940.         mov     eax, [page_tabs+edx*4]
  941.         shr     eax, 12
  942.         add     eax, edx
  943.         cmp     eax, ebx
  944.         jb      .cant_inplace
  945.         sub     eax, ebx
  946.         jz      @f
  947.         shl     eax, 12
  948.         or      al, FREE_BLOCK
  949.         mov     [page_tabs+ebx*4], eax
  950. @@:
  951.         mov     eax, ebx
  952.         sub     eax, ecx
  953.         shl     eax, 12
  954.         or      al, USED_BLOCK
  955.         mov     [page_tabs+ecx*4], eax
  956.         lea     eax, [ecx+1]
  957.         shl     eax, 12
  958.         push    eax
  959.         push    edi
  960.         lea     edi, [page_tabs+edx*4]
  961.         mov     eax, 2
  962.         sub     ebx, edx
  963.         mov     ecx, ebx
  964.         cld
  965.         rep     stosd
  966.         pop     edi
  967.         mov     edx, [current_slot]
  968.         shl     ebx, 12
  969.         add     ebx, [APPDATA.mem_size+edx]
  970.         call    update_mem_size
  971.         pop     eax edx ecx
  972.         ret
  973. .cant_inplace:
  974.         push    esi edi
  975.         mov     eax, [current_slot]
  976.         mov     esi, [APPDATA.heap_base+eax]
  977.         mov     edi, [APPDATA.heap_top+eax]
  978.         shr     esi, 12
  979.         shr     edi, 12
  980.         sub     ebx, ecx
  981. .find_place:
  982.         cmp     esi, edi
  983.         jae     .place_not_found
  984.         mov     eax, [page_tabs+esi*4]
  985.         test    al, FREE_BLOCK
  986.         jz      .next_place
  987.         shr     eax, 12
  988.         cmp     eax, ebx
  989.         jae     .place_found
  990.         add     esi, eax
  991.         jmp     .find_place
  992. .next_place:
  993.         shr     eax, 12
  994.         add     esi, eax
  995.         jmp     .find_place
  996. .place_not_found:
  997.         pop     edi esi
  998.         jmp     .ret0
  999. .place_found:
  1000.         sub     eax, ebx
  1001.         jz      @f
  1002.         push    esi
  1003.         add     esi, eax
  1004.         shl     eax, 12
  1005.         or      al, FREE_BLOCK
  1006.         mov     [page_tabs+esi*4], eax
  1007.         pop     esi
  1008. @@:
  1009.         mov     eax, ebx
  1010.         shl     eax, 12
  1011.         or      al, USED_BLOCK
  1012.         mov     [page_tabs+esi*4], eax
  1013.         inc     esi
  1014.         mov     eax, esi
  1015.         shl     eax, 12
  1016.         push    eax
  1017.         mov     eax, [page_tabs+ecx*4]
  1018.         and     eax, not 0xFFF
  1019.         or      al, FREE_BLOCK
  1020.         sub     edx, ecx
  1021.         mov     [page_tabs+ecx*4], eax
  1022.         inc     ecx
  1023. @@:
  1024.         xor     eax, eax
  1025.         xchg    eax, [page_tabs+ecx*4]
  1026.         mov     [page_tabs+esi*4], eax
  1027.         mov     eax, ecx
  1028.         shl     eax, 12
  1029.         invlpg  [eax]
  1030.         inc     ecx
  1031.         inc     esi
  1032.         dec     ebx
  1033.         dec     edx
  1034.         jnz     @b
  1035.         push    ebx
  1036.         mov     edx, [current_slot]
  1037.         shl     ebx, 12
  1038.         add     ebx, [APPDATA.mem_size+edx]
  1039.         call    update_mem_size
  1040.         pop     ebx
  1041. @@:
  1042.         mov     dword [page_tabs+esi*4], 2
  1043.         inc     esi
  1044.         dec     ebx
  1045.         jnz     @b
  1046.         pop     eax edi esi edx ecx
  1047.         ret
  1048.  
  1049. if 0
  1050. align 4
  1051. proc alloc_dll
  1052.            pushf
  1053.            cli
  1054.            bsf eax, [dll_map]
  1055.            jnz .find
  1056.            popf
  1057.            xor eax, eax
  1058.            ret
  1059. .find:
  1060.            btr [dll_map], eax
  1061.            popf
  1062.            shl eax, 5
  1063.            add eax, dll_tab
  1064.            ret
  1065. endp
  1066.  
  1067. align 4
  1068. proc alloc_service
  1069.            pushf
  1070.            cli
  1071.            bsf eax, [srv_map]
  1072.            jnz .find
  1073.            popf
  1074.            xor eax, eax
  1075.            ret
  1076. .find:
  1077.            btr [srv_map], eax
  1078.            popf
  1079.            shl eax,0x02
  1080.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1081.            ret
  1082. endp
  1083.  
  1084. end if
  1085.