Subversion Repositories Kolibri OS

Rev

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

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