Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. $Revision: 6339 $
  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. FREE_BLOCK     equ  4
  22. USED_BLOCK     equ  8
  23. DONT_FREE_BLOCK equ  10h
  24.  
  25.  
  26. block_next   equ MEM_BLOCK.next_block
  27. block_prev   equ MEM_BLOCK.prev_block
  28. list_fd     equ MEM_BLOCK.list.next
  29. list_bk     equ MEM_BLOCK.list.prev
  30. block_base   equ MEM_BLOCK.base
  31. block_size   equ MEM_BLOCK.size
  32. block_flags equ MEM_BLOCK.flags
  33.  
  34. macro calc_index op
  35. {          shr op, 12
  36.         dec     op
  37.         cmp     op, 63
  38.         jna     @f
  39.         mov     op, 63
  40. @@:
  41. }
  42.  
  43. align 4
  44. md:
  45. .add_to_used:
  46.         mov     eax, [esi+block_base]
  47.         mov     ebx, [esi+block_base]
  48.         shr     ebx, 6
  49.         add     eax, ebx
  50.         shr     ebx, 6
  51.         add     eax, ebx
  52.         shr     eax, 12
  53.         and     eax, 63
  54.         inc     [mem_hash_cnt+eax*4]
  55.  
  56.         lea     ecx, [mem_used_list+eax*8]
  57.         list_add esi, ecx
  58.         mov     [esi+block_flags], USED_BLOCK
  59.         mov     eax, [esi+block_size]
  60.         sub     [heap_free], eax
  61.         ret
  62. align 4
  63. .find_used:
  64.         mov     ecx, eax
  65.         mov     ebx, eax
  66.         shr     ebx, 6
  67.         add     ecx, ebx
  68.         shr     ebx, 6
  69.         add     ecx, ebx
  70.         shr     ecx, 12
  71.         and     ecx, 63
  72.  
  73.         lea     ebx, [mem_used_list+ecx*8]
  74.         mov     esi, ebx
  75. .next:
  76.         mov     esi, [esi+list_fd]
  77.         cmp     esi, ebx
  78.         je      .fail
  79.  
  80.         cmp     eax, [esi+block_base]
  81.         jne     .next
  82.  
  83.         ret
  84. .fail:
  85.         xor     esi, esi
  86.         ret
  87.  
  88. align 4
  89. .del_from_used:
  90.         call    .find_used
  91.         test    esi, esi
  92.         jz      .done
  93.  
  94.         cmp     [esi+block_flags], USED_BLOCK
  95.         jne     .fatal
  96.  
  97.         dec     [mem_hash_cnt+ecx*4]
  98.         list_del esi
  99. .done:
  100.         ret
  101. .fatal:                            ;FIXME panic here
  102.         xor     esi, esi
  103.         ret
  104.  
  105. ;Initial heap state
  106. ;
  107. ;+heap_size               terminator        USED_BLOCK
  108. ;+4096*MEM_BLOCK.sizeof   free space        FREE_BLOCK
  109. ;HEAP_BASE                heap_descriptors  USED_BLOCK
  110. ;
  111.  
  112. align 4
  113. proc init_kernel_heap
  114.  
  115.         mov     ecx, 64
  116.         mov     edi, mem_block_list
  117. @@:
  118.         mov     eax, edi
  119.         stosd
  120.         stosd
  121.         loop    @B
  122.  
  123.         mov     ecx, 64
  124.         mov     edi, mem_used_list
  125. @@:
  126.         mov     eax, edi
  127.         stosd
  128.         stosd
  129.         loop    @B
  130.  
  131.         stdcall alloc_pages, dword 32
  132.  
  133.         or      eax, PG_SWR
  134.         mov     ebx, HEAP_BASE
  135.         mov     ecx, 32
  136.         call    commit_pages
  137.  
  138.         mov     edi, HEAP_BASE                     ;descriptors
  139.         mov     ebx, HEAP_BASE+sizeof.MEM_BLOCK      ;free space
  140.         mov     ecx, HEAP_BASE+sizeof.MEM_BLOCK*2    ;terminator
  141.  
  142.         xor     eax, eax
  143.         mov     [edi+block_next], ebx
  144.         mov     [edi+block_prev], eax
  145.         mov     [edi+list_fd], eax
  146.         mov     [edi+list_bk], eax
  147.         mov     [edi+block_base], HEAP_BASE
  148.         mov     [edi+block_size], 4096*sizeof.MEM_BLOCK
  149.         mov     [edi+block_flags], USED_BLOCK
  150.  
  151.         mov     [ecx+block_next], eax
  152.         mov     [ecx+block_prev], ebx
  153.         mov     [ecx+list_fd], eax
  154.         mov     [ecx+list_bk], eax
  155.         mov     [ecx+block_base], eax
  156.         mov     [ecx+block_size], eax
  157.         mov     [ecx+block_flags], USED_BLOCK
  158.  
  159.         mov     [ebx+block_next], ecx
  160.         mov     [ebx+block_prev], edi
  161.         mov     [ebx+block_base], HEAP_BASE+4096*sizeof.MEM_BLOCK
  162.  
  163.         mov     ecx, [pg_data.kernel_pages]
  164.         shl     ecx, 12
  165.         sub     ecx, HEAP_BASE-OS_BASE+4096*sizeof.MEM_BLOCK
  166.         mov     [heap_size], ecx
  167.         mov     [heap_free], ecx
  168.         mov     [ebx+block_size], ecx
  169.         mov     [ebx+block_flags], FREE_BLOCK
  170.  
  171.         mov     [mem_block_mask], eax
  172.         mov     [mem_block_mask+4], 0x80000000
  173.  
  174.         mov     ecx, mem_block_list+63*8
  175.         list_add ebx, ecx
  176.  
  177.         mov     ecx, 4096-3-1
  178.         mov     eax, HEAP_BASE+sizeof.MEM_BLOCK*4
  179.  
  180.         mov     [next_memblock], HEAP_BASE+sizeof.MEM_BLOCK *3
  181. @@:
  182.         mov     [eax-sizeof.MEM_BLOCK], eax
  183.         add     eax, sizeof.MEM_BLOCK
  184.         loop    @B
  185.  
  186.         mov     [eax-sizeof.MEM_BLOCK], dword 0
  187.  
  188.         mov     ecx, heap_mutex
  189.         call    mutex_init
  190.         mov     [heap_blocks], 4094
  191.         mov     [free_blocks], 4093
  192.         ret
  193. endp
  194.  
  195. ; param
  196. ;  eax= required size
  197. ;
  198. ; retval
  199. ;  edi= memory block descriptor
  200. ;  ebx= descriptor index
  201.  
  202. align 4
  203. get_small_block:
  204.         mov     ecx, eax
  205.         shr     ecx, 12
  206.         dec     ecx
  207.         cmp     ecx, 63
  208.         jle     .get_index
  209.         mov     ecx, 63
  210. .get_index:
  211.         lea     esi, [mem_block_mask]
  212.         xor     ebx, ebx
  213.         or      edx, -1
  214.  
  215.         cmp     ecx, 32
  216.         jb      .bit_test
  217.  
  218.         sub     ecx, 32
  219.         add     ebx, 32
  220.         add     esi, 4
  221. .bit_test:
  222.         shl     edx, cl
  223.         and     edx, [esi]
  224. .find:
  225.         bsf     edi, edx
  226.         jz      .high_mask
  227.         add     ebx, edi
  228.         lea     ecx, [mem_block_list+ebx*8]
  229.         mov     edi, ecx
  230. .next:
  231.         mov     edi, [edi+list_fd]
  232.         cmp     edi, ecx
  233.         je      .err
  234.         cmp     eax, [edi+block_size]
  235.         ja      .next
  236.         ret
  237. .err:
  238.         xor     edi, edi
  239.         ret
  240.  
  241. .high_mask:
  242.         add     esi, 4
  243.         cmp     esi, mem_block_mask+8
  244.         jae     .err
  245.         add     ebx, 32
  246.         mov     edx, [esi]
  247.         jmp     .find
  248.  
  249.  
  250. align 4
  251. free_mem_block:
  252.         mov     ebx, [next_memblock]
  253.         mov     [eax], ebx
  254.         mov     [next_memblock], eax
  255.         xor     ebx, ebx
  256.  
  257.         mov     dword [eax+4], ebx
  258.         mov     dword [eax+8], ebx
  259.         mov     dword [eax+12], ebx
  260.         mov     dword [eax+16], ebx
  261. ;           mov dword [eax+20], 0     ;don't clear block size
  262.         mov     dword [eax+24], ebx
  263.         mov     dword [eax+28], ebx
  264.         inc     [free_blocks]
  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+block_flags], FREE_BLOCK
  292.         jne     .error_unlock
  293.  
  294.         mov     [block_ind], ebx  ;index of allocated block
  295.  
  296.         mov     eax, [edi+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+block_next], edi
  309.         mov     eax, [edi+block_prev]
  310.         mov     [esi+block_prev], eax
  311.         mov     [edi+block_prev], esi
  312.         mov     [esi+list_fd], 0
  313.         mov     [esi+list_bk], 0
  314.         mov     [eax+block_next], esi
  315.  
  316.         mov     ebx, [edi+block_base]
  317.         mov     [esi+block_base], ebx
  318.         mov     edx, [size]
  319.         mov     [esi+block_size], edx
  320.         add     [edi+block_base], edx
  321.         sub     [edi+block_size], edx
  322.  
  323.         mov     eax, [edi+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+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+block_size]
  382.         add     [heap_free], eax
  383.  
  384.         mov     edi, [esi+block_next]
  385.         cmp     [edi+block_flags], FREE_BLOCK
  386.         jne     .prev
  387.  
  388.         list_del edi
  389.  
  390.         mov     edx, [edi+block_next]
  391.         mov     [esi+block_next], edx
  392.         mov     [edx+block_prev], esi
  393.         mov     ecx, [edi+block_size]
  394.         add     [esi+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+block_prev]
  407.         cmp     [edi+block_flags], FREE_BLOCK
  408.         jne     .insert
  409.  
  410.         mov     edx, [esi+block_next]
  411.         mov     [edi+block_next], edx
  412.         mov     [edx+block_prev], edi
  413.  
  414.         mov     eax, esi
  415.         call    free_mem_block
  416.  
  417.         mov     ecx, [edi+block_size]
  418.         mov     eax, [esi+block_size]
  419.         add     eax, ecx
  420.         mov     [edi+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+block_flags], FREE_BLOCK
  447.         mov     eax, [esi+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+block_flags], USED_BLOCK
  536.         jne     .fail
  537.  
  538.         spin_unlock_irqrestore heap_mutex
  539.  
  540.         mov     eax, [esi+block_base]
  541.         mov     ecx, [esi+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. restore block_next
  555. restore block_prev
  556. restore block_list
  557. restore block_base
  558. restore block_size
  559. restore block_flags
  560.  
  561. ;;;;;;;;;;;;;;      USER HEAP     ;;;;;;;;;;;;;;;;;
  562.  
  563. HEAP_TOP equ 0x80000000
  564.  
  565. align 4
  566. proc init_heap
  567.  
  568.         mov     ebx, [current_process]
  569.         mov     eax, [ebx+PROC.heap_top]
  570.         test    eax, eax
  571.         jz      @F
  572.         sub     eax, [ebx+PROC.heap_base]
  573.         sub     eax, PAGE_SIZE
  574.         ret
  575. @@:
  576.         lea     ecx, [ebx+PROC.heap_lock]
  577.         call    mutex_init
  578.  
  579.         mov     esi, [ebx+PROC.mem_used]
  580.         add     esi, 4095
  581.         and     esi, not 4095
  582.         mov     [ebx+PROC.mem_used], esi
  583.         mov     eax, HEAP_TOP
  584.         mov     [ebx+PROC.heap_base], esi
  585.         mov     [ebx+PROC.heap_top], eax
  586.  
  587.         sub     eax, esi
  588.         shr     esi, 9
  589.         mov     ecx, eax
  590.         sub     eax, PAGE_SIZE
  591.         or      ecx, FREE_BLOCK
  592.         mov     [page_tabs+esi], ecx
  593.         ret
  594. endp
  595.  
  596. align 4
  597. proc user_alloc stdcall, alloc_size:dword
  598.  
  599.         push    ebx
  600.         push    esi
  601.         push    edi
  602.  
  603.         mov     ebx, [current_process]
  604.         lea     ecx, [ebx+PROC.heap_lock]
  605.         call    mutex_lock
  606.  
  607.         mov     ecx, [alloc_size]
  608.         add     ecx, (4095+PAGE_SIZE)
  609.         and     ecx, not 4095
  610.  
  611.         mov     esi, dword [ebx+PROC.heap_base] ; heap_base
  612.         mov     edi, dword [ebx+PROC.heap_top]  ; heap_top
  613. .scan:
  614.         cmp     esi, edi
  615.         jae     .m_exit
  616.  
  617.         mov     ebx, esi
  618.         shr     ebx, 12
  619.         mov     eax, [page_tabs+ebx*8]
  620.         test    al, FREE_BLOCK
  621.         jz      .test_used
  622.         and     eax, 0xFFFFF000
  623.         cmp     eax, ecx   ;alloc_size
  624.         jb      .m_next
  625.         jz      @f
  626.  
  627.         lea     edx, [esi+ecx]
  628.         sub     eax, ecx
  629.         or      al, FREE_BLOCK
  630.         shr     edx, 12
  631.         mov     [page_tabs+edx*8], eax
  632. @@:
  633.         or      ecx, USED_BLOCK
  634.         mov     [page_tabs+ebx*8], ecx
  635.         shr     ecx, 12
  636.         inc     ebx
  637.         dec     ecx
  638.         jz      .no
  639. @@:
  640.         mov     dword [page_tabs+ebx*8], 2
  641.         inc     ebx
  642.         dec     ecx
  643.         jnz     @B
  644. .no:
  645.  
  646.         mov     edx, [current_process]
  647.         mov     ebx, [alloc_size]
  648.         add     ebx, 0xFFF
  649.         and     ebx, not 0xFFF
  650.         add     [edx+PROC.mem_used], ebx
  651.  
  652.         lea     ecx, [edx+PROC.heap_lock]
  653.         call    mutex_unlock
  654.  
  655.         lea     eax, [esi+4096]
  656.  
  657.         pop     edi
  658.         pop     esi
  659.         pop     ebx
  660.         ret
  661. .test_used:
  662.         test    al, USED_BLOCK
  663.         jz      .m_exit
  664.  
  665.         and     eax, 0xFFFFF000
  666. .m_next:
  667.         add     esi, eax
  668.         jmp     .scan
  669. .m_exit:
  670.         mov     ecx, [current_process]
  671.         lea     ecx, [ecx+PROC.heap_lock]
  672.         call    mutex_unlock
  673.  
  674.         xor     eax, eax
  675.         pop     edi
  676.         pop     esi
  677.         pop     ebx
  678.         ret
  679. endp
  680.  
  681. align 4
  682. proc user_alloc_at stdcall, address:dword, alloc_size:dword
  683.  
  684.         push    ebx
  685.         push    esi
  686.         push    edi
  687.  
  688.         mov     ebx, [current_process]
  689.         lea     ecx, [ebx+PROC.heap_lock]
  690.         call    mutex_lock
  691.  
  692.         mov     edx, [address]
  693.         and     edx, not 0xFFF
  694.         mov     [address], edx
  695.         sub     edx, 0x1000
  696.         jb      .error
  697.         mov     esi, [ebx+PROC.heap_base]
  698.         mov     edi, [ebx+PROC.heap_top]
  699.         cmp     edx, esi
  700.         jb      .error
  701. .scan:
  702.         cmp     esi, edi
  703.         jae     .error
  704.         mov     ebx, esi
  705.         shr     ebx, 12
  706.         mov     eax, [page_tabs+ebx*8]
  707.         mov     ecx, eax
  708.         and     ecx, 0xFFFFF000
  709.         add     ecx, esi
  710.         cmp     edx, ecx
  711.         jb      .found
  712.         mov     esi, ecx
  713.         jmp     .scan
  714. .error:
  715.         mov     ecx, [current_process]
  716.         lea     ecx, [ecx+PROC.heap_lock]
  717.         call    mutex_unlock
  718.  
  719.         xor     eax, eax
  720.         pop     edi
  721.         pop     esi
  722.         pop     ebx
  723.         ret
  724. .found:
  725.         test    al, FREE_BLOCK
  726.         jz      .error
  727.         mov     eax, ecx
  728.         sub     eax, edx
  729.         sub     eax, 0x1000
  730.         cmp     eax, [alloc_size]
  731.         jb      .error
  732.  
  733. ; Here we have 1 big free block which includes requested area.
  734. ; In general, 3 other blocks must be created instead:
  735. ; free at [esi, edx);
  736. ; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
  737. ; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
  738. ; First or third block (or both) may be absent.
  739.         mov     eax, edx
  740.         sub     eax, esi
  741.         jz      .nofirst
  742.         or      al, FREE_BLOCK
  743.         mov     [page_tabs+ebx*8], eax
  744. .nofirst:
  745.         mov     eax, [alloc_size]
  746.         add     eax, 0x1FFF
  747.         and     eax, not 0xFFF
  748.         mov     ebx, edx
  749.         add     edx, eax
  750.         shr     ebx, 12
  751.         or      al, USED_BLOCK
  752.         mov     [page_tabs+ebx*8], eax
  753.         shr     eax, 12
  754.         dec     eax
  755.         jz      .second_nofill
  756.         inc     ebx
  757. .fill:
  758.         mov     dword [page_tabs+ebx*8], 2
  759.         inc     ebx
  760.         dec     eax
  761.         jnz     .fill
  762.  
  763. .second_nofill:
  764.         sub     ecx, edx
  765.         jz      .nothird
  766.         or      cl, FREE_BLOCK
  767.         mov     [page_tabs+ebx*8], ecx
  768.  
  769. .nothird:
  770.         mov     edx, [current_process]
  771.         mov     ebx, [alloc_size]
  772.         add     ebx, 0xFFF
  773.         and     ebx, not 0xFFF
  774.         add     [edx+PROC.mem_used], ebx
  775.  
  776.         lea     ecx, [edx+PROC.heap_lock]
  777.         call    mutex_unlock
  778.  
  779.         mov     eax, [address]
  780.  
  781.         pop     edi
  782.         pop     esi
  783.         pop     ebx
  784.         ret
  785. endp
  786.  
  787. align 4
  788. proc user_free stdcall, base:dword
  789.  
  790.         push    esi
  791.  
  792.         mov     esi, [base]
  793.         test    esi, esi
  794.         jz      .fail
  795.  
  796.         push    ebx
  797.  
  798.         mov     ebx, [current_process]
  799.         lea     ecx, [ebx+PROC.heap_lock]
  800.         call    mutex_lock
  801.  
  802.         xor     ebx, ebx
  803.         shr     esi, 12
  804.         mov     eax, [page_tabs+(esi-1)*8]
  805.         test    al, USED_BLOCK
  806.         jz      .cantfree
  807.         test    al, DONT_FREE_BLOCK
  808.         jnz     .cantfree
  809.  
  810.         and     eax, not 4095
  811.         mov     ecx, eax
  812.         or      al, FREE_BLOCK
  813.         mov     [page_tabs+(esi-1)*8], eax
  814.         sub     ecx, 4096
  815.         mov     ebx, ecx
  816.         shr     ecx, 12
  817.         jz      .released
  818. .release:
  819.         xor     eax, eax
  820.         xchg    eax, [page_tabs+esi*8]
  821.         test    al, 1
  822.         jz      @F
  823.         test    eax, PG_SHARED
  824.         jnz     @F
  825.         call    free_page
  826.         mov     eax, esi
  827.         shl     eax, 12
  828.         invlpg  [eax]
  829. @@:
  830.         inc     esi
  831.         dec     ecx
  832.         jnz     .release
  833.  
  834. .released:
  835.         push    edi
  836.  
  837.         mov     edx, [current_process]
  838.         lea     ecx, [edx+PROC.heap_lock]
  839.         mov     esi, dword [edx+PROC.heap_base]
  840.         mov     edi, dword [edx+PROC.heap_top]
  841.         sub     ebx, [edx+PROC.mem_used]
  842.         neg     ebx
  843.         mov     [edx+PROC.mem_used], ebx
  844.         call    user_normalize
  845.         pop     edi
  846. .exit:
  847.         call    mutex_unlock
  848.  
  849.         xor     eax, eax
  850.         inc     eax
  851.         pop     ebx
  852.         pop     esi
  853.         ret
  854.  
  855. .cantfree:
  856.         mov     ecx, [current_process]
  857.         lea     ecx, [ecx+PROC.heap_lock]
  858.         jmp     .exit
  859. .fail:
  860.         xor     eax, eax
  861.         pop     esi
  862.         ret
  863. endp
  864.  
  865.  
  866. align 4
  867. proc user_unmap stdcall, base:dword, offset:dword, size:dword
  868.  
  869.         push    ebx
  870.  
  871.         mov     ebx, [base]             ; must be valid pointer
  872.         test    ebx, ebx
  873.         jz      .error
  874.  
  875.         mov     edx, [offset]           ; check offset
  876.         add     edx, ebx                ; must be below 2Gb app limit
  877.         js      .error
  878.  
  879.         shr     ebx, 12                 ; chek block attributes
  880.         lea     ebx, [page_tabs+ebx*8]
  881.         mov     eax, [ebx-4]            ; block attributes
  882.         test    al, USED_BLOCK
  883.         jz      .error
  884.         test    al, DONT_FREE_BLOCK
  885.         jnz     .error
  886.  
  887.         shr     edx, 12
  888.         lea     edx, [page_tabs+edx*8]  ; unmap offset
  889.  
  890.         mov     ecx, [size]
  891.         add     ecx, 4095
  892.         shr     ecx, 12                 ; unmap size in pages
  893.  
  894.         shr     eax, 12                 ; block size + 1 page
  895.         lea     ebx, [ebx+eax*8-8]      ; block end ptr
  896.         lea     eax, [edx+ecx*8]        ; unmap end ptr
  897.  
  898.         cmp     eax, ebx                ; check for overflow
  899.         ja      .error
  900.  
  901.         mov     ebx, [offset]
  902.         and     ebx, not 4095           ; is it required ?
  903.         add     ebx, [base]
  904.  
  905. .unmap:
  906.         mov     eax, [edx]              ; get page addres
  907.         test    al, 1                   ; page mapped ?
  908.         jz      @F
  909.         test    eax, PG_SHARED          ; page shared ?
  910.         jnz     @F
  911.         mov     [edx], dword 2
  912.                                         ; mark page as reserved
  913.         invlpg  [ebx]                   ; when we start using
  914.         call    free_page               ; empty c-o-w page instead this ?
  915. @@:
  916.         add     ebx, 4096
  917.         add     edx, 8
  918.         dec     ecx
  919.         jnz     .unmap
  920.  
  921.         pop     ebx
  922.         or      al, 1                   ; return non zero on success
  923.         ret
  924. .error:
  925.         pop     ebx
  926.         xor     eax, eax                ; something wrong
  927.         ret
  928. endp
  929.  
  930. align 4
  931. user_normalize:
  932. ; in: esi=heap_base, edi=heap_top
  933. ; out: eax=0 <=> OK
  934. ; destroys: ebx,edx,esi,edi
  935.         shr     esi, 12
  936.         shr     edi, 12
  937. @@:
  938.         mov     eax, [page_tabs+esi*8]
  939.         test    al, USED_BLOCK
  940.         jz      .test_free
  941.         shr     eax, 12
  942.         add     esi, eax
  943.         jmp     @B
  944. .test_free:
  945.         test    al, FREE_BLOCK
  946.         jz      .err
  947.         mov     edx, eax
  948.         shr     edx, 12
  949.         add     edx, esi
  950.         cmp     edx, edi
  951.         jae     .exit
  952.  
  953.         mov     ebx, [page_tabs+edx*8]
  954.         test    bl, USED_BLOCK
  955.         jz      .next_free
  956.  
  957.         shr     ebx, 12
  958.         add     edx, ebx
  959.         mov     esi, edx
  960.         jmp     @B
  961. .next_free:
  962.         test    bl, FREE_BLOCK
  963.         jz      .err
  964.         and     dword [page_tabs+edx*8], 0
  965.         add     eax, ebx
  966.         and     eax, not 4095
  967.         or      eax, FREE_BLOCK
  968.         mov     [page_tabs+esi*8], eax
  969.         jmp     @B
  970. .exit:
  971.         xor     eax, eax
  972.         inc     eax
  973.         ret
  974. .err:
  975.         xor     eax, eax
  976.         ret
  977.  
  978. user_realloc:
  979. ; in: eax = pointer, ebx = new size
  980. ; out: eax = new pointer or NULL
  981.         test    eax, eax
  982.         jnz     @f
  983. ; realloc(NULL,sz) - same as malloc(sz)
  984.         push    ebx
  985.         call    user_alloc
  986.         ret
  987. @@:
  988.         push    ecx edx
  989.  
  990.         push    eax
  991.         mov     ecx, [current_process]
  992.         lea     ecx, [ecx+PROC.heap_lock]
  993.         call    mutex_lock
  994.         pop     eax
  995.  
  996.         lea     ecx, [eax - 0x1000]
  997.         shr     ecx, 12
  998.         mov     edx, [page_tabs+ecx*8]
  999.         test    dl, USED_BLOCK
  1000.         jnz     @f
  1001. ; attempt to realloc invalid pointer
  1002. .ret0:
  1003.         mov     ecx, [current_process]
  1004.         lea     ecx, [ecx+PROC.heap_lock]
  1005.         call    mutex_unlock
  1006.  
  1007.         pop     edx ecx
  1008.         xor     eax, eax
  1009.         ret
  1010. @@:
  1011.         test    dl, DONT_FREE_BLOCK
  1012.         jnz     .ret0
  1013.         add     ebx, 0x1FFF
  1014.         shr     edx, 12
  1015.         shr     ebx, 12
  1016. ; edx = allocated size, ebx = new size
  1017.         add     edx, ecx
  1018.         add     ebx, ecx
  1019.         cmp     edx, ebx
  1020.         jb      .realloc_add
  1021. ; release part of allocated memory
  1022. .loop:
  1023.         cmp     edx, ebx
  1024.         jz      .release_done
  1025.         dec     edx
  1026.         xor     eax, eax
  1027.         xchg    eax, [page_tabs+edx*8]
  1028.         test    al, 1
  1029.         jz      .loop
  1030.         call    free_page
  1031.         mov     eax, edx
  1032.         shl     eax, 12
  1033.         invlpg  [eax]
  1034.         jmp     .loop
  1035. .release_done:
  1036.         sub     ebx, ecx
  1037.         cmp     ebx, 1
  1038.         jnz     .nofreeall
  1039.         mov     eax, [page_tabs+ecx*8]
  1040.         and     eax, not 0xFFF
  1041.         mov     edx, [current_process]
  1042.         mov     ebx, [edx+PROC.mem_used]
  1043.         sub     ebx, eax
  1044.         add     ebx, 0x1000
  1045.         or      al, FREE_BLOCK
  1046.         mov     [page_tabs+ecx*8], eax
  1047.         push    esi edi
  1048.         mov     esi, [edx+PROC.heap_base]
  1049.         mov     edi, [edx+PROC.heap_top]
  1050.         mov     [edx+PROC.mem_used], ebx
  1051.         call    user_normalize
  1052.         pop     edi esi
  1053.         jmp     .ret0   ; all freed
  1054. .nofreeall:
  1055.         sub     edx, ecx
  1056.         shl     ebx, 12
  1057.         or      ebx, USED_BLOCK
  1058.         xchg    [page_tabs+ecx*8], ebx
  1059.         shr     ebx, 12
  1060.         sub     ebx, edx
  1061.         push    ebx ecx edx
  1062.         mov     edx, [current_process]
  1063.         shl     ebx, 12
  1064.         sub     ebx, [edx+PROC.mem_used]
  1065.         neg     ebx
  1066.         mov     [edx+PROC.mem_used], ebx
  1067.         pop     edx ecx ebx
  1068.         lea     eax, [ecx+1]
  1069.         shl     eax, 12
  1070.         push    eax
  1071.         add     ecx, edx
  1072.         lea     edx, [ecx+ebx]
  1073.         shl     ebx, 12
  1074.         jz      .ret
  1075.         push    esi
  1076.         mov     esi, [current_process]
  1077.         mov     esi, [esi+PROC.heap_top]
  1078.         shr     esi, 12
  1079. @@:
  1080.         cmp     edx, esi
  1081.         jae     .merge_done
  1082.         mov     eax, [page_tabs+edx*8]
  1083.         test    al, USED_BLOCK
  1084.         jnz     .merge_done
  1085.         and     dword [page_tabs+edx*8], 0
  1086.         shr     eax, 12
  1087.         add     edx, eax
  1088.         shl     eax, 12
  1089.         add     ebx, eax
  1090.         jmp     @b
  1091. .merge_done:
  1092.         pop     esi
  1093.         or      ebx, FREE_BLOCK
  1094.         mov     [page_tabs+ecx*8], ebx
  1095. .ret:
  1096.         mov     ecx, [current_process]
  1097.         lea     ecx, [ecx+PROC.heap_lock]
  1098.         call    mutex_unlock
  1099.         pop     eax edx ecx
  1100.         ret
  1101.  
  1102. .realloc_add:
  1103. ; get some additional memory
  1104.         mov     eax, [current_process]
  1105.         mov     eax, [eax+PROC.heap_top]
  1106.         shr     eax, 12
  1107.         cmp     edx, eax
  1108.         jae     .cant_inplace
  1109.         mov     eax, [page_tabs+edx*8]
  1110.         test    al, FREE_BLOCK
  1111.         jz      .cant_inplace
  1112.         shr     eax, 12
  1113.         add     eax, edx
  1114.         sub     eax, ebx
  1115.         jb      .cant_inplace
  1116.         jz      @f
  1117.         shl     eax, 12
  1118.         or      al, FREE_BLOCK
  1119.         mov     [page_tabs+ebx*8], eax
  1120. @@:
  1121.         mov     eax, ebx
  1122.         sub     eax, ecx
  1123.         shl     eax, 12
  1124.         or      al, USED_BLOCK
  1125.         mov     [page_tabs+ecx*8], eax
  1126.         lea     eax, [ecx+1]
  1127.         shl     eax, 12
  1128.         push    eax
  1129.         push    edi
  1130.         lea     edi, [page_tabs+edx*8]
  1131.         mov     eax, 2
  1132.         sub     ebx, edx
  1133.         mov     ecx, ebx
  1134.         cld
  1135.         rep stosd
  1136.         pop     edi
  1137.         mov     edx, [current_process]
  1138.         shl     ebx, 12
  1139.         add     [edx+PROC.mem_used], ebx
  1140.  
  1141.         mov     ecx, [current_process]
  1142.         lea     ecx, [ecx+PROC.heap_lock]
  1143.         call    mutex_unlock
  1144.         pop     eax edx ecx
  1145.         ret
  1146.  
  1147. .cant_inplace:
  1148.         push    esi edi
  1149.         mov     eax, [current_process]
  1150.         mov     esi, [eax+PROC.heap_base]
  1151.         mov     edi, [eax+PROC.heap_top]
  1152.         shr     esi, 12
  1153.         shr     edi, 12
  1154.         sub     ebx, ecx
  1155. .find_place:
  1156.         cmp     esi, edi
  1157.         jae     .place_not_found
  1158.         mov     eax, [page_tabs+esi*8]
  1159.         test    al, FREE_BLOCK
  1160.         jz      .next_place
  1161.         shr     eax, 12
  1162.         cmp     eax, ebx
  1163.         jae     .place_found
  1164.         add     esi, eax
  1165.         jmp     .find_place
  1166. .next_place:
  1167.         shr     eax, 12
  1168.         add     esi, eax
  1169.         jmp     .find_place
  1170. .place_not_found:
  1171.         pop     edi esi
  1172.         jmp     .ret0
  1173. .place_found:
  1174.         sub     eax, ebx
  1175.         jz      @f
  1176.         push    esi
  1177.         add     esi, ebx
  1178.         shl     eax, 12
  1179.         or      al, FREE_BLOCK
  1180.         mov     [page_tabs+esi*8], eax
  1181.         pop     esi
  1182. @@:
  1183.         mov     eax, ebx
  1184.         shl     eax, 12
  1185.         or      al, USED_BLOCK
  1186.         mov     [page_tabs+esi*8], eax
  1187.         inc     esi
  1188.         mov     eax, esi
  1189.         shl     eax, 12
  1190.         push    eax
  1191.         mov     eax, [page_tabs+ecx*8]
  1192.         and     eax, not 0xFFF
  1193.         or      al, FREE_BLOCK
  1194.         sub     edx, ecx
  1195.         mov     [page_tabs+ecx*8], eax
  1196.         inc     ecx
  1197.         dec     ebx
  1198.         dec     edx
  1199.         jz      .no
  1200. @@:
  1201.         xor     eax, eax
  1202.         xchg    eax, [page_tabs+ecx*8]
  1203.         mov     [page_tabs+esi*8], eax
  1204.         mov     eax, ecx
  1205.         shl     eax, 12
  1206.         invlpg  [eax]
  1207.         inc     esi
  1208.         inc     ecx
  1209.         dec     ebx
  1210.         dec     edx
  1211.         jnz     @b
  1212. .no:
  1213.         push    ebx
  1214.         mov     edx, [current_process]
  1215.         shl     ebx, 12
  1216.         add     [edx+PROC.mem_used], ebx
  1217.         pop     ebx
  1218. @@:
  1219.         mov     dword [page_tabs+esi*8], 2
  1220.         inc     esi
  1221.         dec     ebx
  1222.         jnz     @b
  1223.  
  1224.         mov     ecx, [current_process]
  1225.         lea     ecx, [ecx+PROC.heap_lock]
  1226.         call    mutex_unlock
  1227.         pop     eax edi esi edx ecx
  1228.         ret
  1229.  
  1230.  
  1231.  
  1232. ;;;;;;;;;;;;;;      SHARED MEMORY     ;;;;;;;;;;;;;;;;;
  1233.  
  1234.  
  1235. ; param
  1236. ;  eax= shm_map object
  1237.  
  1238. align 4
  1239. destroy_smap:
  1240.  
  1241.         pushfd
  1242.         cli
  1243.  
  1244.         push    esi
  1245.         push    edi
  1246.  
  1247.         mov     edi, eax
  1248.         mov     esi, [eax+SMAP.parent]
  1249.         test    esi, esi
  1250.         jz      .done
  1251.  
  1252.         lock dec [esi+SMEM.refcount]
  1253.         jnz     .done
  1254.  
  1255.         mov     ecx, [esi+SMEM.bk]
  1256.         mov     edx, [esi+SMEM.fd]
  1257.  
  1258.         mov     [ecx+SMEM.fd], edx
  1259.         mov     [edx+SMEM.bk], ecx
  1260.  
  1261.         stdcall kernel_free, [esi+SMEM.base]
  1262.         mov     eax, esi
  1263.         call    free
  1264. .done:
  1265.         mov     eax, edi
  1266.         call    destroy_kernel_object
  1267.  
  1268.         pop     edi
  1269.         pop     esi
  1270.         popfd
  1271.  
  1272.         ret
  1273.  
  1274. E_NOTFOUND     equ  5
  1275. E_ACCESS       equ 10
  1276. E_NOMEM         equ 30
  1277. E_PARAM         equ 33
  1278.  
  1279. SHM_READ       equ 0
  1280. SHM_WRITE       equ 1
  1281.  
  1282. SHM_ACCESS_MASK equ 3
  1283.  
  1284. SHM_OPEN       equ (0 shl 2)
  1285. SHM_OPEN_ALWAYS equ (1 shl 2)
  1286. SHM_CREATE     equ (2 shl 2)
  1287.  
  1288. SHM_OPEN_MASK   equ (3 shl 2)
  1289.  
  1290. align 4
  1291. proc shmem_open stdcall name:dword, size:dword, access:dword
  1292.         locals
  1293.            action         dd ?
  1294.            owner_access   dd ?
  1295.            mapped         dd ?
  1296.         endl
  1297.  
  1298.         push    ebx
  1299.         push    esi
  1300.         push    edi
  1301.  
  1302.         mov     [mapped], 0
  1303.         mov     [owner_access], 0
  1304.  
  1305.         pushfd                         ;mutex required
  1306.         cli
  1307.  
  1308.         mov     eax, [access]
  1309.         and     eax, SHM_OPEN_MASK
  1310.         mov     [action], eax
  1311.  
  1312.         mov     ebx, [name]
  1313.         test    ebx, ebx
  1314.         mov     edx, E_PARAM
  1315.         jz      .fail
  1316.  
  1317.         mov     esi, [shmem_list.fd]
  1318. align 4
  1319. @@:
  1320.         cmp     esi, shmem_list
  1321.         je      .not_found
  1322.  
  1323.         lea     edx, [esi+SMEM.name]; link , base, size
  1324.         stdcall strncmp, edx, ebx, 32
  1325.         test    eax, eax
  1326.         je      .found
  1327.  
  1328.         mov     esi, [esi+SMEM.fd]
  1329.         jmp     @B
  1330.  
  1331. .not_found:
  1332.         mov     eax, [action]
  1333.  
  1334.         cmp     eax, SHM_OPEN
  1335.         mov     edx, E_NOTFOUND
  1336.         je      .fail
  1337.  
  1338.         cmp     eax, SHM_CREATE
  1339.         mov     edx, E_PARAM
  1340.         je      .create_shm
  1341.  
  1342.         cmp     eax, SHM_OPEN_ALWAYS
  1343.         jne     .fail
  1344.  
  1345. .create_shm:
  1346.  
  1347.         mov     ecx, [size]
  1348.         test    ecx, ecx
  1349.         jz      .fail
  1350.  
  1351.         add     ecx, 4095
  1352.         and     ecx, -4096
  1353.         mov     [size], ecx
  1354.  
  1355.         mov     eax, sizeof.SMEM
  1356.         call    malloc
  1357.         test    eax, eax
  1358.         mov     esi, eax
  1359.         mov     edx, E_NOMEM
  1360.         jz      .fail
  1361.  
  1362.         stdcall kernel_alloc, [size]
  1363.         test    eax, eax
  1364.         mov     [mapped], eax
  1365.         mov     edx, E_NOMEM
  1366.         jz      .cleanup
  1367.  
  1368.         mov     ecx, [size]
  1369.         mov     edx, [access]
  1370.         and     edx, SHM_ACCESS_MASK
  1371.  
  1372.         mov     [esi+SMEM.base], eax
  1373.         mov     [esi+SMEM.size], ecx
  1374.         mov     [esi+SMEM.access], edx
  1375.         mov     [esi+SMEM.refcount], 0
  1376.         mov     [esi+SMEM.name+28], 0
  1377.  
  1378.         lea     eax, [esi+SMEM.name]
  1379.         stdcall strncpy, eax, [name], 31
  1380.  
  1381.         mov     eax, [shmem_list.fd]
  1382.         mov     [esi+SMEM.bk], shmem_list
  1383.         mov     [esi+SMEM.fd], eax
  1384.  
  1385.         mov     [eax+SMEM.bk], esi
  1386.         mov     [shmem_list.fd], esi
  1387.  
  1388.         mov     [action], SHM_OPEN
  1389.         mov     [owner_access], SHM_WRITE
  1390.  
  1391. .found:
  1392.         mov     eax, [action]
  1393.  
  1394.         cmp     eax, SHM_CREATE
  1395.         mov     edx, E_ACCESS
  1396.         je      .exit
  1397.  
  1398.         cmp     eax, SHM_OPEN
  1399.         mov     edx, E_PARAM
  1400.         je      .create_map
  1401.  
  1402.         cmp     eax, SHM_OPEN_ALWAYS
  1403.         jne     .fail
  1404.  
  1405. .create_map:
  1406.  
  1407.         mov     eax, [access]
  1408.         and     eax, SHM_ACCESS_MASK
  1409.         cmp     eax, [esi+SMEM.access]
  1410.         mov     [access], eax
  1411.         mov     edx, E_ACCESS
  1412.         ja      .fail
  1413.  
  1414.         mov     ebx, [CURRENT_TASK]
  1415.         shl     ebx, 5
  1416.         mov     ebx, [CURRENT_TASK+ebx+4]
  1417.         mov     eax, sizeof.SMAP
  1418.  
  1419.         call    create_kernel_object
  1420.         test    eax, eax
  1421.         mov     edi, eax
  1422.         mov     edx, E_NOMEM
  1423.         jz      .fail
  1424.  
  1425.         inc     [esi+SMEM.refcount]
  1426.  
  1427.         mov     [edi+SMAP.magic], 'SMAP'
  1428.         mov     [edi+SMAP.destroy], destroy_smap
  1429.         mov     [edi+SMAP.parent], esi
  1430.         mov     [edi+SMAP.base], 0
  1431.  
  1432.         stdcall user_alloc, [esi+SMEM.size]
  1433.         test    eax, eax
  1434.         mov     [mapped], eax
  1435.         mov     edx, E_NOMEM
  1436.         jz      .cleanup2
  1437.  
  1438.         mov     [edi+SMAP.base], eax
  1439.  
  1440.         mov     ecx, [esi+SMEM.size]
  1441.         mov     [size], ecx
  1442.  
  1443.         shr     ecx, 12
  1444.         shr     eax, 9
  1445.  
  1446.         mov     esi, [esi+SMEM.base]
  1447.         shr     esi, 9
  1448.         lea     edi, [page_tabs+eax]
  1449.         add     esi, page_tabs
  1450.  
  1451.         mov     edx, [access]
  1452.         or      edx, [owner_access]
  1453.         shl     edx, 1
  1454.         or      edx, PG_SHARED+PG_UR
  1455. @@:
  1456.         lodsd
  1457.         and     eax, 0xFFFFF000
  1458.         or      eax, edx
  1459.         stosd
  1460.         movsd
  1461.         loop    @B
  1462.  
  1463.         xor     edx, edx
  1464.  
  1465.         cmp     [owner_access], 0
  1466.         jne     .fail
  1467. .exit:
  1468.         mov     edx, [size]
  1469. .fail:
  1470.         mov     eax, [mapped]
  1471.  
  1472.         popfd
  1473.         pop     edi
  1474.         pop     esi
  1475.         pop     ebx
  1476.         ret
  1477. .cleanup:
  1478.         mov     [size], edx
  1479.         mov     eax, esi
  1480.         call    free
  1481.         jmp     .exit
  1482.  
  1483. .cleanup2:
  1484.         mov     [size], edx
  1485.         mov     eax, edi
  1486.         call    destroy_smap
  1487.         jmp     .exit
  1488. endp
  1489.  
  1490. align 4
  1491. proc shmem_close stdcall, name:dword
  1492.  
  1493.         mov     eax, [name]
  1494.         test    eax, eax
  1495.         jz      .fail
  1496.  
  1497.         push    esi
  1498.         push    edi
  1499.         pushfd
  1500.         cli
  1501.  
  1502.         mov     esi, [current_slot]
  1503.         add     esi, APP_OBJ_OFFSET
  1504. .next:
  1505.         mov     eax, [esi+APPOBJ.fd]
  1506.         test    eax, eax
  1507.         jz      @F
  1508.  
  1509.         cmp     eax, esi
  1510.         mov     esi, eax
  1511.         je      @F
  1512.  
  1513.         cmp     [eax+SMAP.magic], 'SMAP'
  1514.         jne     .next
  1515.  
  1516.         mov     edi, [eax+SMAP.parent]
  1517.         test    edi, edi
  1518.         jz      .next
  1519.  
  1520.         lea     edi, [edi+SMEM.name]
  1521.         stdcall strncmp, [name], edi, 32
  1522.         test    eax, eax
  1523.         jne     .next
  1524.  
  1525.         stdcall user_free, [esi+SMAP.base]
  1526.  
  1527.         mov     eax, esi
  1528.         call    [esi+APPOBJ.destroy]
  1529. @@:
  1530.         popfd
  1531.         pop     edi
  1532.         pop     esi
  1533. .fail:
  1534.         ret
  1535. endp
  1536.