Subversion Repositories Kolibri OS

Rev

Rev 9047 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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