Subversion Repositories Kolibri OS

Rev

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

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