Subversion Repositories Kolibri OS

Rev

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