Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 2151 $
  9.  
  10. HASH_IT  = 1
  11.  
  12. struc MEM_BLOCK
  13. {
  14.    .list        LHEAD
  15.    .next_block  dd ? ;+8
  16.    .prev_block  dd ? ;+4
  17.    .base        dd ? ;+16
  18.    .size        dd ? ;+20
  19.    .flags       dd ? ;+24
  20.    .handle      dd ? ;+28
  21.    .sizeof:
  22. }
  23.  
  24. FREE_BLOCK      equ  4
  25. USED_BLOCK      equ  8
  26. DONT_FREE_BLOCK equ  10h
  27.  
  28. virtual at 0
  29.   MEM_BLOCK MEM_BLOCK
  30. end virtual
  31.  
  32.  
  33. block_next   equ MEM_BLOCK.next_block
  34. block_prev   equ MEM_BLOCK.prev_block
  35. list_fd      equ MEM_BLOCK.list.next
  36. list_bk      equ MEM_BLOCK.list.prev
  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_used op
  51. {
  52.            mov edx, [op+list_fd]
  53.            mov ecx, [op+list_bk]
  54.            mov [edx+list_bk], ecx
  55.            mov [ecx+list_fd], edx
  56.            mov [op+list_fd], 0
  57.            mov [op+list_bk], 0
  58. }
  59.  
  60. ;Initial heap state
  61. ;
  62. ;+heap_size               terminator        USED_BLOCK
  63. ;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
  64. ;HEAP_BASE                heap_descriptors  USED_BLOCK
  65. ;
  66.  
  67. align 4
  68. proc init_kernel_heap
  69.  
  70.             mov ecx, 64
  71.             mov edi, mem_block_list
  72. @@:
  73.             mov eax, edi
  74.             stosd
  75.             stosd
  76.             loop @B
  77.  
  78.             mov eax, mem_used.fd
  79.             mov [mem_used.fd], eax
  80.             mov [mem_used.bk], eax
  81.  
  82.             stdcall alloc_pages, dword 32
  83.             mov ecx, 32
  84.             mov edx, eax
  85.             mov edi, HEAP_BASE
  86. .l1:
  87.             stdcall map_page,edi,edx,PG_SW
  88.             add edi, 0x1000
  89.             add edx, 0x1000
  90.             dec ecx
  91.             jnz .l1
  92.  
  93.             mov edi, HEAP_BASE                     ;descriptors
  94.             mov ebx, HEAP_BASE+MEM_BLOCK.sizeof      ;free space
  95.             mov ecx, HEAP_BASE+MEM_BLOCK.sizeof*2    ;terminator
  96.  
  97.             xor eax, eax
  98.             mov [edi+block_next], ebx
  99.             mov [edi+block_prev], eax
  100.             mov [edi+list_fd], eax
  101.             mov [edi+list_bk], eax
  102.             mov [edi+block_base], HEAP_BASE
  103.             mov [edi+block_size], 4096*MEM_BLOCK.sizeof
  104.             mov [edi+block_flags], USED_BLOCK
  105.  
  106.             mov [ecx+block_next], eax
  107.             mov [ecx+block_prev], ebx
  108.             mov [edi+list_fd], eax
  109.             mov [edi+list_bk], eax
  110.             mov [edi+block_base], eax
  111.             mov [edi+block_size], eax
  112.             mov [edi+block_flags], USED_BLOCK
  113.  
  114.             mov [ebx+block_next], ecx
  115.             mov [ebx+block_prev], edi
  116.             mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK.sizeof
  117.  
  118.             mov ecx, [pg_data.kernel_pages]
  119.             shl ecx, 12
  120.             sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK.sizeof
  121.             mov [heap_size], ecx
  122.             mov [heap_free], ecx
  123.             mov [ebx+block_size], ecx
  124.             mov [ebx+block_flags], FREE_BLOCK
  125.  
  126.             mov [mem_block_mask], eax
  127.             mov [mem_block_mask+4],0x80000000
  128.  
  129.             mov ecx, mem_block_list+63*8
  130.             list_add ebx, ecx
  131.  
  132.             mov ecx, 4096-3-1
  133.             mov eax, HEAP_BASE+MEM_BLOCK.sizeof*4
  134.  
  135.             mov [next_memblock], HEAP_BASE+MEM_BLOCK.sizeof*3
  136. @@:
  137.             mov [eax-MEM_BLOCK.sizeof], eax
  138.             add eax, MEM_BLOCK.sizeof
  139.             loop @B
  140.  
  141.             mov [eax-MEM_BLOCK.sizeof], dword 0
  142.  
  143.  
  144.             mov ecx, heap_mutex
  145.             call mutex_init
  146.             mov [heap_blocks], 4094
  147.             mov [free_blocks], 4093
  148.             ret
  149. endp
  150.  
  151. ; param
  152. ;  eax= required size
  153. ;
  154. ; retval
  155. ;  edi= memory block descriptor
  156. ;  ebx= descriptor index
  157.  
  158. align 4
  159. get_small_block:
  160.            mov ecx, eax
  161.            shr ecx, 12
  162.            dec ecx
  163.            cmp ecx, 63
  164.            jle .get_index
  165.            mov ecx, 63
  166. .get_index:
  167.            lea esi, [mem_block_mask]
  168.            xor ebx, ebx
  169.            or edx, -1
  170.  
  171.            cmp ecx, 32
  172.            jb .bit_test
  173.  
  174.            sub ecx, 32
  175.            add ebx, 32
  176.            add esi, 4
  177. .bit_test:
  178.            shl edx, cl
  179.            and edx, [esi]
  180. .find:
  181.            bsf edi, edx
  182.            jz .high_mask
  183.            add ebx, edi
  184.            lea ecx, [mem_block_list+ebx*8]
  185.            mov edi, ecx
  186. .next:
  187.            mov edi, [edi+list_fd]
  188.            cmp edi, ecx
  189.            je .err
  190.            cmp eax, [edi+block_size]
  191.            ja .next
  192.            ret
  193. .err:
  194.            xor edi, edi
  195.            ret
  196.  
  197. .high_mask:
  198.            add esi, 4
  199.            cmp esi, mem_block_mask+8
  200.            jae .err
  201.            add ebx, 32
  202.            mov edx, [esi]
  203.            jmp .find
  204.  
  205.  
  206. align 4
  207. free_mem_block:
  208.            mov ebx, [next_memblock]
  209.            mov [eax], ebx
  210.            mov [next_memblock], eax
  211.            xor ebx, ebx
  212.  
  213.            mov dword [eax+4], ebx
  214.            mov dword [eax+8], ebx
  215.            mov dword [eax+12], ebx
  216.            mov dword [eax+16], ebx
  217. ;           mov dword [eax+20], 0     ;don't clear block size
  218.            mov dword [eax+24], ebx
  219.            mov dword [eax+28], ebx
  220.            inc [free_blocks]
  221.            ret
  222.  
  223. align 4
  224. proc alloc_kernel_space stdcall, size:dword
  225.            local block_ind:DWORD
  226.  
  227. ;           xchg bx, bx
  228.  
  229.            push ebx
  230.            push esi
  231.            push edi
  232.  
  233.            mov eax, [size]
  234.            add eax, 4095
  235.            and eax, not 4095
  236.            mov [size], eax
  237.  
  238.            cmp eax, [heap_free]
  239.            ja .error
  240.  
  241.            mov ecx, heap_mutex
  242.            call mutex_lock
  243.  
  244.            mov eax, [size]
  245.  
  246.            call get_small_block ; eax
  247.            test edi, edi
  248.            jz .error_unlock
  249.  
  250.            cmp [edi+block_flags], FREE_BLOCK
  251.            jne .error_unlock
  252.  
  253.            mov [block_ind], ebx         ;index of allocated block
  254.  
  255.            mov eax, [edi+block_size]
  256.            cmp eax, [size]
  257.            je .m_eq_size
  258.  
  259.            mov esi, [next_memblock]     ;new memory block
  260.            test esi, esi
  261.            jz .error_unlock
  262.  
  263.            dec [free_blocks]
  264.            mov eax, [esi]
  265.            mov [next_memblock], eax
  266.  
  267.            mov [esi+block_next], edi
  268.            mov eax, [edi+block_prev]
  269.            mov [esi+block_prev], eax
  270.            mov [edi+block_prev], esi
  271.            mov [esi+list_fd], 0
  272.            mov [esi+list_bk], 0
  273.            mov [eax+block_next], esi
  274.  
  275.            mov ebx, [edi+block_base]
  276.            mov [esi+block_base], ebx
  277.            mov edx, [size]
  278.            mov [esi+block_size], edx
  279.            add [edi+block_base], edx
  280.            sub [edi+block_size], edx
  281.  
  282.            mov eax, [edi+block_size]
  283.            calc_index eax
  284.            cmp eax, [block_ind]
  285.            je .m_eq_ind
  286.  
  287.            list_del edi
  288.  
  289.            mov ecx, [block_ind]
  290.            lea edx, [mem_block_list+ecx*8]
  291.            cmp edx, [edx]
  292.            jnz @f
  293.            btr [mem_block_mask], ecx
  294. @@:
  295.            bts [mem_block_mask], eax
  296.            lea edx, [mem_block_list+eax*8]   ;edx= list head
  297.            list_add edi, edx
  298. .m_eq_ind:
  299.            mov ecx, mem_used.fd
  300.            mov edx, [ecx+list_fd]
  301.            mov [esi+list_fd], edx
  302.            mov [esi+list_bk], ecx
  303.            mov [ecx+list_fd], esi
  304.            mov [edx+list_bk], esi
  305.  
  306.            mov [esi+block_flags], USED_BLOCK
  307.            mov ebx, [size]
  308.            sub [heap_free], ebx
  309.  
  310. if HASH_IT
  311.            pushad
  312.            mov eax, [esi+block_base]
  313.            mov ebx, [esi+block_base]
  314.            shr ebx, 6
  315.            add eax, ebx
  316.            shr ebx, 6
  317.            add eax, ebx
  318.            shr eax, 12
  319.            and eax, 63
  320.            inc [mem_hash_cnt+eax*4]
  321.            popad
  322. end if
  323.  
  324.            mov ecx, heap_mutex
  325.            call mutex_unlock
  326.            mov eax, [esi+block_base]
  327.            pop edi
  328.            pop esi
  329.            pop ebx
  330.            ret
  331. .m_eq_size:
  332.            list_del edi
  333.            lea edx, [mem_block_list+ebx*8]
  334.            cmp edx, [edx]
  335.            jnz @f
  336.            btr [mem_block_mask], ebx
  337. @@:
  338.            mov ecx, mem_used.fd
  339.            mov edx, [ecx+list_fd]
  340.            mov [edi+list_fd], edx
  341.            mov [edi+list_bk], ecx
  342.            mov [ecx+list_fd], edi
  343.            mov [edx+list_bk], edi
  344.  
  345.            mov [edi+block_flags], USED_BLOCK
  346.            mov ebx, [size]
  347.            sub [heap_free], ebx
  348.  
  349. if HASH_IT
  350.            pushad
  351.            mov eax, [edi+block_base]
  352.            mov ebx, [edi+block_base]
  353.            shr ebx, 6
  354.            add eax, ebx
  355.            shr ebx, 6
  356.            add eax, ebx
  357.            shr eax, 12
  358.            and eax, 63
  359.            inc [mem_hash_cnt+eax*4]
  360.            popad
  361. end if
  362.  
  363.            mov ecx, heap_mutex
  364.            call mutex_unlock
  365.            mov eax, [edi+block_base]
  366.            pop edi
  367.            pop esi
  368.            pop ebx
  369.            ret
  370.  
  371. .error_unlock:
  372.            mov ecx, heap_mutex
  373.            call mutex_unlock
  374. .error:
  375.            xor eax, eax
  376.            pop edi
  377.            pop esi
  378.            pop ebx
  379.            ret
  380. endp
  381.  
  382. align 4
  383. proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
  384.  
  385. ;           xchg bx, bx
  386.  
  387.            mov ecx, heap_mutex
  388.            call mutex_lock
  389.  
  390.            mov eax, [base]
  391.            mov esi, [mem_used.fd]
  392. @@:
  393.            cmp esi, mem_used.fd
  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. if HASH_IT
  405.            pushad
  406.            mov eax, [esi+block_base]
  407.            mov ebx, [esi+block_base]
  408.            shr ebx, 6
  409.            add eax, ebx
  410.            shr ebx, 6
  411.            add eax, ebx
  412.            shr eax, 12
  413.            and eax, 63
  414.            dec [mem_hash_cnt+eax*4]
  415.            popad
  416. end if
  417.            mov eax, [esi+block_size]
  418.            add [heap_free], eax
  419.  
  420.            mov edi, [esi+block_next]
  421.            cmp [edi+block_flags], FREE_BLOCK
  422.            jne .prev
  423.  
  424.            list_del edi
  425.  
  426.            mov edx, [edi+block_next]
  427.            mov [esi+block_next], edx
  428.            mov [edx+block_prev], esi
  429.            mov ecx, [edi+block_size]
  430.            add [esi+block_size], ecx
  431.  
  432.            calc_index ecx
  433.  
  434.            lea edx, [mem_block_list+ecx*8]
  435.            cmp edx, [edx]
  436.            jne @F
  437.            btr [mem_block_mask], ecx
  438. @@:
  439.            mov eax, edi
  440.            call free_mem_block
  441. .prev:
  442.            mov edi, [esi+block_prev]
  443.            cmp [edi+block_flags], FREE_BLOCK
  444.            jne .insert
  445.  
  446.            remove_from_used esi
  447.  
  448.            mov edx, [esi+block_next]
  449.            mov [edi+block_next], edx
  450.            mov [edx+block_prev], edi
  451.  
  452.            mov eax, esi
  453.            call free_mem_block
  454.  
  455.            mov ecx, [edi+block_size]
  456.            mov eax, [esi+block_size]
  457.            add eax, ecx
  458.            mov [edi+block_size], eax
  459.  
  460.            calc_index eax                     ;new index
  461.            calc_index ecx                     ;old index
  462.            cmp eax, ecx
  463.            je .m_eq
  464.  
  465.            push ecx
  466.            list_del edi
  467.            pop ecx
  468.  
  469.            lea edx, [mem_block_list+ecx*8]
  470.            cmp edx, [edx]
  471.            jne .add_block
  472.            btr [mem_block_mask], ecx
  473. .add_block:
  474.            bts [mem_block_mask], eax
  475.            lea edx, [mem_block_list+eax*8]
  476.            list_add edi, edx
  477. .m_eq:
  478.            mov ecx, heap_mutex
  479.            call mutex_unlock
  480.            xor eax, eax
  481.            not eax
  482.            ret
  483. .insert:
  484.            remove_from_used esi
  485.            mov [esi+block_flags], FREE_BLOCK
  486.            mov eax, [esi+block_size]
  487.            calc_index eax
  488.            mov edi, esi
  489.            jmp .add_block
  490.  
  491. .fail:
  492.            mov ecx, heap_mutex
  493.            call mutex_unlock
  494.            xor eax, eax
  495.            ret
  496. endp
  497.  
  498. align 4
  499. proc kernel_alloc stdcall, size:dword
  500.            locals
  501.              lin_addr    dd ?
  502.              pages_count dd ?
  503.            endl
  504.  
  505.            push ebx
  506.            push edi
  507.  
  508.            mov eax, [size]
  509.            add eax, 4095
  510.            and eax, not 4095;
  511.            mov [size], eax
  512.            and eax, eax
  513.            jz .err
  514.            mov ebx, eax
  515.            shr ebx, 12
  516.            mov [pages_count], ebx
  517.  
  518.            stdcall alloc_kernel_space, eax
  519.            test eax, eax
  520.            jz .err
  521.            mov [lin_addr], eax
  522.  
  523.            mov ecx, [pages_count]
  524.            mov edx, eax
  525.            mov ebx, ecx
  526.  
  527.            shr ecx, 3
  528.            jz .next
  529.  
  530.            and ebx, not 7
  531.            push ebx
  532.            stdcall alloc_pages, ebx
  533.            pop ecx                   ; yes ecx!!!
  534.            and eax, eax
  535.            jz .err
  536.  
  537.            mov edi, eax
  538.            mov edx, [lin_addr]
  539. @@:
  540.            stdcall map_page,edx,edi,dword PG_SW
  541.            add edx, 0x1000
  542.            add edi, 0x1000
  543.            dec ecx
  544.            jnz @B
  545. .next:
  546.            mov ecx, [pages_count]
  547.            and ecx, 7
  548.            jz .end
  549. @@:
  550.            push ecx
  551.            call alloc_page
  552.            pop ecx
  553.            test eax, eax
  554.            jz .err
  555.  
  556.            stdcall map_page,edx,eax,dword PG_SW
  557.            add edx, 0x1000
  558.            dec ecx
  559.            jnz @B
  560. .end:
  561.            mov eax, [lin_addr]
  562.            pop edi
  563.            pop ebx
  564.            ret
  565. .err:
  566.            xor eax, eax
  567.            pop edi
  568.            pop ebx
  569.            ret
  570. endp
  571.  
  572. align 4
  573. proc kernel_free stdcall, base:dword
  574.            push ebx esi
  575.  
  576.            mov ecx, heap_mutex
  577.            call mutex_lock
  578.  
  579.            mov eax, [base]
  580.            mov esi, [mem_used.fd]
  581. @@:
  582.            cmp esi, mem_used.fd
  583.            je .fail
  584.  
  585.            cmp [esi+block_base], eax
  586.            je .found
  587.            mov esi, [esi+list_fd]
  588.            jmp @b
  589. .found:
  590.            cmp [esi+block_flags], USED_BLOCK
  591.            jne .fail
  592.  
  593.            call mutex_unlock
  594.  
  595.            mov ecx, [esi+block_size];
  596.            shr ecx, 12
  597.            call release_pages   ;eax, ecx
  598.            stdcall free_kernel_space, [base]
  599.            pop esi ebx
  600.            ret
  601. .fail:
  602.            call mutex_unlock
  603.            xor eax, eax
  604.            pop esi ebx
  605.            ret
  606. endp
  607.  
  608. restore block_next
  609. restore block_prev
  610. restore block_list
  611. restore block_base
  612. restore block_size
  613. restore block_flags
  614.  
  615. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  616.  
  617. HEAP_TOP  equ 0x5FC00000
  618.  
  619. align 4
  620. proc init_heap
  621.  
  622.            mov ebx,[current_slot]
  623.            mov eax, [ebx+APPDATA.heap_top]
  624.            test eax, eax
  625.            jz @F
  626.            sub eax,[ebx+APPDATA.heap_base]
  627.            sub eax, 4096
  628.            ret
  629. @@:
  630.            mov esi, [ebx+APPDATA.mem_size]
  631.            add esi, 4095
  632.            and esi, not 4095
  633.            mov [ebx+APPDATA.mem_size], esi
  634.            mov eax, HEAP_TOP
  635.            mov [ebx+APPDATA.heap_base], esi
  636.            mov [ebx+APPDATA.heap_top], eax
  637.  
  638.            sub eax, esi
  639.            shr esi, 10
  640.            mov ecx, eax
  641.            sub eax, 4096
  642.            or ecx, FREE_BLOCK
  643.            mov [page_tabs+esi], ecx
  644.            ret
  645. endp
  646.  
  647. align 4
  648. proc user_alloc stdcall, alloc_size:dword
  649.  
  650.            push ebx
  651.            push esi
  652.            push edi
  653.  
  654.            mov ecx, [alloc_size]
  655.            add ecx, (4095+4096)
  656.            and ecx, not 4095
  657.  
  658.            mov ebx, [current_slot]
  659.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  660.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  661. l_0:
  662.            cmp esi, edi
  663.            jae m_exit
  664.  
  665.            mov ebx, esi
  666.            shr ebx, 12
  667.            mov eax, [page_tabs+ebx*4]
  668.            test al, FREE_BLOCK
  669.            jz test_used
  670.            and eax, 0xFFFFF000
  671.            cmp eax, ecx    ;alloc_size
  672.            jb  m_next
  673.            jz  @f
  674.  
  675.            lea edx, [esi+ecx]
  676.            sub eax, ecx
  677.            or al, FREE_BLOCK
  678.            shr edx, 12
  679.            mov [page_tabs+edx*4], eax
  680. @@:
  681.            or ecx, USED_BLOCK
  682.            mov [page_tabs+ebx*4], ecx
  683.            shr ecx, 12
  684.            inc ebx
  685.            dec ecx
  686.            jz  .no
  687. @@:
  688.            mov dword [page_tabs+ebx*4], 2
  689.            inc ebx
  690.            dec ecx
  691.            jnz @B
  692. .no:
  693.  
  694.            mov     edx, [current_slot]
  695.            mov     ebx, [alloc_size]
  696.            add     ebx, 0xFFF
  697.            and     ebx, not 0xFFF
  698.            add     ebx, [edx+APPDATA.mem_size]
  699.            call    update_mem_size
  700.  
  701.            lea eax, [esi+4096]
  702.  
  703.            pop edi
  704.            pop esi
  705.            pop ebx
  706.            ret
  707. test_used:
  708.            test al, USED_BLOCK
  709.            jz m_exit
  710.  
  711.            and eax, 0xFFFFF000
  712. m_next:
  713.            add esi, eax
  714.            jmp l_0
  715. m_exit:
  716.            xor eax, eax
  717.            pop edi
  718.            pop esi
  719.            pop ebx
  720.            ret
  721. endp
  722.  
  723. align 4
  724. proc user_alloc_at stdcall, address:dword, alloc_size:dword
  725.  
  726.            push ebx
  727.            push esi
  728.            push edi
  729.  
  730.            mov ebx, [current_slot]
  731.            mov edx, [address]
  732.            and edx, not 0xFFF
  733.            mov [address], edx
  734.            sub edx, 0x1000
  735.            jb  .error
  736.            mov esi, [ebx+APPDATA.heap_base]
  737.            mov edi, [ebx+APPDATA.heap_top]
  738.            cmp edx, esi
  739.            jb  .error
  740. .scan:
  741.            cmp esi, edi
  742.            jae .error
  743.            mov ebx, esi
  744.            shr ebx, 12
  745.            mov eax, [page_tabs+ebx*4]
  746.            mov ecx, eax
  747.            and ecx, 0xFFFFF000
  748.            add ecx, esi
  749.            cmp edx, ecx
  750.            jb  .found
  751.            mov esi, ecx
  752.            jmp .scan
  753. .error:
  754.            xor eax, eax
  755.            pop edi
  756.            pop esi
  757.            pop ebx
  758.            ret
  759. .found:
  760.            test al, FREE_BLOCK
  761.            jz  .error
  762.            mov eax, ecx
  763.            sub eax, edx
  764.            sub eax, 0x1000
  765.            cmp eax, [alloc_size]
  766.            jb  .error
  767.  
  768. ; Here we have 1 big free block which includes requested area.
  769. ; In general, 3 other blocks must be created instead:
  770. ; free at [esi, edx);
  771. ; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
  772. ; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
  773. ; First or third block (or both) may be absent.
  774.            mov eax, edx
  775.            sub eax, esi
  776.            jz  .nofirst
  777.            or  al, FREE_BLOCK
  778.            mov [page_tabs+ebx*4], eax
  779. .nofirst:
  780.            mov eax, [alloc_size]
  781.            add eax, 0x1FFF
  782.            and eax, not 0xFFF
  783.            mov ebx, edx
  784.            add edx, eax
  785.            shr ebx, 12
  786.            or  al, USED_BLOCK
  787.            mov [page_tabs+ebx*4], eax
  788.            shr eax, 12
  789.            dec eax
  790.            jz  .second_nofill
  791.            inc ebx
  792. .fill:
  793.            mov dword [page_tabs+ebx*4], 2
  794.            inc ebx
  795.            dec eax
  796.            jnz .fill
  797. .second_nofill:
  798.            sub ecx, edx
  799.            jz  .nothird
  800.            or  cl, FREE_BLOCK
  801.            mov [page_tabs+ebx*4], ecx
  802. .nothird:
  803.  
  804.            mov     edx, [current_slot]
  805.            mov     ebx, [alloc_size]
  806.            add     ebx, 0xFFF
  807.            and     ebx, not 0xFFF
  808.            add     ebx, [edx+APPDATA.mem_size]
  809.            call    update_mem_size
  810.  
  811.            mov eax, [address]
  812.  
  813.            pop edi
  814.            pop esi
  815.            pop ebx
  816.            ret
  817. endp
  818.  
  819. align 4
  820. proc user_free stdcall, base:dword
  821.  
  822.            push esi
  823.  
  824.            mov esi, [base]
  825.            test esi, esi
  826.            jz .exit
  827.  
  828.            push ebx
  829.  
  830.            xor ebx, ebx
  831.            shr esi, 12
  832.            mov eax, [page_tabs+(esi-1)*4]
  833.            test al, USED_BLOCK
  834.            jz .cantfree
  835.            test al, DONT_FREE_BLOCK
  836.            jnz .cantfree
  837.  
  838.            and eax, not 4095
  839.            mov ecx, eax
  840.            or al, FREE_BLOCK
  841.            mov [page_tabs+(esi-1)*4], eax
  842.            sub ecx, 4096
  843.            mov ebx, ecx
  844.            shr ecx, 12
  845.            jz .released
  846. .release:
  847.            xor eax, eax
  848.            xchg eax, [page_tabs+esi*4]
  849.            test al, 1
  850.            jz @F
  851.            test eax, PG_SHARED
  852.            jnz @F
  853.            call free_page
  854.            mov eax, esi
  855.            shl eax, 12
  856.            invlpg [eax]
  857. @@:
  858.            inc esi
  859.            dec ecx
  860.            jnz .release
  861. .released:
  862.            push edi
  863.  
  864.            mov edx, [current_slot]
  865.            mov esi, dword [edx+APPDATA.heap_base]
  866.            mov edi, dword [edx+APPDATA.heap_top]
  867.            sub ebx, [edx+APPDATA.mem_size]
  868.            neg ebx
  869.            call update_mem_size
  870.            call user_normalize
  871.            pop edi
  872.            pop ebx
  873.            pop esi
  874.            ret
  875. .exit:
  876.            xor eax, eax
  877.            inc eax
  878.            pop esi
  879.            ret
  880. .cantfree:
  881.            xor eax, eax
  882.            pop ebx
  883.            pop esi
  884.            ret
  885. endp
  886.  
  887. user_normalize:
  888. ; in: esi=heap_base, edi=heap_top
  889. ; out: eax=0 <=> OK
  890. ; destroys: ebx,edx,esi,edi
  891.            shr esi, 12
  892.            shr edi, 12
  893. @@:
  894.            mov eax, [page_tabs+esi*4]
  895.            test al, USED_BLOCK
  896.            jz .test_free
  897.            shr eax, 12
  898.            add esi, eax
  899.            jmp @B
  900. .test_free:
  901.            test al, FREE_BLOCK
  902.            jz .err
  903.            mov edx, eax
  904.            shr edx, 12
  905.            add edx, esi
  906.            cmp edx, edi
  907.            jae .exit
  908.  
  909.            mov ebx, [page_tabs+edx*4]
  910.            test bl, USED_BLOCK
  911.            jz .next_free
  912.  
  913.            shr ebx, 12
  914.            add edx, ebx
  915.            mov esi, edx
  916.            jmp @B
  917. .next_free:
  918.            test bl, FREE_BLOCK
  919.            jz .err
  920.            and dword [page_tabs+edx*4], 0
  921.            add eax, ebx
  922.            and eax, not 4095
  923.            or eax, FREE_BLOCK
  924.            mov [page_tabs+esi*4], eax
  925.            jmp @B
  926. .exit:
  927.            xor eax, eax
  928.            inc eax
  929.            ret
  930. .err:
  931.            xor eax, eax
  932.            ret
  933.  
  934. user_realloc:
  935. ; in: eax = pointer, ebx = new size
  936. ; out: eax = new pointer or NULL
  937.         test    eax, eax
  938.         jnz     @f
  939. ; realloc(NULL,sz) - same as malloc(sz)
  940.         push    ebx
  941.         call    user_alloc
  942.         ret
  943. @@:
  944.         push    ecx edx
  945.         lea     ecx, [eax - 0x1000]
  946.         shr     ecx, 12
  947.         mov     edx, [page_tabs+ecx*4]
  948.         test    dl, USED_BLOCK
  949.         jnz     @f
  950. ; attempt to realloc invalid pointer
  951. .ret0:
  952.         pop     edx ecx
  953.         xor     eax, eax
  954.         ret
  955. @@:
  956.         test    dl, DONT_FREE_BLOCK
  957.         jnz     .ret0
  958.         add     ebx, 0x1FFF
  959.         shr     edx, 12
  960.         shr     ebx, 12
  961. ; edx = allocated size, ebx = new size
  962.         add     edx, ecx
  963.         add     ebx, ecx
  964.         cmp     edx, ebx
  965.         jb      .realloc_add
  966. ; release part of allocated memory
  967. .loop:
  968.         cmp     edx, ebx
  969.         jz      .release_done
  970.         dec     edx
  971.         xor     eax, eax
  972.         xchg    eax, [page_tabs+edx*4]
  973.         test    al, 1
  974.         jz      .loop
  975.         call    free_page
  976.         mov     eax, edx
  977.         shl     eax, 12
  978.         invlpg  [eax]
  979.         jmp     .loop
  980. .release_done:
  981.         sub     ebx, ecx
  982.         cmp     ebx, 1
  983.         jnz     .nofreeall
  984.         mov     eax, [page_tabs+ecx*4]
  985.         and     eax, not 0xFFF
  986.         mov     edx, [current_slot]
  987.         mov     ebx, [APPDATA.mem_size+edx]
  988.         sub     ebx, eax
  989.         add     ebx, 0x1000
  990.         or      al, FREE_BLOCK
  991.         mov     [page_tabs+ecx*4], eax
  992.         push    esi edi
  993.         mov     esi, [APPDATA.heap_base+edx]
  994.         mov     edi, [APPDATA.heap_top+edx]
  995.         call    update_mem_size
  996.         call    user_normalize
  997.         pop     edi esi
  998.         jmp     .ret0   ; all freed
  999. .nofreeall:
  1000.         sub     edx, ecx
  1001.         shl     ebx, 12
  1002.         or      ebx, USED_BLOCK
  1003.         xchg    [page_tabs+ecx*4], ebx
  1004.         shr     ebx, 12
  1005.         sub     ebx, edx
  1006.         push    ebx ecx edx
  1007.         mov     edx, [current_slot]
  1008.         shl     ebx, 12
  1009.         sub     ebx, [APPDATA.mem_size+edx]
  1010.         neg     ebx
  1011.         call    update_mem_size
  1012.         pop     edx ecx ebx
  1013.         lea     eax, [ecx+1]
  1014.         shl     eax, 12
  1015.         push    eax
  1016.         add     ecx, edx
  1017.         lea     edx, [ecx+ebx]
  1018.         shl     ebx, 12
  1019.         jz      .ret
  1020.         push    esi
  1021.         mov     esi, [current_slot]
  1022.         mov     esi, [APPDATA.heap_top+esi]
  1023.         shr     esi, 12
  1024. @@:
  1025.         cmp     edx, esi
  1026.         jae     .merge_done
  1027.         mov     eax, [page_tabs+edx*4]
  1028.         test    al, USED_BLOCK
  1029.         jnz     .merge_done
  1030.         and     dword [page_tabs+edx*4], 0
  1031.         shr     eax, 12
  1032.         add     edx, eax
  1033.         shl     eax, 12
  1034.         add     ebx, eax
  1035.         jmp     @b
  1036. .merge_done:
  1037.         pop     esi
  1038.         or      ebx, FREE_BLOCK
  1039.         mov     [page_tabs+ecx*4], ebx
  1040. .ret:
  1041.         pop     eax edx ecx
  1042.         ret
  1043. .realloc_add:
  1044. ; get some additional memory
  1045.         mov     eax, [current_slot]
  1046.         mov     eax, [APPDATA.heap_top+eax]
  1047.         shr     eax, 12
  1048.         cmp     edx, eax
  1049.         jae     .cant_inplace
  1050.         mov     eax, [page_tabs+edx*4]
  1051.         test    al, FREE_BLOCK
  1052.         jz      .cant_inplace
  1053.         shr     eax, 12
  1054.         add     eax, edx
  1055.         sub     eax, ebx
  1056.         jb      .cant_inplace
  1057.         jz      @f
  1058.         shl     eax, 12
  1059.         or      al, FREE_BLOCK
  1060.         mov     [page_tabs+ebx*4], eax
  1061. @@:
  1062.         mov     eax, ebx
  1063.         sub     eax, ecx
  1064.         shl     eax, 12
  1065.         or      al, USED_BLOCK
  1066.         mov     [page_tabs+ecx*4], eax
  1067.         lea     eax, [ecx+1]
  1068.         shl     eax, 12
  1069.         push    eax
  1070.         push    edi
  1071.         lea     edi, [page_tabs+edx*4]
  1072.         mov     eax, 2
  1073.         sub     ebx, edx
  1074.         mov     ecx, ebx
  1075.         cld
  1076.         rep     stosd
  1077.         pop     edi
  1078.         mov     edx, [current_slot]
  1079.         shl     ebx, 12
  1080.         add     ebx, [APPDATA.mem_size+edx]
  1081.         call    update_mem_size
  1082.         pop     eax edx ecx
  1083.         ret
  1084. .cant_inplace:
  1085.         push    esi edi
  1086.         mov     eax, [current_slot]
  1087.         mov     esi, [APPDATA.heap_base+eax]
  1088.         mov     edi, [APPDATA.heap_top+eax]
  1089.         shr     esi, 12
  1090.         shr     edi, 12
  1091.         sub     ebx, ecx
  1092. .find_place:
  1093.         cmp     esi, edi
  1094.         jae     .place_not_found
  1095.         mov     eax, [page_tabs+esi*4]
  1096.         test    al, FREE_BLOCK
  1097.         jz      .next_place
  1098.         shr     eax, 12
  1099.         cmp     eax, ebx
  1100.         jae     .place_found
  1101.         add     esi, eax
  1102.         jmp     .find_place
  1103. .next_place:
  1104.         shr     eax, 12
  1105.         add     esi, eax
  1106.         jmp     .find_place
  1107. .place_not_found:
  1108.         pop     edi esi
  1109.         jmp     .ret0
  1110. .place_found:
  1111.         sub     eax, ebx
  1112.         jz      @f
  1113.         push    esi
  1114.         add     esi, ebx
  1115.         shl     eax, 12
  1116.         or      al, FREE_BLOCK
  1117.         mov     [page_tabs+esi*4], eax
  1118.         pop     esi
  1119. @@:
  1120.         mov     eax, ebx
  1121.         shl     eax, 12
  1122.         or      al, USED_BLOCK
  1123.         mov     [page_tabs+esi*4], eax
  1124.         inc     esi
  1125.         mov     eax, esi
  1126.         shl     eax, 12
  1127.         push    eax
  1128.         mov     eax, [page_tabs+ecx*4]
  1129.         and     eax, not 0xFFF
  1130.         or      al, FREE_BLOCK
  1131.         sub     edx, ecx
  1132.         mov     [page_tabs+ecx*4], eax
  1133.         inc     ecx
  1134.         dec     ebx
  1135.         dec     edx
  1136.         jz      .no
  1137. @@:
  1138.         xor     eax, eax
  1139.         xchg    eax, [page_tabs+ecx*4]
  1140.         mov     [page_tabs+esi*4], eax
  1141.         mov     eax, ecx
  1142.         shl     eax, 12
  1143.         invlpg  [eax]
  1144.         inc     esi
  1145.         inc     ecx
  1146.         dec     ebx
  1147.         dec     edx
  1148.         jnz     @b
  1149. .no:
  1150.         push    ebx
  1151.         mov     edx, [current_slot]
  1152.         shl     ebx, 12
  1153.         add     ebx, [APPDATA.mem_size+edx]
  1154.         call    update_mem_size
  1155.         pop     ebx
  1156. @@:
  1157.         mov     dword [page_tabs+esi*4], 2
  1158.         inc     esi
  1159.         dec     ebx
  1160.         jnz     @b
  1161.         pop     eax edi esi edx ecx
  1162.         ret
  1163.  
  1164. if 0
  1165. align 4
  1166. proc alloc_dll
  1167.            pushf
  1168.            cli
  1169.            bsf eax, [dll_map]
  1170.            jnz .find
  1171.            popf
  1172.            xor eax, eax
  1173.            ret
  1174. .find:
  1175.            btr [dll_map], eax
  1176.            popf
  1177.            shl eax, 5
  1178.            add eax, dll_tab
  1179.            ret
  1180. endp
  1181.  
  1182. align 4
  1183. proc alloc_service
  1184.            pushf
  1185.            cli
  1186.            bsf eax, [srv_map]
  1187.            jnz .find
  1188.            popf
  1189.            xor eax, eax
  1190.            ret
  1191. .find:
  1192.            btr [srv_map], eax
  1193.            popf
  1194.            shl eax,0x02
  1195.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1196.            ret
  1197. endp
  1198.  
  1199. end if
  1200.  
  1201.  
  1202. ;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
  1203.  
  1204.  
  1205. ; param
  1206. ;  eax= shm_map object
  1207.  
  1208. align 4
  1209. destroy_smap:
  1210.  
  1211.            pushfd
  1212.            cli
  1213.  
  1214.            push esi
  1215.            push edi
  1216.  
  1217.            mov edi, eax
  1218.            mov esi, [eax+SMAP.parent]
  1219.            test esi, esi
  1220.            jz .done
  1221.  
  1222.            lock dec [esi+SMEM.refcount]
  1223.            jnz .done
  1224.  
  1225.            mov ecx, [esi+SMEM.bk]
  1226.            mov edx, [esi+SMEM.fd]
  1227.  
  1228.            mov [ecx+SMEM.fd], edx
  1229.            mov [edx+SMEM.bk], ecx
  1230.  
  1231.            stdcall kernel_free, [esi+SMEM.base]
  1232.            mov eax, esi
  1233.            call free
  1234. .done:
  1235.            mov eax, edi
  1236.            call destroy_kernel_object
  1237.  
  1238.            pop edi
  1239.            pop esi
  1240.            popfd
  1241.  
  1242.            ret
  1243.  
  1244. E_NOTFOUND      equ  5
  1245. E_ACCESS        equ 10
  1246. E_NOMEM         equ 30
  1247. E_PARAM         equ 33
  1248.  
  1249. SHM_READ        equ 0
  1250. SHM_WRITE       equ 1
  1251.  
  1252. SHM_ACCESS_MASK equ 3
  1253.  
  1254. SHM_OPEN        equ (0 shl 2)
  1255. SHM_OPEN_ALWAYS equ (1 shl 2)
  1256. SHM_CREATE      equ (2 shl 2)
  1257.  
  1258. SHM_OPEN_MASK   equ (3 shl 2)
  1259.  
  1260. align 4
  1261. proc shmem_open stdcall name:dword, size:dword, access:dword
  1262.            locals
  1263.               action         dd ?
  1264.               owner_access   dd ?
  1265.               mapped         dd ?
  1266.            endl
  1267.  
  1268.            push ebx
  1269.            push esi
  1270.            push edi
  1271.  
  1272.            mov [mapped], 0
  1273.            mov [owner_access], 0
  1274.  
  1275.            pushfd                      ;mutex required
  1276.            cli
  1277.  
  1278.            mov eax, [access]
  1279.            and eax, SHM_OPEN_MASK
  1280.            mov [action], eax
  1281.  
  1282.            mov ebx, [name]
  1283.            test ebx, ebx
  1284.            mov edx, E_PARAM
  1285.            jz .fail
  1286.  
  1287.            mov esi, [shmem_list.fd]
  1288. align 4
  1289. @@:
  1290.            cmp esi, shmem_list
  1291.            je .not_found
  1292.  
  1293.            lea edx, [esi+SMEM.name] ; link , base, size
  1294.            stdcall strncmp, edx, ebx, 32
  1295.            test eax, eax
  1296.            je .found
  1297.  
  1298.            mov esi, [esi+SMEM.fd]
  1299.            jmp @B
  1300.  
  1301. .not_found:
  1302.            mov eax, [action]
  1303.  
  1304.            cmp eax, SHM_OPEN
  1305.            mov edx, E_NOTFOUND
  1306.            je .fail
  1307.  
  1308.            cmp eax, SHM_CREATE
  1309.            mov edx, E_PARAM
  1310.            je .create_shm
  1311.  
  1312.            cmp eax, SHM_OPEN_ALWAYS
  1313.            jne .fail
  1314.  
  1315. .create_shm:
  1316.  
  1317.            mov ecx, [size]
  1318.            test ecx, ecx
  1319.            jz .fail
  1320.  
  1321.            add ecx, 4095
  1322.            and ecx, -4096
  1323.            mov [size], ecx
  1324.  
  1325.            mov eax, SMEM.sizeof
  1326.            call malloc
  1327.            test eax, eax
  1328.            mov esi, eax
  1329.            mov edx, E_NOMEM
  1330.            jz .fail
  1331.  
  1332.            stdcall kernel_alloc, [size]
  1333.            test eax, eax
  1334.            mov [mapped], eax
  1335.            mov edx, E_NOMEM
  1336.            jz .cleanup
  1337.  
  1338.            mov ecx, [size]
  1339.            mov edx, [access]
  1340.            and edx, SHM_ACCESS_MASK
  1341.  
  1342.            mov [esi+SMEM.base], eax
  1343.            mov [esi+SMEM.size], ecx
  1344.            mov [esi+SMEM.access], edx
  1345.            mov [esi+SMEM.refcount], 0
  1346.            mov [esi+SMEM.name+28], 0
  1347.  
  1348.            lea eax, [esi+SMEM.name]
  1349.            stdcall strncpy, eax, [name], 31
  1350.  
  1351.            mov eax, [shmem_list.fd]
  1352.            mov [esi+SMEM.bk], shmem_list
  1353.            mov [esi+SMEM.fd], eax
  1354.  
  1355.            mov [eax+SMEM.bk], esi
  1356.            mov [shmem_list.fd], esi
  1357.  
  1358.            mov [action], SHM_OPEN
  1359.            mov [owner_access], SHM_WRITE
  1360.  
  1361. .found:
  1362.            mov eax, [action]
  1363.  
  1364.            cmp eax, SHM_CREATE
  1365.            mov edx, E_ACCESS
  1366.            je .exit
  1367.  
  1368.            cmp eax, SHM_OPEN
  1369.            mov edx, E_PARAM
  1370.            je .create_map
  1371.  
  1372.            cmp eax, SHM_OPEN_ALWAYS
  1373.            jne .fail
  1374.  
  1375. .create_map:
  1376.  
  1377.            mov eax, [access]
  1378.            and eax, SHM_ACCESS_MASK
  1379.            cmp eax, [esi+SMEM.access]
  1380.            mov [access], eax
  1381.            mov edx, E_ACCESS
  1382.            ja .fail
  1383.  
  1384.            mov ebx, [CURRENT_TASK]
  1385.            shl ebx, 5
  1386.            mov ebx, [CURRENT_TASK+ebx+4]
  1387.            mov eax, SMAP.sizeof
  1388.  
  1389.            call create_kernel_object
  1390.            test eax, eax
  1391.            mov edi, eax
  1392.            mov edx, E_NOMEM
  1393.            jz .fail
  1394.  
  1395.            inc [esi+SMEM.refcount]
  1396.  
  1397.            mov [edi+SMAP.magic], 'SMAP'
  1398.            mov [edi+SMAP.destroy], destroy_smap
  1399.            mov [edi+SMAP.parent], esi
  1400.            mov [edi+SMAP.base], 0
  1401.  
  1402.            stdcall user_alloc, [esi+SMEM.size]
  1403.            test eax, eax
  1404.            mov [mapped], eax
  1405.            mov edx, E_NOMEM
  1406.            jz .cleanup2
  1407.  
  1408.            mov [edi+SMAP.base], eax
  1409.  
  1410.            mov ecx, [esi+SMEM.size]
  1411.            mov [size], ecx
  1412.  
  1413.            shr ecx, 12
  1414.            shr eax, 10
  1415.  
  1416.            mov esi, [esi+SMEM.base]
  1417.            shr esi, 10
  1418.            lea edi, [page_tabs+eax]
  1419.            add esi, page_tabs
  1420.  
  1421.            mov edx, [access]
  1422.            or edx, [owner_access]
  1423.            shl edx, 1
  1424.            or edx, PG_USER+PG_SHARED
  1425. @@:
  1426.            lodsd
  1427.            and eax, 0xFFFFF000
  1428.            or eax, edx
  1429.            stosd
  1430.            loop @B
  1431.  
  1432.            xor edx, edx
  1433.  
  1434.            cmp [owner_access], 0
  1435.            jne .fail
  1436. .exit:
  1437.            mov edx, [size]
  1438. .fail:
  1439.            mov eax, [mapped]
  1440.  
  1441.            popfd
  1442.            pop edi
  1443.            pop esi
  1444.            pop ebx
  1445.            ret
  1446. .cleanup:
  1447.            mov [size], edx
  1448.            mov eax, esi
  1449.            call free
  1450.            jmp .exit
  1451.  
  1452. .cleanup2:
  1453.            mov [size], edx
  1454.            mov eax, edi
  1455.            call destroy_smap
  1456.            jmp .exit
  1457. endp
  1458.  
  1459. align 4
  1460. proc shmem_close stdcall, name:dword
  1461.  
  1462.            mov eax, [name]
  1463.            test eax, eax
  1464.            jz .fail
  1465.  
  1466.            push esi
  1467.            push edi
  1468.            pushfd
  1469.            cli
  1470.  
  1471.            mov esi, [current_slot]
  1472.            add esi, APP_OBJ_OFFSET
  1473. .next:
  1474.            mov eax, [esi+APPOBJ.fd]
  1475.            test eax, eax
  1476.            jz @F
  1477.  
  1478.            cmp eax, esi
  1479.            mov esi, eax
  1480.            je @F
  1481.  
  1482.            cmp [eax+SMAP.magic], 'SMAP'
  1483.            jne .next
  1484.  
  1485.            mov edi, [eax+SMAP.parent]
  1486.            test edi, edi
  1487.            jz .next
  1488.  
  1489.            lea edi, [edi+SMEM.name]
  1490.            stdcall strncmp, [name], edi, 32
  1491.            test eax, eax
  1492.            jne .next
  1493.  
  1494.            stdcall user_free, [esi+SMAP.base]
  1495.  
  1496.            mov eax,esi
  1497.            call [esi+APPOBJ.destroy]
  1498. @@:
  1499.            popfd
  1500.            pop edi
  1501.            pop esi
  1502. .fail:
  1503.            ret
  1504. endp
  1505.  
  1506. align 4
  1507. sys_perf:
  1508.            test ecx, ecx
  1509.            jz .fail
  1510.  
  1511.            mov edi, ecx
  1512.            mov esi, mem_hash_cnt
  1513.            mov ecx, 64
  1514.            rep movsd
  1515. .fail:
  1516.            ret
  1517.