Subversion Repositories Kolibri OS

Rev

Rev 9900 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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