Subversion Repositories Kolibri OS

Rev

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