Subversion Repositories Kolibri OS

Rev

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

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