Subversion Repositories Kolibri OS

Rev

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