Subversion Repositories Kolibri OS

Rev

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