Subversion Repositories Kolibri OS

Rev

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