Subversion Repositories Kolibri OS

Rev

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

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