Subversion Repositories Kolibri OS

Rev

Rev 823 | Rev 839 | 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: 837 $
  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 - OS_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_small_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. ; param
  213. ;  eax= required size
  214. ;
  215. ; retval
  216. ;  edi= memory block descriptor
  217. ;  ebx= descriptor index
  218. align 4
  219. get_large_block:
  220.            mov edx, -1
  221.            mov ecx, eax
  222.            shr ecx, 22
  223.            dec ecx
  224.            cmp ecx, 31
  225.            jle .get_index
  226.            mov ecx, 31
  227. .get_index:
  228.            shl edx, cl
  229.            and edx, [large_block_mask]
  230. .find:
  231.            bsf edi, edx
  232.            mov ebx, edi
  233.            mov edi, [large_block_list+edi*4]
  234. .check_size:
  235.            cmp eax, [edi+block_size]
  236.            ja .next
  237.            ret
  238. .next:
  239.            mov edi, [edi+list_fd]
  240.            test edi, edi
  241.            jnz .check_size
  242. .fail:
  243.            xor edi, edi
  244.            ret
  245.  
  246. align 4
  247. alloc_mem_block:
  248.  
  249.            mov ebx, [mem_block_start]
  250.            mov ecx, [mem_block_end]
  251. .l1:
  252.            bsf eax,[ebx];
  253.            jnz found
  254.            add ebx,4
  255.            cmp ebx, ecx
  256.            jb .l1
  257.            xor eax,eax
  258.            ret
  259.  
  260. found:
  261.            btr [ebx], eax
  262.            mov [mem_block_start],ebx
  263.            sub ebx, mem_block_map
  264.            lea eax,[eax+ebx*8]
  265.            shl eax, 5
  266.            add eax, [mem_block_arr]
  267.            dec [free_blocks]
  268.            ret
  269. align 4
  270. free_mem_block:
  271.            mov dword [eax], 0
  272.            mov dword [eax+4], 0
  273.            mov dword [eax+8], 0
  274.            mov dword [eax+12], 0
  275.            mov dword [eax+16], 0
  276. ;           mov dword [eax+20], 0
  277.            mov dword [eax+24], 0
  278.            mov dword [eax+28], 0
  279.  
  280.            sub eax, [mem_block_arr]
  281.            shr eax, 5
  282.  
  283.            mov ebx, mem_block_map
  284.            bts [ebx], eax
  285.            inc [free_blocks]
  286.            shr eax, 3
  287.            and eax, not 3
  288.            add eax, ebx
  289.            cmp [mem_block_start], eax
  290.            ja @f
  291.            ret
  292. @@:
  293.            mov [mem_block_start], eax
  294.            ret
  295. .err:
  296.            xor eax, eax
  297.            ret
  298.  
  299. align 4
  300. proc alloc_kernel_space stdcall, size:dword
  301.            local block_ind:DWORD
  302.  
  303.            push ebx
  304.            push esi
  305.            push edi
  306.  
  307.            mov eax, [size]
  308.            add eax, 4095
  309.            and eax, not 4095
  310.            mov [size], eax
  311.  
  312.            mov ebx, heap_mutex
  313.            call wait_mutex    ;ebx
  314.  
  315.            cmp eax, [heap_free]
  316.            ja .error
  317.  
  318.            call get_small_block ; eax
  319.            test edi, edi
  320.            jz .error
  321.  
  322.            cmp [edi+block_flags], FREE_BLOCK
  323.            jne .error
  324.  
  325.            mov [block_ind], ebx   ;index of allocated block
  326.  
  327.            mov eax, [edi+block_size]
  328.            cmp eax, [size]
  329.            je .m_eq_size
  330.  
  331.            call alloc_mem_block
  332.            and eax, eax
  333.            jz .error
  334.  
  335.            mov esi, eax           ;esi - splitted block
  336.  
  337.            mov [esi+block_next], edi
  338.            mov eax, [edi+block_prev]
  339.            mov [esi+block_prev], eax
  340.            mov [edi+block_prev], esi
  341.            mov [esi+list_fd], 0
  342.            mov [esi+list_bk], 0
  343.            and eax, eax
  344.            jz @f
  345.            mov [eax+block_next], esi
  346. @@:
  347.            mov ebx, [edi+block_base]
  348.            mov [esi+block_base], ebx
  349.            mov edx, [size]
  350.            mov [esi+block_size], edx
  351.            add [edi+block_base], edx
  352.            sub [edi+block_size], edx
  353.  
  354.            mov eax, [edi+block_size]
  355.            shr eax, 12
  356.            sub eax, 1
  357.            cmp eax, 63
  358.            jna @f
  359.            mov eax, 63
  360. @@:
  361.            cmp eax, [block_ind]
  362.            je .m_eq_ind
  363.  
  364.            remove_from_list edi
  365.  
  366.            mov ecx, [block_ind]
  367.            mov [mem_block_list+ecx*4], edx
  368.  
  369.            test edx, edx
  370.            jnz @f
  371.            btr [mem_block_mask], ecx
  372. @@:
  373.            mov edx, [mem_block_list+eax*4]
  374.            mov [edi+list_fd], edx
  375.            test edx, edx
  376.            jz @f
  377.            mov [edx+list_bk], edi
  378. @@:
  379.            mov [mem_block_list+eax*4], edi
  380.            bts [mem_block_mask], eax
  381. .m_eq_ind:
  382.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  383.            mov edx, [ecx+list_fd]
  384.            mov [esi+list_fd], edx
  385.            mov [esi+list_bk], ecx
  386.            mov [ecx+list_fd], esi
  387.            mov [edx+list_bk], esi
  388.  
  389.            mov [esi+block_flags], USED_BLOCK
  390.            mov eax, [esi+block_base]
  391.            mov ebx, [size]
  392.            sub [heap_free], ebx
  393.            and [heap_mutex], 0
  394.            pop edi
  395.            pop esi
  396.            pop ebx
  397.            ret
  398. .m_eq_size:
  399.            remove_from_list edi
  400.            mov [mem_block_list+ebx*4], edx
  401.            and edx, edx
  402.            jnz @f
  403.            btr [mem_block_mask], ebx
  404. @@:
  405.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  406.            mov edx, [ecx+list_fd]
  407.            mov [edi+list_fd], edx
  408.            mov [edi+list_bk], ecx
  409.            mov [ecx+list_fd], edi
  410.            mov [edx+list_bk], edi
  411.  
  412.            mov [edi+block_flags], USED_BLOCK
  413.            mov eax, [edi+block_base]
  414.            mov ebx, [size]
  415.            sub [heap_free], ebx
  416.            and [heap_mutex], 0
  417.            pop edi
  418.            pop esi
  419.            pop ebx
  420.            ret
  421. .error:
  422.            xor eax, eax
  423.            mov [heap_mutex], eax
  424.            pop edi
  425.            pop esi
  426.            pop ebx
  427.            ret
  428. endp
  429.  
  430. align 4
  431. proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
  432.            push ebx
  433.            push esi
  434.            push edi
  435.            mov ebx, heap_mutex
  436.            call wait_mutex    ;ebx
  437.  
  438.            mov eax, [base]
  439.            mov esi, [mem_used.fd]
  440. @@:
  441.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  442.            je .fail
  443.  
  444.            cmp [esi+block_base], eax
  445.            je .found
  446.            mov esi, [esi+list_fd]
  447.            jmp @b
  448. .found:
  449.            cmp [esi+block_flags], USED_BLOCK
  450.            jne .fail
  451.  
  452.            mov eax, [esi+block_size]
  453.            add [heap_free], eax
  454.  
  455.            mov edi, [esi+block_next]
  456.            test edi, edi
  457.            jz .prev
  458.  
  459.            cmp [edi+block_flags], FREE_BLOCK
  460.            jne .prev
  461.  
  462.            remove_from_free edi
  463.  
  464.            mov edx, [edi+block_next]
  465.            mov [esi+block_next], edx
  466.            test edx, edx
  467.            jz @f
  468.  
  469.            mov [edx+block_prev], esi
  470. @@:
  471.            mov ecx, [edi+block_size]
  472.            add [esi+block_size], ecx
  473.  
  474.            mov eax, edi
  475.            call free_mem_block
  476. .prev:
  477.            mov edi, [esi+block_prev]
  478.            test edi, edi
  479.            jz .insert
  480.  
  481.            cmp [edi+block_flags], FREE_BLOCK
  482.            jne .insert
  483.  
  484.            remove_from_used esi
  485.  
  486.            mov edx, [esi+block_next]
  487.            mov [edi+block_next], edx
  488.            test edx, edx
  489.            jz @f
  490.            mov [edx+block_prev], edi
  491. @@:
  492.            mov eax, esi
  493.            call free_mem_block
  494.  
  495.            mov ecx, [edi+block_size]
  496.            mov eax, [esi+block_size]
  497.            add eax, ecx
  498.            mov [edi+block_size], eax
  499.  
  500.            calc_index eax
  501.            calc_index ecx
  502.            cmp eax, ecx
  503.            je .m_eq
  504.  
  505.            push ecx
  506.            remove_from_list edi
  507.            pop ecx
  508.  
  509.            cmp [mem_block_list+ecx*4], edi
  510.            jne @f
  511.            mov [mem_block_list+ecx*4], edx
  512. @@:
  513.            cmp [mem_block_list+ecx*4], 0
  514.            jne @f
  515.            btr [mem_block_mask], ecx
  516. @@:
  517.            mov esi, [mem_block_list+eax*4]
  518.            mov [mem_block_list+eax*4], edi
  519.            mov [edi+list_fd], esi
  520.            test esi, esi
  521.            jz @f
  522.            mov [esi+list_bk], edi
  523. @@:
  524.            bts [mem_block_mask], eax
  525. .m_eq:
  526.            xor eax, eax
  527.            mov [heap_mutex], eax
  528.            dec eax
  529.            pop edi
  530.            pop esi
  531.            pop ebx
  532.            ret
  533. .insert:
  534.            remove_from_used esi
  535.  
  536.            mov eax, [esi+block_size]
  537.            calc_index eax
  538.  
  539.            mov edi, [mem_block_list+eax*4]
  540.            mov [mem_block_list+eax*4], esi
  541.            mov [esi+list_fd], edi
  542.            test edi, edi
  543.            jz @f
  544.            mov [edi+list_bk], esi
  545. @@:
  546.            bts [mem_block_mask], eax
  547.            mov [esi+block_flags],FREE_BLOCK
  548.            xor eax, eax
  549.            mov [heap_mutex], eax
  550.            dec eax
  551.            pop edi
  552.            pop esi
  553.            pop ebx
  554.            ret
  555. .fail:
  556.            xor eax, eax
  557.            mov [heap_mutex], eax
  558.            pop edi
  559.            pop esi
  560.            pop ebx
  561.            ret
  562. endp
  563.  
  564. align 4
  565. proc kernel_alloc stdcall, size:dword
  566.            locals
  567.              lin_addr    dd ?
  568.              pages_count dd ?
  569.            endl
  570.  
  571.            push ebx
  572.            push edi
  573.  
  574.            mov eax, [size]
  575.            add eax, 4095
  576.            and eax, not 4095;
  577.            mov [size], eax
  578.            and eax, eax
  579.            jz .err
  580.            mov ebx, eax
  581.            shr ebx, 12
  582.            mov [pages_count], ebx
  583.  
  584.            stdcall alloc_kernel_space, eax
  585.            test eax, eax
  586.            jz .err
  587.            mov [lin_addr], eax
  588.  
  589.            mov ecx, [pages_count]
  590.            mov edx, eax
  591.            mov ebx, ecx
  592.  
  593.            shr ecx, 3
  594.            jz .next
  595.  
  596.            and ebx, not 7
  597.            push ebx
  598.            stdcall alloc_pages, ebx
  599.            pop ecx                   ; yes ecx!!!
  600.            and eax, eax
  601.            jz .err
  602.  
  603.            mov edi, eax
  604.            mov edx, [lin_addr]
  605. @@:
  606.            stdcall map_page,edx,edi,dword PG_SW
  607.            add edx, 0x1000
  608.            add edi, 0x1000
  609.            dec ecx
  610.            jnz @B
  611. .next:
  612.            mov ecx, [pages_count]
  613.            and ecx, 7
  614.            jz .end
  615. @@:
  616.            push ecx
  617.            call alloc_page
  618.            pop ecx
  619.            test eax, eax
  620.            jz .err
  621.  
  622.            stdcall map_page,edx,eax,dword PG_SW
  623.            add edx, 0x1000
  624.            dec ecx
  625.            jnz @B
  626. .end:
  627.            mov eax, [lin_addr]
  628.            pop edi
  629.            pop ebx
  630.            ret
  631. .err:
  632.            xor eax, eax
  633.            pop edi
  634.            pop ebx
  635.            ret
  636. endp
  637.  
  638. align 4
  639. proc kernel_free stdcall, base:dword
  640.            push ebx esi
  641.  
  642.            mov ebx, heap_mutex
  643.            call wait_mutex    ;ebx
  644.  
  645.            mov eax, [base]
  646.            mov esi, [mem_used.fd]
  647. @@:
  648.            cmp esi, mem_used.fd-MEM_LIST_OFFSET
  649.            je .fail
  650.  
  651.            cmp [esi+block_base], eax
  652.            je .found
  653.            mov esi, [esi+list_fd]
  654.            jmp @b
  655. .found:
  656.            cmp [esi+block_flags], USED_BLOCK
  657.            jne .fail
  658.  
  659.            and [heap_mutex], 0
  660.  
  661.            push ecx
  662.            mov ecx, [esi+block_size];
  663.            shr ecx, 12
  664.            call release_pages   ;eax, ecx
  665.            pop ecx
  666.            stdcall free_kernel_space, [base]
  667.            pop esi ebx
  668.            ret
  669. .fail:
  670.            and [heap_mutex], 0
  671.            pop esi ebx
  672.            ret
  673. endp
  674.  
  675.  
  676. align 4
  677. proc alloc_large stdcall, size:dword
  678.            local block_ind:DWORD
  679.  
  680.            push ebx
  681.            push esi
  682.            push edi
  683.  
  684.            mov eax, [size]
  685.            add eax, 0x3FFFFF
  686.            and eax, not 0x3FFFFF
  687.            mov [size], eax
  688.  
  689.          ;  mov ebx, heap_mutex
  690.          ;  call wait_mutex    ;ebx
  691.  
  692.          ;  cmp eax, [heap_free]
  693.          ;  ja .error
  694.  
  695.            call get_large_block ; eax
  696.            test edi, edi
  697.            jz .error
  698.  
  699.            cmp [edi+block_flags], FREE_BLOCK
  700.            jne .error
  701.  
  702.            mov [block_ind], ebx   ;index of allocated block
  703.  
  704.            mov eax, [edi+block_size]
  705.            cmp eax, [size]
  706.            je .m_eq_size
  707.  
  708.            call alloc_mem_block
  709.            and eax, eax
  710.            jz .error
  711.  
  712.            mov esi, eax           ;esi - splitted block
  713.  
  714.            mov [esi+block_next], edi
  715.            mov eax, [edi+block_prev]
  716.            mov [esi+block_prev], eax
  717.            mov [edi+block_prev], esi
  718.            mov [esi+list_fd], 0
  719.            mov [esi+list_bk], 0
  720.            test eax, eax
  721.            jz @f
  722.            mov [eax+block_next], esi
  723. @@:
  724.            mov ebx, [edi+block_base]
  725.            mov [esi+block_base], ebx
  726.            mov edx, [size]
  727.            mov [esi+block_size], edx
  728.            add [edi+block_base], edx
  729.            sub [edi+block_size], edx
  730.  
  731.            mov eax, [edi+block_size]
  732.            shr eax, 22
  733.            dec eax
  734.            cmp eax, 31
  735.            jna @f
  736.            mov eax, 31
  737. @@:
  738.            cmp eax, [block_ind]
  739.            je .m_eq_ind
  740.  
  741.            remove_from_list edi
  742.  
  743.            mov ecx, [block_ind]
  744.            mov [large_block_list+ecx*4], edx
  745.  
  746.            test edx, edx
  747.            jnz @f
  748.            btr [large_block_mask], ecx
  749. @@:
  750.            mov edx, [large_block_list+eax*4]
  751.            mov [edi+list_fd], edx
  752.            test edx, edx
  753.            jz @f
  754.            mov [edx+list_bk], edi
  755. @@:
  756.            mov [large_block_list+eax*4], edi
  757.            bts [large_block_mask], eax
  758. .m_eq_ind:
  759.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  760.            mov edx, [ecx+list_fd]
  761.            mov [esi+list_fd], edx
  762.            mov [esi+list_bk], ecx
  763.            mov [ecx+list_fd], esi
  764.            mov [edx+list_bk], esi
  765.  
  766.            mov [esi+block_flags], USED_BLOCK
  767.            mov eax, [esi+block_base]
  768.            mov ebx, [size]
  769.            sub [heap_free], ebx
  770.            and [heap_mutex], 0
  771.            pop edi
  772.            pop esi
  773.            pop ebx
  774.            ret
  775. .m_eq_size:
  776.            remove_from_list edi
  777.            mov [large_block_list+ebx*4], edx
  778.            and edx, edx
  779.            jnz @f
  780.            btr [large_block_mask], ebx
  781. @@:
  782.            mov ecx, mem_used.fd-MEM_LIST_OFFSET
  783.            mov edx, [ecx+list_fd]
  784.            mov [edi+list_fd], edx
  785.            mov [edi+list_bk], ecx
  786.            mov [ecx+list_fd], edi
  787.            mov [edx+list_bk], edi
  788.  
  789.            mov [edi+block_flags], USED_BLOCK
  790.            mov eax, [edi+block_base]
  791.            mov ebx, [size]
  792.            sub [heap_free], ebx
  793.            and [heap_mutex], 0
  794.            pop edi
  795.            pop esi
  796.            pop ebx
  797.            ret
  798. .error:
  799.            xor eax, eax
  800.            mov [heap_mutex], eax
  801.            pop edi
  802.            pop esi
  803.            pop ebx
  804.            ret
  805. endp
  806.  
  807. restore block_next
  808. restore block_prev
  809. restore block_list
  810. restore block_base
  811. restore block_size
  812. restore block_flags
  813.  
  814. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  815.  
  816. HEAP_TOP  equ 0x5FC00000
  817.  
  818. align 4
  819. proc init_heap
  820.  
  821.            mov ebx,[current_slot]
  822.            mov eax, [ebx+APPDATA.heap_top]
  823.            test eax, eax
  824.            jz @F
  825.            sub eax,[ebx+APPDATA.heap_base]
  826.            sub eax, 4096
  827.            ret
  828. @@:
  829.            mov esi, [ebx+APPDATA.mem_size]
  830.            add esi, 4095
  831.            and esi, not 4095
  832.            mov [ebx+APPDATA.mem_size], esi
  833.            mov eax, HEAP_TOP
  834.            mov [ebx+APPDATA.heap_base], esi
  835.            mov [ebx+APPDATA.heap_top], eax
  836.  
  837.            sub eax, esi
  838.            shr esi, 10
  839.            mov ecx, eax
  840.            sub eax, 4096
  841.            or ecx, FREE_BLOCK
  842.            mov [page_tabs+esi], ecx
  843.            ret
  844. endp
  845.  
  846. align 4
  847. proc user_alloc stdcall, alloc_size:dword
  848.  
  849.            push ebx
  850.            push esi
  851.            push edi
  852.  
  853.            mov ecx, [alloc_size]
  854.            add ecx, (4095+4096)
  855.            and ecx, not 4095
  856.  
  857.            mov ebx, [current_slot]
  858.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  859.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  860. l_0:
  861.            cmp esi, edi
  862.            jae m_exit
  863.  
  864.            mov ebx, esi
  865.            shr ebx, 12
  866.            mov eax, [page_tabs+ebx*4]
  867.            test al, FREE_BLOCK
  868.            jz test_used
  869.            and eax, 0xFFFFF000
  870.            cmp eax, ecx    ;alloc_size
  871.            jb  m_next
  872.            jz  @f
  873.  
  874.            lea edx, [esi+ecx]
  875.            sub eax, ecx
  876.            or al, FREE_BLOCK
  877.            shr edx, 12
  878.            mov [page_tabs+edx*4], eax
  879. @@:
  880.            or ecx, USED_BLOCK
  881.            mov [page_tabs+ebx*4], ecx
  882.            shr ecx, 12
  883.            inc ebx
  884.            dec ecx
  885.            jz  .no
  886. @@:
  887.            mov dword [page_tabs+ebx*4], 2
  888.            inc ebx
  889.            dec ecx
  890.            jnz @B
  891. .no:
  892.  
  893.            mov     edx, [current_slot]
  894.            mov     ebx, [alloc_size]
  895.            add     ebx, 0xFFF
  896.            and     ebx, not 0xFFF
  897.            add     ebx, [edx+APPDATA.mem_size]
  898.            call    update_mem_size
  899.  
  900.            lea eax, [esi+4096]
  901.  
  902.            pop edi
  903.            pop esi
  904.            pop ebx
  905.            ret
  906. test_used:
  907.            test al, USED_BLOCK
  908.            jz m_exit
  909.  
  910.            and eax, 0xFFFFF000
  911. m_next:
  912.            add esi, eax
  913.            jmp l_0
  914. m_exit:
  915.            xor eax, eax
  916.            pop edi
  917.            pop esi
  918.            pop ebx
  919.            ret
  920. endp
  921.  
  922. align 4
  923. proc user_free stdcall, base:dword
  924.  
  925.            push esi
  926.  
  927.            mov esi, [base]
  928.            test esi, esi
  929.            jz .exit
  930.  
  931.            push ebx
  932.  
  933.            xor ebx, ebx
  934.            shr esi, 12
  935.            mov eax, [page_tabs+(esi-1)*4]
  936.            test al, USED_BLOCK
  937.            jz .cantfree
  938.            test al, DONT_FREE_BLOCK
  939.            jnz .cantfree
  940.  
  941.            and eax, not 4095
  942.            mov ecx, eax
  943.            or al, FREE_BLOCK
  944.            mov [page_tabs+(esi-1)*4], eax
  945.            sub ecx, 4096
  946.            mov ebx, ecx
  947.            shr ecx, 12
  948.            jz .released
  949. .release:
  950.            xor eax, eax
  951.            xchg eax, [page_tabs+esi*4]
  952.            test al, 1
  953.            jz @F
  954.            call free_page
  955.            mov eax, esi
  956.            shl eax, 12
  957.            invlpg [eax]
  958. @@:
  959.            inc esi
  960.            dec ecx
  961.            jnz .release
  962. .released:
  963.            push edi
  964.  
  965.            mov edx, [current_slot]
  966.            mov esi, dword [edx+APPDATA.heap_base]
  967.            mov edi, dword [edx+APPDATA.heap_top]
  968.            sub ebx, [edx+APPDATA.mem_size]
  969.            neg ebx
  970.            call update_mem_size
  971.            call user_normalize
  972.            pop edi
  973.            pop ebx
  974.            pop esi
  975.            ret
  976. .exit:
  977.            xor eax, eax
  978.            inc eax
  979.            pop esi
  980.            ret
  981. .cantfree:
  982.            xor eax, eax
  983.            pop ebx
  984.            pop esi
  985.            ret
  986. endp
  987.  
  988. user_normalize:
  989. ; in: esi=heap_base, edi=heap_top
  990. ; out: eax=0 <=> OK
  991. ; destroys: ebx,edx,esi,edi
  992.            shr esi, 12
  993.            shr edi, 12
  994. @@:
  995.            mov eax, [page_tabs+esi*4]
  996.            test al, USED_BLOCK
  997.            jz .test_free
  998.            shr eax, 12
  999.            add esi, eax
  1000.            jmp @B
  1001. .test_free:
  1002.            test al, FREE_BLOCK
  1003.            jz .err
  1004.            mov edx, eax
  1005.            shr edx, 12
  1006.            add edx, esi
  1007.            cmp edx, edi
  1008.            jae .exit
  1009.  
  1010.            mov ebx, [page_tabs+edx*4]
  1011.            test bl, USED_BLOCK
  1012.            jz .next_free
  1013.  
  1014.            shr ebx, 12
  1015.            add edx, ebx
  1016.            mov esi, edx
  1017.            jmp @B
  1018. .next_free:
  1019.            test bl, FREE_BLOCK
  1020.            jz .err
  1021.            and dword [page_tabs+edx*4], 0
  1022.            add eax, ebx
  1023.            and eax, not 4095
  1024.            or eax, FREE_BLOCK
  1025.            mov [page_tabs+esi*4], eax
  1026.            jmp @B
  1027. .exit:
  1028.            xor eax, eax
  1029.            inc eax
  1030.            ret
  1031. .err:
  1032.            xor eax, eax
  1033.            ret
  1034.  
  1035. user_realloc:
  1036. ; in: eax = pointer, ebx = new size
  1037. ; out: eax = new pointer or NULL
  1038.         test    eax, eax
  1039.         jnz     @f
  1040. ; realloc(NULL,sz) - same as malloc(sz)
  1041.         push    ebx
  1042.         call    user_alloc
  1043.         ret
  1044. @@:
  1045.         push    ecx edx
  1046.         lea     ecx, [eax - 0x1000]
  1047.         shr     ecx, 12
  1048.         mov     edx, [page_tabs+ecx*4]
  1049.         test    dl, USED_BLOCK
  1050.         jnz     @f
  1051. ; attempt to realloc invalid pointer
  1052. .ret0:
  1053.         pop     edx ecx
  1054.         xor     eax, eax
  1055.         ret
  1056. @@:
  1057.         test    dl, DONT_FREE_BLOCK
  1058.         jnz     .ret0
  1059.         add     ebx, 0x1FFF
  1060.         shr     edx, 12
  1061.         shr     ebx, 12
  1062. ; edx = allocated size, ebx = new size
  1063.         add     edx, ecx
  1064.         add     ebx, ecx
  1065.         cmp     edx, ebx
  1066.         jb      .realloc_add
  1067. ; release part of allocated memory
  1068. .loop:
  1069.         cmp     edx, ebx
  1070.         jz      .release_done
  1071.         dec     edx
  1072.         xor     eax, eax
  1073.         xchg    eax, [page_tabs+edx*4]
  1074.         test    al, 1
  1075.         jz      .loop
  1076.         call    free_page
  1077.         mov     eax, edx
  1078.         shl     eax, 12
  1079.         invlpg  [eax]
  1080.         jmp     .loop
  1081. .release_done:
  1082.         sub     ebx, ecx
  1083.         cmp     ebx, 1
  1084.         jnz     .nofreeall
  1085.         mov     eax, [page_tabs+ecx*4]
  1086.         and     eax, not 0xFFF
  1087.         mov     edx, [current_slot]
  1088.         mov     ebx, [APPDATA.mem_size+edx]
  1089.         sub     ebx, eax
  1090.         add     ebx, 0x1000
  1091.         or      al, FREE_BLOCK
  1092.         mov     [page_tabs+ecx*4], eax
  1093.         push    esi edi
  1094.         mov     esi, [APPDATA.heap_base+edx]
  1095.         mov     edi, [APPDATA.heap_top+edx]
  1096.         call    update_mem_size
  1097.         call    user_normalize
  1098.         pop     edi esi
  1099.         jmp     .ret0   ; all freed
  1100. .nofreeall:
  1101.         sub     edx, ecx
  1102.         shl     ebx, 12
  1103.         or      ebx, USED_BLOCK
  1104.         xchg    [page_tabs+ecx*4], ebx
  1105.         shr     ebx, 12
  1106.         sub     ebx, edx
  1107.         push    ebx ecx edx
  1108.         mov     edx, [current_slot]
  1109.         shl     ebx, 12
  1110.         sub     ebx, [APPDATA.mem_size+edx]
  1111.         neg     ebx
  1112.         call    update_mem_size
  1113.         pop     edx ecx ebx
  1114.         lea     eax, [ecx+1]
  1115.         shl     eax, 12
  1116.         push    eax
  1117.         add     ecx, edx
  1118.         lea     edx, [ecx+ebx]
  1119.         shl     ebx, 12
  1120.         jz      .ret
  1121.         push    esi
  1122.         mov     esi, [current_slot]
  1123.         mov     esi, [APPDATA.heap_top+esi]
  1124.         shr     esi, 12
  1125. @@:
  1126.         cmp     edx, esi
  1127.         jae     .merge_done
  1128.         mov     eax, [page_tabs+edx*4]
  1129.         test    al, USED_BLOCK
  1130.         jnz     .merge_done
  1131.         and     dword [page_tabs+edx*4], 0
  1132.         shr     eax, 12
  1133.         add     edx, eax
  1134.         shl     eax, 12
  1135.         add     ebx, eax
  1136.         jmp     @b
  1137. .merge_done:
  1138.         pop     esi
  1139.         or      ebx, FREE_BLOCK
  1140.         mov     [page_tabs+ecx*4], ebx
  1141. .ret:
  1142.         pop     eax edx ecx
  1143.         ret
  1144. .realloc_add:
  1145. ; get some additional memory
  1146.         mov     eax, [current_slot]
  1147.         mov     eax, [APPDATA.heap_top+eax]
  1148.         shr     eax, 12
  1149.         cmp     edx, eax
  1150.         jae     .cant_inplace
  1151.         mov     eax, [page_tabs+edx*4]
  1152.         test    al, FREE_BLOCK
  1153.         jz      .cant_inplace
  1154.         shr     eax, 12
  1155.         add     eax, edx
  1156.         sub     eax, ebx
  1157.         jb      .cant_inplace
  1158.         jz      @f
  1159.         shl     eax, 12
  1160.         or      al, FREE_BLOCK
  1161.         mov     [page_tabs+ebx*4], eax
  1162. @@:
  1163.         mov     eax, ebx
  1164.         sub     eax, ecx
  1165.         shl     eax, 12
  1166.         or      al, USED_BLOCK
  1167.         mov     [page_tabs+ecx*4], eax
  1168.         lea     eax, [ecx+1]
  1169.         shl     eax, 12
  1170.         push    eax
  1171.         push    edi
  1172.         lea     edi, [page_tabs+edx*4]
  1173.         mov     eax, 2
  1174.         sub     ebx, edx
  1175.         mov     ecx, ebx
  1176.         cld
  1177.         rep     stosd
  1178.         pop     edi
  1179.         mov     edx, [current_slot]
  1180.         shl     ebx, 12
  1181.         add     ebx, [APPDATA.mem_size+edx]
  1182.         call    update_mem_size
  1183.         pop     eax edx ecx
  1184.         ret
  1185. .cant_inplace:
  1186.         push    esi edi
  1187.         mov     eax, [current_slot]
  1188.         mov     esi, [APPDATA.heap_base+eax]
  1189.         mov     edi, [APPDATA.heap_top+eax]
  1190.         shr     esi, 12
  1191.         shr     edi, 12
  1192.         sub     ebx, ecx
  1193. .find_place:
  1194.         cmp     esi, edi
  1195.         jae     .place_not_found
  1196.         mov     eax, [page_tabs+esi*4]
  1197.         test    al, FREE_BLOCK
  1198.         jz      .next_place
  1199.         shr     eax, 12
  1200.         cmp     eax, ebx
  1201.         jae     .place_found
  1202.         add     esi, eax
  1203.         jmp     .find_place
  1204. .next_place:
  1205.         shr     eax, 12
  1206.         add     esi, eax
  1207.         jmp     .find_place
  1208. .place_not_found:
  1209.         pop     edi esi
  1210.         jmp     .ret0
  1211. .place_found:
  1212.         sub     eax, ebx
  1213.         jz      @f
  1214.         push    esi
  1215.         add     esi, ebx
  1216.         shl     eax, 12
  1217.         or      al, FREE_BLOCK
  1218.         mov     [page_tabs+esi*4], eax
  1219.         pop     esi
  1220. @@:
  1221.         mov     eax, ebx
  1222.         shl     eax, 12
  1223.         or      al, USED_BLOCK
  1224.         mov     [page_tabs+esi*4], eax
  1225.         inc     esi
  1226.         mov     eax, esi
  1227.         shl     eax, 12
  1228.         push    eax
  1229.         mov     eax, [page_tabs+ecx*4]
  1230.         and     eax, not 0xFFF
  1231.         or      al, FREE_BLOCK
  1232.         sub     edx, ecx
  1233.         mov     [page_tabs+ecx*4], eax
  1234.         inc     ecx
  1235.         dec     ebx
  1236.         dec     edx
  1237.         jz      .no
  1238. @@:
  1239.         xor     eax, eax
  1240.         xchg    eax, [page_tabs+ecx*4]
  1241.         mov     [page_tabs+esi*4], eax
  1242.         mov     eax, ecx
  1243.         shl     eax, 12
  1244.         invlpg  [eax]
  1245.         inc     esi
  1246.         inc     ecx
  1247.         dec     ebx
  1248.         dec     edx
  1249.         jnz     @b
  1250. .no:
  1251.         push    ebx
  1252.         mov     edx, [current_slot]
  1253.         shl     ebx, 12
  1254.         add     ebx, [APPDATA.mem_size+edx]
  1255.         call    update_mem_size
  1256.         pop     ebx
  1257. @@:
  1258.         mov     dword [page_tabs+esi*4], 2
  1259.         inc     esi
  1260.         dec     ebx
  1261.         jnz     @b
  1262.         pop     eax edi esi edx ecx
  1263.         ret
  1264.  
  1265. if 0
  1266. align 4
  1267. proc alloc_dll
  1268.            pushf
  1269.            cli
  1270.            bsf eax, [dll_map]
  1271.            jnz .find
  1272.            popf
  1273.            xor eax, eax
  1274.            ret
  1275. .find:
  1276.            btr [dll_map], eax
  1277.            popf
  1278.            shl eax, 5
  1279.            add eax, dll_tab
  1280.            ret
  1281. endp
  1282.  
  1283. align 4
  1284. proc alloc_service
  1285.            pushf
  1286.            cli
  1287.            bsf eax, [srv_map]
  1288.            jnz .find
  1289.            popf
  1290.            xor eax, eax
  1291.            ret
  1292. .find:
  1293.            btr [srv_map], eax
  1294.            popf
  1295.            shl eax,0x02
  1296.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1297.            ret
  1298. endp
  1299.  
  1300. end if
  1301.