Subversion Repositories Kolibri OS

Rev

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