Subversion Repositories Kolibri OS

Rev

Rev 593 | 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: 620 $
  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. endp
  652.  
  653. align 4
  654. proc user_alloc stdcall, alloc_size:dword
  655.  
  656.            mov ecx, [alloc_size]
  657.            add ecx, (4095+4096)
  658.            and ecx, not 4095
  659.  
  660.            mov ebx, [current_slot]
  661.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  662.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  663. l_0:
  664.            cmp esi, edi
  665.            jae m_exit
  666.  
  667.            mov ebx, esi
  668.            shr ebx, 12
  669.            mov eax, [page_tabs+ebx*4]
  670.            test al, FREE_BLOCK
  671.            jz test_used
  672.            and eax, 0xFFFFF000
  673.            cmp eax, ecx    ;alloc_size
  674.            jb  m_next
  675.            jz  @f
  676.  
  677.            lea edx, [esi+ecx]
  678.            sub eax, ecx
  679.            or al, FREE_BLOCK
  680.            shr edx, 12
  681.            mov [page_tabs+edx*4], eax
  682. @@:
  683.            or ecx, USED_BLOCK
  684.            mov [page_tabs+ebx*4], ecx
  685.            shr ecx, 12
  686.            inc ebx
  687.            dec ecx
  688.            jz  .no
  689. @@:
  690.            mov dword [page_tabs+ebx*4], 2
  691.            inc ebx
  692.            dec ecx
  693.            jnz @B
  694. .no:
  695.  
  696.            mov     edx, [current_slot]
  697.            mov     ebx, [alloc_size]
  698.            add     ebx, 0xFFF
  699.            and     ebx, not 0xFFF
  700.            add     ebx, [edx+APPDATA.mem_size]
  701.            call    update_mem_size
  702.  
  703.            lea eax, [esi+4096]
  704.            ret
  705. test_used:
  706.            test al, USED_BLOCK
  707.            jz m_exit
  708.  
  709.            and eax, 0xFFFFF000
  710. m_next:
  711.            add esi, eax
  712.            jmp l_0
  713. m_exit:
  714.            xor eax, eax
  715.            ret
  716. endp
  717.  
  718. align 4
  719. proc user_free stdcall, base:dword
  720.  
  721.            mov esi, [base]
  722.            test esi, esi
  723.            jz .exit
  724.  
  725.            xor ebx, ebx
  726.            shr esi, 12
  727.            mov eax, [page_tabs+(esi-1)*4]
  728.            test al, USED_BLOCK
  729.            jz .cantfree
  730.            test al, DONT_FREE_BLOCK
  731.            jnz .cantfree
  732.  
  733.            and eax, not 4095
  734.            mov ecx, eax
  735.            or al, FREE_BLOCK
  736.            mov [page_tabs+(esi-1)*4], eax
  737.            sub ecx, 4096
  738.            mov ebx, ecx
  739.            shr ecx, 12
  740.            jz .released
  741. .release:
  742.            xor eax, eax
  743.            xchg eax, [page_tabs+esi*4]
  744.            test al, 1
  745.            jz @F
  746.            call free_page
  747.            mov eax, esi
  748.            shl eax, 12
  749.            invlpg [eax]
  750. @@:
  751.            inc esi
  752.            dec ecx
  753.            jnz .release
  754. .released:
  755.            mov edx, [current_slot]
  756.            mov esi, dword [edx+APPDATA.heap_base]
  757.            mov edi, dword [edx+APPDATA.heap_top]
  758.            sub ebx, [edx+APPDATA.mem_size]
  759.            neg ebx
  760.            call update_mem_size
  761.            call user_normalize
  762.            ret
  763. .exit:
  764.            xor eax, eax
  765.            inc eax
  766.            ret
  767. .cantfree:
  768.            xor eax, eax
  769.            ret
  770. endp
  771.  
  772. user_normalize:
  773. ; in: esi=heap_base, edi=heap_top
  774. ; out: eax=0 <=> OK
  775. ; destroys: ebx,edx,esi,edi
  776.            shr esi, 12
  777.            shr edi, 12
  778. @@:
  779.            mov eax, [page_tabs+esi*4]
  780.            test al, USED_BLOCK
  781.            jz .test_free
  782.            shr eax, 12
  783.            add esi, eax
  784.            jmp @B
  785. .test_free:
  786.            test al, FREE_BLOCK
  787.            jz .err
  788.            mov edx, eax
  789.            shr edx, 12
  790.            add edx, esi
  791.            cmp edx, edi
  792.            jae .exit
  793.  
  794.            mov ebx, [page_tabs+edx*4]
  795.            test bl, USED_BLOCK
  796.            jz .next_free
  797.  
  798.            shr ebx, 12
  799.            add edx, ebx
  800.            mov esi, edx
  801.            jmp @B
  802. .next_free:
  803.            test bl, FREE_BLOCK
  804.            jz .err
  805.            and dword [page_tabs+edx*4], 0
  806.            add eax, ebx
  807.            and eax, not 4095
  808.            or eax, FREE_BLOCK
  809.            mov [page_tabs+esi*4], eax
  810.            jmp @B
  811. .exit:
  812.            xor eax, eax
  813.            inc eax
  814.            ret
  815. .err:
  816.            xor eax, eax
  817.            ret
  818.  
  819. user_realloc:
  820. ; in: eax = pointer, ebx = new size
  821. ; out: eax = new pointer or NULL
  822.         test    eax, eax
  823.         jnz     @f
  824. ; realloc(NULL,sz) - same as malloc(sz)
  825.         push    ebx
  826.         call    user_alloc
  827.         ret
  828. @@:
  829.         push    ecx edx
  830.         lea     ecx, [eax - 0x1000]
  831.         shr     ecx, 12
  832.         mov     edx, [page_tabs+ecx*4]
  833.         test    dl, USED_BLOCK
  834.         jnz     @f
  835. ; attempt to realloc invalid pointer
  836. .ret0:
  837.         pop     edx ecx
  838.         xor     eax, eax
  839.         ret
  840. @@:
  841.         test    dl, DONT_FREE_BLOCK
  842.         jnz     .ret0
  843.         add     ebx, 0x1FFF
  844.         shr     edx, 12
  845.         shr     ebx, 12
  846. ; edx = allocated size, ebx = new size
  847.         add     edx, ecx
  848.         add     ebx, ecx
  849.         cmp     edx, ebx
  850.         jb      .realloc_add
  851. ; release part of allocated memory
  852. .loop:
  853.         cmp     edx, ebx
  854.         jz      .release_done
  855.         dec     edx
  856.         xor     eax, eax
  857.         xchg    eax, [page_tabs+edx*4]
  858.         test    al, 1
  859.         jz      .loop
  860.         call    free_page
  861.         mov     eax, edx
  862.         shl     eax, 12
  863.         invlpg  [eax]
  864.         jmp     .loop
  865. .release_done:
  866.         sub     ebx, ecx
  867.         cmp     ebx, 1
  868.         jnz     .nofreeall
  869.         mov     eax, [page_tabs+ecx*4]
  870.         and     eax, not 0xFFF
  871.         mov     edx, [current_slot]
  872.         mov     ebx, [APPDATA.mem_size+edx]
  873.         sub     ebx, eax
  874.         add     ebx, 0x1000
  875.         or      al, FREE_BLOCK
  876.         mov     [page_tabs+ecx*4], eax
  877.         push    esi edi
  878.         mov     esi, [APPDATA.heap_base+edx]
  879.         mov     edi, [APPDATA.heap_top+edx]
  880.         call    update_mem_size
  881.         call    user_normalize
  882.         pop     edi esi
  883.         jmp     .ret0   ; all freed
  884. .nofreeall:
  885.         sub     edx, ecx
  886.         shl     ebx, 12
  887.         or      ebx, USED_BLOCK
  888.         xchg    [page_tabs+ecx*4], ebx
  889.         shr     ebx, 12
  890.         sub     ebx, edx
  891.         push    ebx ecx edx
  892.         mov     edx, [current_slot]
  893.         shl     ebx, 12
  894.         sub     ebx, [APPDATA.mem_size+edx]
  895.         neg     ebx
  896.         call    update_mem_size
  897.         pop     edx ecx ebx
  898.         lea     eax, [ecx+1]
  899.         shl     eax, 12
  900.         push    eax
  901.         add     ecx, ebx
  902.         add     edx, ecx
  903.         shl     ebx, 12
  904.         jz      .ret
  905.         push    esi
  906.         mov     esi, [current_slot]
  907.         mov     esi, [APPDATA.heap_top+esi]
  908.         shr     esi, 12
  909. @@:
  910.         cmp     edx, esi
  911.         jae     .merge_done
  912.         mov     eax, [page_tabs+edx*4]
  913.         test    al, USED_BLOCK
  914.         jz      .merge_done
  915.         and     dword [page_tabs+edx*4], 0
  916.         and     eax, not 0xFFF
  917.         add     ebx, eax
  918.         add     edx, eax
  919.         jmp     @b
  920. .merge_done:
  921.         pop     esi
  922.         or      ebx, FREE_BLOCK
  923.         mov     [page_tabs+ecx*4], ebx
  924. .ret:
  925.         pop     eax edx ecx
  926.         ret
  927. .realloc_add:
  928. ; get some additional memory
  929.         mov     eax, [current_slot]
  930.         mov     eax, [APPDATA.heap_top+eax]
  931.         shr     eax, 12
  932.         cmp     edx, eax
  933.         jae     .cant_inplace
  934.         mov     eax, [page_tabs+edx*4]
  935.         test    al, FREE_BLOCK
  936.         jz      .cant_inplace
  937.         shr     eax, 12
  938.         add     eax, edx
  939.         sub     eax, ebx
  940.         jb      .cant_inplace
  941.         jz      @f
  942.         shl     eax, 12
  943.         or      al, FREE_BLOCK
  944.         mov     [page_tabs+ebx*4], eax
  945. @@:
  946.         mov     eax, ebx
  947.         sub     eax, ecx
  948.         shl     eax, 12
  949.         or      al, USED_BLOCK
  950.         mov     [page_tabs+ecx*4], eax
  951.         lea     eax, [ecx+1]
  952.         shl     eax, 12
  953.         push    eax
  954.         push    edi
  955.         lea     edi, [page_tabs+edx*4]
  956.         mov     eax, 2
  957.         sub     ebx, edx
  958.         mov     ecx, ebx
  959.         cld
  960.         rep     stosd
  961.         pop     edi
  962.         mov     edx, [current_slot]
  963.         shl     ebx, 12
  964.         add     ebx, [APPDATA.mem_size+edx]
  965.         call    update_mem_size
  966.         pop     eax edx ecx
  967.         ret
  968. .cant_inplace:
  969.         push    esi edi
  970.         mov     eax, [current_slot]
  971.         mov     esi, [APPDATA.heap_base+eax]
  972.         mov     edi, [APPDATA.heap_top+eax]
  973.         shr     esi, 12
  974.         shr     edi, 12
  975.         sub     ebx, ecx
  976. .find_place:
  977.         cmp     esi, edi
  978.         jae     .place_not_found
  979.         mov     eax, [page_tabs+esi*4]
  980.         test    al, FREE_BLOCK
  981.         jz      .next_place
  982.         shr     eax, 12
  983.         cmp     eax, ebx
  984.         jae     .place_found
  985.         add     esi, eax
  986.         jmp     .find_place
  987. .next_place:
  988.         shr     eax, 12
  989.         add     esi, eax
  990.         jmp     .find_place
  991. .place_not_found:
  992.         pop     edi esi
  993.         jmp     .ret0
  994. .place_found:
  995.         sub     eax, ebx
  996.         jz      @f
  997.         push    esi
  998.         add     esi, ebx
  999.         shl     eax, 12
  1000.         or      al, FREE_BLOCK
  1001.         mov     [page_tabs+esi*4], eax
  1002.         pop     esi
  1003. @@:
  1004.         mov     eax, ebx
  1005.         shl     eax, 12
  1006.         or      al, USED_BLOCK
  1007.         mov     [page_tabs+esi*4], eax
  1008.         inc     esi
  1009.         mov     eax, esi
  1010.         shl     eax, 12
  1011.         push    eax
  1012.         mov     eax, [page_tabs+ecx*4]
  1013.         and     eax, not 0xFFF
  1014.         or      al, FREE_BLOCK
  1015.         sub     edx, ecx
  1016.         mov     [page_tabs+ecx*4], eax
  1017.         inc     ecx
  1018.         dec     ebx
  1019.         dec     edx
  1020.         jz      .no
  1021. @@:
  1022.         xor     eax, eax
  1023.         xchg    eax, [page_tabs+ecx*4]
  1024.         mov     [page_tabs+esi*4], eax
  1025.         mov     eax, ecx
  1026.         shl     eax, 12
  1027.         invlpg  [eax]
  1028.         inc     esi
  1029.         inc     ecx
  1030.         dec     ebx
  1031.         dec     edx
  1032.         jnz     @b
  1033. .no:
  1034.         push    ebx
  1035.         mov     edx, [current_slot]
  1036.         shl     ebx, 12
  1037.         add     ebx, [APPDATA.mem_size+edx]
  1038.         call    update_mem_size
  1039.         pop     ebx
  1040. @@:
  1041.         mov     dword [page_tabs+esi*4], 2
  1042.         inc     esi
  1043.         dec     ebx
  1044.         jnz     @b
  1045.         pop     eax edi esi edx ecx
  1046.         ret
  1047.  
  1048. if 0
  1049. align 4
  1050. proc alloc_dll
  1051.            pushf
  1052.            cli
  1053.            bsf eax, [dll_map]
  1054.            jnz .find
  1055.            popf
  1056.            xor eax, eax
  1057.            ret
  1058. .find:
  1059.            btr [dll_map], eax
  1060.            popf
  1061.            shl eax, 5
  1062.            add eax, dll_tab
  1063.            ret
  1064. endp
  1065.  
  1066. align 4
  1067. proc alloc_service
  1068.            pushf
  1069.            cli
  1070.            bsf eax, [srv_map]
  1071.            jnz .find
  1072.            popf
  1073.            xor eax, eax
  1074.            ret
  1075. .find:
  1076.            btr [srv_map], eax
  1077.            popf
  1078.            shl eax,0x02
  1079.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1080.            ret
  1081. endp
  1082.  
  1083. end if
  1084.