Subversion Repositories Kolibri OS

Rev

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