Subversion Repositories Kolibri OS

Rev

Rev 2154 | Rev 2167 | 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: 2164 $
  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 eax, [esi+block_base]
  548.            mov ecx, [esi+block_size]
  549.            shr ecx, 12
  550.            call release_pages   ;eax, ecx
  551.            stdcall free_kernel_space, [base]
  552.            pop esi ebx
  553.            ret
  554. .fail:
  555.            call mutex_unlock
  556.            xor eax, eax
  557.            pop esi ebx
  558.            ret
  559. endp
  560.  
  561. restore block_next
  562. restore block_prev
  563. restore block_list
  564. restore block_base
  565. restore block_size
  566. restore block_flags
  567.  
  568. ;;;;;;;;;;;;;;      USER     ;;;;;;;;;;;;;;;;;
  569.  
  570. HEAP_TOP  equ 0x5FC00000
  571.  
  572. align 4
  573. proc init_heap
  574.  
  575.            mov ebx,[current_slot]
  576.            mov eax, [ebx+APPDATA.heap_top]
  577.            test eax, eax
  578.            jz @F
  579.            sub eax,[ebx+APPDATA.heap_base]
  580.            sub eax, 4096
  581.            ret
  582. @@:
  583.            mov esi, [ebx+APPDATA.mem_size]
  584.            add esi, 4095
  585.            and esi, not 4095
  586.            mov [ebx+APPDATA.mem_size], esi
  587.            mov eax, HEAP_TOP
  588.            mov [ebx+APPDATA.heap_base], esi
  589.            mov [ebx+APPDATA.heap_top], eax
  590.  
  591.            sub eax, esi
  592.            shr esi, 10
  593.            mov ecx, eax
  594.            sub eax, 4096
  595.            or ecx, FREE_BLOCK
  596.            mov [page_tabs+esi], ecx
  597.            ret
  598. endp
  599.  
  600. align 4
  601. proc user_alloc stdcall, alloc_size:dword
  602.  
  603.            push ebx
  604.            push esi
  605.            push edi
  606.  
  607.            mov ecx, [alloc_size]
  608.            add ecx, (4095+4096)
  609.            and ecx, not 4095
  610.  
  611.            mov ebx, [current_slot]
  612.            mov esi, dword [ebx+APPDATA.heap_base]  ; heap_base
  613.            mov edi, dword [ebx+APPDATA.heap_top]   ; heap_top
  614. l_0:
  615.            cmp esi, edi
  616.            jae m_exit
  617.  
  618.            mov ebx, esi
  619.            shr ebx, 12
  620.            mov eax, [page_tabs+ebx*4]
  621.            test al, FREE_BLOCK
  622.            jz test_used
  623.            and eax, 0xFFFFF000
  624.            cmp eax, ecx    ;alloc_size
  625.            jb  m_next
  626.            jz  @f
  627.  
  628.            lea edx, [esi+ecx]
  629.            sub eax, ecx
  630.            or al, FREE_BLOCK
  631.            shr edx, 12
  632.            mov [page_tabs+edx*4], eax
  633. @@:
  634.            or ecx, USED_BLOCK
  635.            mov [page_tabs+ebx*4], ecx
  636.            shr ecx, 12
  637.            inc ebx
  638.            dec ecx
  639.            jz  .no
  640. @@:
  641.            mov dword [page_tabs+ebx*4], 2
  642.            inc ebx
  643.            dec ecx
  644.            jnz @B
  645. .no:
  646.  
  647.            mov     edx, [current_slot]
  648.            mov     ebx, [alloc_size]
  649.            add     ebx, 0xFFF
  650.            and     ebx, not 0xFFF
  651.            add     ebx, [edx+APPDATA.mem_size]
  652.            call    update_mem_size
  653.  
  654.            lea eax, [esi+4096]
  655.  
  656.            pop edi
  657.            pop esi
  658.            pop ebx
  659.            ret
  660. test_used:
  661.            test al, USED_BLOCK
  662.            jz m_exit
  663.  
  664.            and eax, 0xFFFFF000
  665. m_next:
  666.            add esi, eax
  667.            jmp l_0
  668. m_exit:
  669.            xor eax, eax
  670.            pop edi
  671.            pop esi
  672.            pop ebx
  673.            ret
  674. endp
  675.  
  676. align 4
  677. proc user_alloc_at stdcall, address:dword, alloc_size:dword
  678.  
  679.            push ebx
  680.            push esi
  681.            push edi
  682.  
  683.            mov ebx, [current_slot]
  684.            mov edx, [address]
  685.            and edx, not 0xFFF
  686.            mov [address], edx
  687.            sub edx, 0x1000
  688.            jb  .error
  689.            mov esi, [ebx+APPDATA.heap_base]
  690.            mov edi, [ebx+APPDATA.heap_top]
  691.            cmp edx, esi
  692.            jb  .error
  693. .scan:
  694.            cmp esi, edi
  695.            jae .error
  696.            mov ebx, esi
  697.            shr ebx, 12
  698.            mov eax, [page_tabs+ebx*4]
  699.            mov ecx, eax
  700.            and ecx, 0xFFFFF000
  701.            add ecx, esi
  702.            cmp edx, ecx
  703.            jb  .found
  704.            mov esi, ecx
  705.            jmp .scan
  706. .error:
  707.            xor eax, eax
  708.            pop edi
  709.            pop esi
  710.            pop ebx
  711.            ret
  712. .found:
  713.            test al, FREE_BLOCK
  714.            jz  .error
  715.            mov eax, ecx
  716.            sub eax, edx
  717.            sub eax, 0x1000
  718.            cmp eax, [alloc_size]
  719.            jb  .error
  720.  
  721. ; Here we have 1 big free block which includes requested area.
  722. ; In general, 3 other blocks must be created instead:
  723. ; free at [esi, edx);
  724. ; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
  725. ; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
  726. ; First or third block (or both) may be absent.
  727.            mov eax, edx
  728.            sub eax, esi
  729.            jz  .nofirst
  730.            or  al, FREE_BLOCK
  731.            mov [page_tabs+ebx*4], eax
  732. .nofirst:
  733.            mov eax, [alloc_size]
  734.            add eax, 0x1FFF
  735.            and eax, not 0xFFF
  736.            mov ebx, edx
  737.            add edx, eax
  738.            shr ebx, 12
  739.            or  al, USED_BLOCK
  740.            mov [page_tabs+ebx*4], eax
  741.            shr eax, 12
  742.            dec eax
  743.            jz  .second_nofill
  744.            inc ebx
  745. .fill:
  746.            mov dword [page_tabs+ebx*4], 2
  747.            inc ebx
  748.            dec eax
  749.            jnz .fill
  750. .second_nofill:
  751.            sub ecx, edx
  752.            jz  .nothird
  753.            or  cl, FREE_BLOCK
  754.            mov [page_tabs+ebx*4], ecx
  755. .nothird:
  756.  
  757.            mov     edx, [current_slot]
  758.            mov     ebx, [alloc_size]
  759.            add     ebx, 0xFFF
  760.            and     ebx, not 0xFFF
  761.            add     ebx, [edx+APPDATA.mem_size]
  762.            call    update_mem_size
  763.  
  764.            mov eax, [address]
  765.  
  766.            pop edi
  767.            pop esi
  768.            pop ebx
  769.            ret
  770. endp
  771.  
  772. align 4
  773. proc user_free stdcall, base:dword
  774.  
  775.            push esi
  776.  
  777.            mov esi, [base]
  778.            test esi, esi
  779.            jz .exit
  780.  
  781.            push ebx
  782.  
  783.            xor ebx, ebx
  784.            shr esi, 12
  785.            mov eax, [page_tabs+(esi-1)*4]
  786.            test al, USED_BLOCK
  787.            jz .cantfree
  788.            test al, DONT_FREE_BLOCK
  789.            jnz .cantfree
  790.  
  791.            and eax, not 4095
  792.            mov ecx, eax
  793.            or al, FREE_BLOCK
  794.            mov [page_tabs+(esi-1)*4], eax
  795.            sub ecx, 4096
  796.            mov ebx, ecx
  797.            shr ecx, 12
  798.            jz .released
  799. .release:
  800.            xor eax, eax
  801.            xchg eax, [page_tabs+esi*4]
  802.            test al, 1
  803.            jz @F
  804.            test eax, PG_SHARED
  805.            jnz @F
  806.            call free_page
  807.            mov eax, esi
  808.            shl eax, 12
  809.            invlpg [eax]
  810. @@:
  811.            inc esi
  812.            dec ecx
  813.            jnz .release
  814. .released:
  815.            push edi
  816.  
  817.            mov edx, [current_slot]
  818.            mov esi, dword [edx+APPDATA.heap_base]
  819.            mov edi, dword [edx+APPDATA.heap_top]
  820.            sub ebx, [edx+APPDATA.mem_size]
  821.            neg ebx
  822.            call update_mem_size
  823.            call user_normalize
  824.            pop edi
  825.            pop ebx
  826.            pop esi
  827.            ret
  828. .exit:
  829.            xor eax, eax
  830.            inc eax
  831.            pop esi
  832.            ret
  833. .cantfree:
  834.            xor eax, eax
  835.            pop ebx
  836.            pop esi
  837.            ret
  838. endp
  839.  
  840. user_normalize:
  841. ; in: esi=heap_base, edi=heap_top
  842. ; out: eax=0 <=> OK
  843. ; destroys: ebx,edx,esi,edi
  844.            shr esi, 12
  845.            shr edi, 12
  846. @@:
  847.            mov eax, [page_tabs+esi*4]
  848.            test al, USED_BLOCK
  849.            jz .test_free
  850.            shr eax, 12
  851.            add esi, eax
  852.            jmp @B
  853. .test_free:
  854.            test al, FREE_BLOCK
  855.            jz .err
  856.            mov edx, eax
  857.            shr edx, 12
  858.            add edx, esi
  859.            cmp edx, edi
  860.            jae .exit
  861.  
  862.            mov ebx, [page_tabs+edx*4]
  863.            test bl, USED_BLOCK
  864.            jz .next_free
  865.  
  866.            shr ebx, 12
  867.            add edx, ebx
  868.            mov esi, edx
  869.            jmp @B
  870. .next_free:
  871.            test bl, FREE_BLOCK
  872.            jz .err
  873.            and dword [page_tabs+edx*4], 0
  874.            add eax, ebx
  875.            and eax, not 4095
  876.            or eax, FREE_BLOCK
  877.            mov [page_tabs+esi*4], eax
  878.            jmp @B
  879. .exit:
  880.            xor eax, eax
  881.            inc eax
  882.            ret
  883. .err:
  884.            xor eax, eax
  885.            ret
  886.  
  887. user_realloc:
  888. ; in: eax = pointer, ebx = new size
  889. ; out: eax = new pointer or NULL
  890.         test    eax, eax
  891.         jnz     @f
  892. ; realloc(NULL,sz) - same as malloc(sz)
  893.         push    ebx
  894.         call    user_alloc
  895.         ret
  896. @@:
  897.         push    ecx edx
  898.         lea     ecx, [eax - 0x1000]
  899.         shr     ecx, 12
  900.         mov     edx, [page_tabs+ecx*4]
  901.         test    dl, USED_BLOCK
  902.         jnz     @f
  903. ; attempt to realloc invalid pointer
  904. .ret0:
  905.         pop     edx ecx
  906.         xor     eax, eax
  907.         ret
  908. @@:
  909.         test    dl, DONT_FREE_BLOCK
  910.         jnz     .ret0
  911.         add     ebx, 0x1FFF
  912.         shr     edx, 12
  913.         shr     ebx, 12
  914. ; edx = allocated size, ebx = new size
  915.         add     edx, ecx
  916.         add     ebx, ecx
  917.         cmp     edx, ebx
  918.         jb      .realloc_add
  919. ; release part of allocated memory
  920. .loop:
  921.         cmp     edx, ebx
  922.         jz      .release_done
  923.         dec     edx
  924.         xor     eax, eax
  925.         xchg    eax, [page_tabs+edx*4]
  926.         test    al, 1
  927.         jz      .loop
  928.         call    free_page
  929.         mov     eax, edx
  930.         shl     eax, 12
  931.         invlpg  [eax]
  932.         jmp     .loop
  933. .release_done:
  934.         sub     ebx, ecx
  935.         cmp     ebx, 1
  936.         jnz     .nofreeall
  937.         mov     eax, [page_tabs+ecx*4]
  938.         and     eax, not 0xFFF
  939.         mov     edx, [current_slot]
  940.         mov     ebx, [APPDATA.mem_size+edx]
  941.         sub     ebx, eax
  942.         add     ebx, 0x1000
  943.         or      al, FREE_BLOCK
  944.         mov     [page_tabs+ecx*4], eax
  945.         push    esi edi
  946.         mov     esi, [APPDATA.heap_base+edx]
  947.         mov     edi, [APPDATA.heap_top+edx]
  948.         call    update_mem_size
  949.         call    user_normalize
  950.         pop     edi esi
  951.         jmp     .ret0   ; all freed
  952. .nofreeall:
  953.         sub     edx, ecx
  954.         shl     ebx, 12
  955.         or      ebx, USED_BLOCK
  956.         xchg    [page_tabs+ecx*4], ebx
  957.         shr     ebx, 12
  958.         sub     ebx, edx
  959.         push    ebx ecx edx
  960.         mov     edx, [current_slot]
  961.         shl     ebx, 12
  962.         sub     ebx, [APPDATA.mem_size+edx]
  963.         neg     ebx
  964.         call    update_mem_size
  965.         pop     edx ecx ebx
  966.         lea     eax, [ecx+1]
  967.         shl     eax, 12
  968.         push    eax
  969.         add     ecx, edx
  970.         lea     edx, [ecx+ebx]
  971.         shl     ebx, 12
  972.         jz      .ret
  973.         push    esi
  974.         mov     esi, [current_slot]
  975.         mov     esi, [APPDATA.heap_top+esi]
  976.         shr     esi, 12
  977. @@:
  978.         cmp     edx, esi
  979.         jae     .merge_done
  980.         mov     eax, [page_tabs+edx*4]
  981.         test    al, USED_BLOCK
  982.         jnz     .merge_done
  983.         and     dword [page_tabs+edx*4], 0
  984.         shr     eax, 12
  985.         add     edx, eax
  986.         shl     eax, 12
  987.         add     ebx, eax
  988.         jmp     @b
  989. .merge_done:
  990.         pop     esi
  991.         or      ebx, FREE_BLOCK
  992.         mov     [page_tabs+ecx*4], ebx
  993. .ret:
  994.         pop     eax edx ecx
  995.         ret
  996. .realloc_add:
  997. ; get some additional memory
  998.         mov     eax, [current_slot]
  999.         mov     eax, [APPDATA.heap_top+eax]
  1000.         shr     eax, 12
  1001.         cmp     edx, eax
  1002.         jae     .cant_inplace
  1003.         mov     eax, [page_tabs+edx*4]
  1004.         test    al, FREE_BLOCK
  1005.         jz      .cant_inplace
  1006.         shr     eax, 12
  1007.         add     eax, edx
  1008.         sub     eax, ebx
  1009.         jb      .cant_inplace
  1010.         jz      @f
  1011.         shl     eax, 12
  1012.         or      al, FREE_BLOCK
  1013.         mov     [page_tabs+ebx*4], eax
  1014. @@:
  1015.         mov     eax, ebx
  1016.         sub     eax, ecx
  1017.         shl     eax, 12
  1018.         or      al, USED_BLOCK
  1019.         mov     [page_tabs+ecx*4], eax
  1020.         lea     eax, [ecx+1]
  1021.         shl     eax, 12
  1022.         push    eax
  1023.         push    edi
  1024.         lea     edi, [page_tabs+edx*4]
  1025.         mov     eax, 2
  1026.         sub     ebx, edx
  1027.         mov     ecx, ebx
  1028.         cld
  1029.         rep     stosd
  1030.         pop     edi
  1031.         mov     edx, [current_slot]
  1032.         shl     ebx, 12
  1033.         add     ebx, [APPDATA.mem_size+edx]
  1034.         call    update_mem_size
  1035.         pop     eax edx ecx
  1036.         ret
  1037. .cant_inplace:
  1038.         push    esi edi
  1039.         mov     eax, [current_slot]
  1040.         mov     esi, [APPDATA.heap_base+eax]
  1041.         mov     edi, [APPDATA.heap_top+eax]
  1042.         shr     esi, 12
  1043.         shr     edi, 12
  1044.         sub     ebx, ecx
  1045. .find_place:
  1046.         cmp     esi, edi
  1047.         jae     .place_not_found
  1048.         mov     eax, [page_tabs+esi*4]
  1049.         test    al, FREE_BLOCK
  1050.         jz      .next_place
  1051.         shr     eax, 12
  1052.         cmp     eax, ebx
  1053.         jae     .place_found
  1054.         add     esi, eax
  1055.         jmp     .find_place
  1056. .next_place:
  1057.         shr     eax, 12
  1058.         add     esi, eax
  1059.         jmp     .find_place
  1060. .place_not_found:
  1061.         pop     edi esi
  1062.         jmp     .ret0
  1063. .place_found:
  1064.         sub     eax, ebx
  1065.         jz      @f
  1066.         push    esi
  1067.         add     esi, ebx
  1068.         shl     eax, 12
  1069.         or      al, FREE_BLOCK
  1070.         mov     [page_tabs+esi*4], eax
  1071.         pop     esi
  1072. @@:
  1073.         mov     eax, ebx
  1074.         shl     eax, 12
  1075.         or      al, USED_BLOCK
  1076.         mov     [page_tabs+esi*4], eax
  1077.         inc     esi
  1078.         mov     eax, esi
  1079.         shl     eax, 12
  1080.         push    eax
  1081.         mov     eax, [page_tabs+ecx*4]
  1082.         and     eax, not 0xFFF
  1083.         or      al, FREE_BLOCK
  1084.         sub     edx, ecx
  1085.         mov     [page_tabs+ecx*4], eax
  1086.         inc     ecx
  1087.         dec     ebx
  1088.         dec     edx
  1089.         jz      .no
  1090. @@:
  1091.         xor     eax, eax
  1092.         xchg    eax, [page_tabs+ecx*4]
  1093.         mov     [page_tabs+esi*4], eax
  1094.         mov     eax, ecx
  1095.         shl     eax, 12
  1096.         invlpg  [eax]
  1097.         inc     esi
  1098.         inc     ecx
  1099.         dec     ebx
  1100.         dec     edx
  1101.         jnz     @b
  1102. .no:
  1103.         push    ebx
  1104.         mov     edx, [current_slot]
  1105.         shl     ebx, 12
  1106.         add     ebx, [APPDATA.mem_size+edx]
  1107.         call    update_mem_size
  1108.         pop     ebx
  1109. @@:
  1110.         mov     dword [page_tabs+esi*4], 2
  1111.         inc     esi
  1112.         dec     ebx
  1113.         jnz     @b
  1114.         pop     eax edi esi edx ecx
  1115.         ret
  1116.  
  1117. if 0
  1118. align 4
  1119. proc alloc_dll
  1120.            pushf
  1121.            cli
  1122.            bsf eax, [dll_map]
  1123.            jnz .find
  1124.            popf
  1125.            xor eax, eax
  1126.            ret
  1127. .find:
  1128.            btr [dll_map], eax
  1129.            popf
  1130.            shl eax, 5
  1131.            add eax, dll_tab
  1132.            ret
  1133. endp
  1134.  
  1135. align 4
  1136. proc alloc_service
  1137.            pushf
  1138.            cli
  1139.            bsf eax, [srv_map]
  1140.            jnz .find
  1141.            popf
  1142.            xor eax, eax
  1143.            ret
  1144. .find:
  1145.            btr [srv_map], eax
  1146.            popf
  1147.            shl eax,0x02
  1148.            lea eax,[srv_tab+eax+eax*8]   ;srv_tab+eax*36
  1149.            ret
  1150. endp
  1151.  
  1152. end if
  1153.  
  1154.  
  1155. ;;;;;;;;;;;;;;      SHARED      ;;;;;;;;;;;;;;;;;
  1156.  
  1157.  
  1158. ; param
  1159. ;  eax= shm_map object
  1160.  
  1161. align 4
  1162. destroy_smap:
  1163.  
  1164.            pushfd
  1165.            cli
  1166.  
  1167.            push esi
  1168.            push edi
  1169.  
  1170.            mov edi, eax
  1171.            mov esi, [eax+SMAP.parent]
  1172.            test esi, esi
  1173.            jz .done
  1174.  
  1175.            lock dec [esi+SMEM.refcount]
  1176.            jnz .done
  1177.  
  1178.            mov ecx, [esi+SMEM.bk]
  1179.            mov edx, [esi+SMEM.fd]
  1180.  
  1181.            mov [ecx+SMEM.fd], edx
  1182.            mov [edx+SMEM.bk], ecx
  1183.  
  1184.            stdcall kernel_free, [esi+SMEM.base]
  1185.            mov eax, esi
  1186.            call free
  1187. .done:
  1188.            mov eax, edi
  1189.            call destroy_kernel_object
  1190.  
  1191.            pop edi
  1192.            pop esi
  1193.            popfd
  1194.  
  1195.            ret
  1196.  
  1197. E_NOTFOUND      equ  5
  1198. E_ACCESS        equ 10
  1199. E_NOMEM         equ 30
  1200. E_PARAM         equ 33
  1201.  
  1202. SHM_READ        equ 0
  1203. SHM_WRITE       equ 1
  1204.  
  1205. SHM_ACCESS_MASK equ 3
  1206.  
  1207. SHM_OPEN        equ (0 shl 2)
  1208. SHM_OPEN_ALWAYS equ (1 shl 2)
  1209. SHM_CREATE      equ (2 shl 2)
  1210.  
  1211. SHM_OPEN_MASK   equ (3 shl 2)
  1212.  
  1213. align 4
  1214. proc shmem_open stdcall name:dword, size:dword, access:dword
  1215.            locals
  1216.               action         dd ?
  1217.               owner_access   dd ?
  1218.               mapped         dd ?
  1219.            endl
  1220.  
  1221.            push ebx
  1222.            push esi
  1223.            push edi
  1224.  
  1225.            mov [mapped], 0
  1226.            mov [owner_access], 0
  1227.  
  1228.            pushfd                      ;mutex required
  1229.            cli
  1230.  
  1231.            mov eax, [access]
  1232.            and eax, SHM_OPEN_MASK
  1233.            mov [action], eax
  1234.  
  1235.            mov ebx, [name]
  1236.            test ebx, ebx
  1237.            mov edx, E_PARAM
  1238.            jz .fail
  1239.  
  1240.            mov esi, [shmem_list.fd]
  1241. align 4
  1242. @@:
  1243.            cmp esi, shmem_list
  1244.            je .not_found
  1245.  
  1246.            lea edx, [esi+SMEM.name] ; link , base, size
  1247.            stdcall strncmp, edx, ebx, 32
  1248.            test eax, eax
  1249.            je .found
  1250.  
  1251.            mov esi, [esi+SMEM.fd]
  1252.            jmp @B
  1253.  
  1254. .not_found:
  1255.            mov eax, [action]
  1256.  
  1257.            cmp eax, SHM_OPEN
  1258.            mov edx, E_NOTFOUND
  1259.            je .fail
  1260.  
  1261.            cmp eax, SHM_CREATE
  1262.            mov edx, E_PARAM
  1263.            je .create_shm
  1264.  
  1265.            cmp eax, SHM_OPEN_ALWAYS
  1266.            jne .fail
  1267.  
  1268. .create_shm:
  1269.  
  1270.            mov ecx, [size]
  1271.            test ecx, ecx
  1272.            jz .fail
  1273.  
  1274.            add ecx, 4095
  1275.            and ecx, -4096
  1276.            mov [size], ecx
  1277.  
  1278.            mov eax, SMEM.sizeof
  1279.            call malloc
  1280.            test eax, eax
  1281.            mov esi, eax
  1282.            mov edx, E_NOMEM
  1283.            jz .fail
  1284.  
  1285.            stdcall kernel_alloc, [size]
  1286.            test eax, eax
  1287.            mov [mapped], eax
  1288.            mov edx, E_NOMEM
  1289.            jz .cleanup
  1290.  
  1291.            mov ecx, [size]
  1292.            mov edx, [access]
  1293.            and edx, SHM_ACCESS_MASK
  1294.  
  1295.            mov [esi+SMEM.base], eax
  1296.            mov [esi+SMEM.size], ecx
  1297.            mov [esi+SMEM.access], edx
  1298.            mov [esi+SMEM.refcount], 0
  1299.            mov [esi+SMEM.name+28], 0
  1300.  
  1301.            lea eax, [esi+SMEM.name]
  1302.            stdcall strncpy, eax, [name], 31
  1303.  
  1304.            mov eax, [shmem_list.fd]
  1305.            mov [esi+SMEM.bk], shmem_list
  1306.            mov [esi+SMEM.fd], eax
  1307.  
  1308.            mov [eax+SMEM.bk], esi
  1309.            mov [shmem_list.fd], esi
  1310.  
  1311.            mov [action], SHM_OPEN
  1312.            mov [owner_access], SHM_WRITE
  1313.  
  1314. .found:
  1315.            mov eax, [action]
  1316.  
  1317.            cmp eax, SHM_CREATE
  1318.            mov edx, E_ACCESS
  1319.            je .exit
  1320.  
  1321.            cmp eax, SHM_OPEN
  1322.            mov edx, E_PARAM
  1323.            je .create_map
  1324.  
  1325.            cmp eax, SHM_OPEN_ALWAYS
  1326.            jne .fail
  1327.  
  1328. .create_map:
  1329.  
  1330.            mov eax, [access]
  1331.            and eax, SHM_ACCESS_MASK
  1332.            cmp eax, [esi+SMEM.access]
  1333.            mov [access], eax
  1334.            mov edx, E_ACCESS
  1335.            ja .fail
  1336.  
  1337.            mov ebx, [CURRENT_TASK]
  1338.            shl ebx, 5
  1339.            mov ebx, [CURRENT_TASK+ebx+4]
  1340.            mov eax, SMAP.sizeof
  1341.  
  1342.            call create_kernel_object
  1343.            test eax, eax
  1344.            mov edi, eax
  1345.            mov edx, E_NOMEM
  1346.            jz .fail
  1347.  
  1348.            inc [esi+SMEM.refcount]
  1349.  
  1350.            mov [edi+SMAP.magic], 'SMAP'
  1351.            mov [edi+SMAP.destroy], destroy_smap
  1352.            mov [edi+SMAP.parent], esi
  1353.            mov [edi+SMAP.base], 0
  1354.  
  1355.            stdcall user_alloc, [esi+SMEM.size]
  1356.            test eax, eax
  1357.            mov [mapped], eax
  1358.            mov edx, E_NOMEM
  1359.            jz .cleanup2
  1360.  
  1361.            mov [edi+SMAP.base], eax
  1362.  
  1363.            mov ecx, [esi+SMEM.size]
  1364.            mov [size], ecx
  1365.  
  1366.            shr ecx, 12
  1367.            shr eax, 10
  1368.  
  1369.            mov esi, [esi+SMEM.base]
  1370.            shr esi, 10
  1371.            lea edi, [page_tabs+eax]
  1372.            add esi, page_tabs
  1373.  
  1374.            mov edx, [access]
  1375.            or edx, [owner_access]
  1376.            shl edx, 1
  1377.            or edx, PG_USER+PG_SHARED
  1378. @@:
  1379.            lodsd
  1380.            and eax, 0xFFFFF000
  1381.            or eax, edx
  1382.            stosd
  1383.            loop @B
  1384.  
  1385.            xor edx, edx
  1386.  
  1387.            cmp [owner_access], 0
  1388.            jne .fail
  1389. .exit:
  1390.            mov edx, [size]
  1391. .fail:
  1392.            mov eax, [mapped]
  1393.  
  1394.            popfd
  1395.            pop edi
  1396.            pop esi
  1397.            pop ebx
  1398.            ret
  1399. .cleanup:
  1400.            mov [size], edx
  1401.            mov eax, esi
  1402.            call free
  1403.            jmp .exit
  1404.  
  1405. .cleanup2:
  1406.            mov [size], edx
  1407.            mov eax, edi
  1408.            call destroy_smap
  1409.            jmp .exit
  1410. endp
  1411.  
  1412. align 4
  1413. proc shmem_close stdcall, name:dword
  1414.  
  1415.            mov eax, [name]
  1416.            test eax, eax
  1417.            jz .fail
  1418.  
  1419.            push esi
  1420.            push edi
  1421.            pushfd
  1422.            cli
  1423.  
  1424.            mov esi, [current_slot]
  1425.            add esi, APP_OBJ_OFFSET
  1426. .next:
  1427.            mov eax, [esi+APPOBJ.fd]
  1428.            test eax, eax
  1429.            jz @F
  1430.  
  1431.            cmp eax, esi
  1432.            mov esi, eax
  1433.            je @F
  1434.  
  1435.            cmp [eax+SMAP.magic], 'SMAP'
  1436.            jne .next
  1437.  
  1438.            mov edi, [eax+SMAP.parent]
  1439.            test edi, edi
  1440.            jz .next
  1441.  
  1442.            lea edi, [edi+SMEM.name]
  1443.            stdcall strncmp, [name], edi, 32
  1444.            test eax, eax
  1445.            jne .next
  1446.  
  1447.            stdcall user_free, [esi+SMAP.base]
  1448.  
  1449.            mov eax,esi
  1450.            call [esi+APPOBJ.destroy]
  1451. @@:
  1452.            popfd
  1453.            pop edi
  1454.            pop esi
  1455. .fail:
  1456.            ret
  1457. endp
  1458.