Subversion Repositories Kolibri OS

Rev

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

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