mirror of
https://github.com/KolibriOS/kolibrios.git
synced 2024-12-30 02:09:41 +03:00
5ce26ca2da
git-svn-id: svn://kolibrios.org@1710 a494cfbc-eb01-0410-851d-a64ba20cac60
1544 lines
36 KiB
PHP
1544 lines
36 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision$
|
|
|
|
|
|
struc MEM_BLOCK
|
|
{ .next_block dd ?
|
|
.prev_block dd ? ;+4
|
|
.list_fd dd ? ;+8
|
|
.list_bk dd ? ;+12
|
|
.base dd ? ;+16
|
|
.size dd ? ;+20
|
|
.flags dd ? ;+24
|
|
.handle dd ? ;+28
|
|
}
|
|
|
|
MEM_LIST_OFFSET equ 8
|
|
FREE_BLOCK equ 4
|
|
USED_BLOCK equ 8
|
|
DONT_FREE_BLOCK equ 10h
|
|
|
|
virtual at 0
|
|
MEM_BLOCK MEM_BLOCK
|
|
end virtual
|
|
|
|
MEM_BLOCK_SIZE equ 8*4
|
|
|
|
block_next equ MEM_BLOCK.next_block
|
|
block_prev equ MEM_BLOCK.prev_block
|
|
list_fd equ MEM_BLOCK.list_fd
|
|
list_bk equ MEM_BLOCK.list_bk
|
|
block_base equ MEM_BLOCK.base
|
|
block_size equ MEM_BLOCK.size
|
|
block_flags equ MEM_BLOCK.flags
|
|
|
|
macro calc_index op
|
|
{ shr op, 12
|
|
dec op
|
|
cmp op, 63
|
|
jna @f
|
|
mov op, 63
|
|
@@:
|
|
}
|
|
|
|
macro remove_from_list op
|
|
{ mov edx, [op+list_fd]
|
|
mov ecx, [op+list_bk]
|
|
test edx, edx
|
|
jz @f
|
|
mov [edx+list_bk], ecx
|
|
@@:
|
|
test ecx, ecx
|
|
jz @f
|
|
mov [ecx+list_fd], edx
|
|
@@:
|
|
mov [op+list_fd],0
|
|
mov [op+list_bk],0
|
|
}
|
|
|
|
macro remove_from_free op
|
|
{
|
|
remove_from_list op
|
|
|
|
mov eax, [op+block_size]
|
|
calc_index eax
|
|
cmp [mem_block_list+eax*4], op
|
|
jne @f
|
|
mov [mem_block_list+eax*4], edx
|
|
@@:
|
|
cmp [mem_block_list+eax*4], 0
|
|
jne @f
|
|
btr [mem_block_mask], eax
|
|
@@:
|
|
}
|
|
|
|
macro remove_from_used op
|
|
{
|
|
mov edx, [op+list_fd]
|
|
mov ecx, [op+list_bk]
|
|
mov [edx+list_bk], ecx
|
|
mov [ecx+list_fd], edx
|
|
mov [op+list_fd], 0
|
|
mov [op+list_bk], 0
|
|
}
|
|
|
|
align 4
|
|
proc init_kernel_heap
|
|
|
|
mov ecx, 64
|
|
mov edi, mem_block_list
|
|
xor eax, eax
|
|
cld
|
|
rep stosd
|
|
|
|
mov ecx, 512/4
|
|
mov edi, mem_block_map
|
|
not eax
|
|
rep stosd
|
|
|
|
mov [mem_block_start], mem_block_map
|
|
mov [mem_block_end], mem_block_map+512
|
|
mov [mem_block_arr], HEAP_BASE
|
|
|
|
mov eax, mem_used.fd-MEM_LIST_OFFSET
|
|
mov [mem_used.fd], eax
|
|
mov [mem_used.bk], eax
|
|
|
|
mov [KERNEL_ALLOC_FLAG], dword PG_SW
|
|
stdcall alloc_pages, dword 32
|
|
mov ecx, 32
|
|
mov edx, eax
|
|
mov edi, HEAP_BASE
|
|
.l1:
|
|
stdcall map_page,edi,edx,PG_SW
|
|
add edi, 0x1000
|
|
add edx, 0x1000
|
|
dec ecx
|
|
jnz .l1
|
|
|
|
mov edi, HEAP_BASE
|
|
mov ebx, HEAP_BASE+MEM_BLOCK_SIZE
|
|
xor eax, eax
|
|
mov [edi+block_next], ebx
|
|
mov [edi+block_prev], eax
|
|
mov [edi+list_fd], eax
|
|
mov [edi+list_bk], eax
|
|
mov [edi+block_base], HEAP_BASE
|
|
mov [edi+block_size], 4096*MEM_BLOCK_SIZE
|
|
mov [edi+block_flags], USED_BLOCK
|
|
|
|
mov [ebx+block_next], eax
|
|
mov [ebx+block_prev], eax
|
|
mov [ebx+list_fd], eax
|
|
mov [ebx+list_bk], eax
|
|
mov [ebx+block_base], HEAP_BASE+4096*MEM_BLOCK_SIZE
|
|
|
|
mov ecx, [pg_data.kernel_pages]
|
|
shl ecx, 12
|
|
sub ecx, HEAP_BASE-OS_BASE+4096*MEM_BLOCK_SIZE
|
|
mov [heap_size], ecx
|
|
mov [heap_free], ecx
|
|
mov [ebx+block_size], ecx
|
|
mov [ebx+block_flags], FREE_BLOCK
|
|
|
|
mov [mem_block_mask], eax
|
|
mov [mem_block_mask+4],0x80000000
|
|
|
|
mov [mem_block_list+63*4], ebx
|
|
mov byte [mem_block_map], 0xFC
|
|
and [heap_mutex], 0
|
|
mov [heap_blocks], 4095
|
|
mov [free_blocks], 4094
|
|
ret
|
|
endp
|
|
|
|
; param
|
|
; eax= required size
|
|
;
|
|
; retval
|
|
; edi= memory block descriptor
|
|
; ebx= descriptor index
|
|
|
|
align 4
|
|
get_small_block:
|
|
mov ecx, eax
|
|
shr ecx, 12
|
|
dec ecx
|
|
cmp ecx, 63
|
|
jle .get_index
|
|
mov ecx, 63
|
|
.get_index:
|
|
lea esi, [mem_block_mask]
|
|
xor ebx, ebx
|
|
or edx, -1
|
|
|
|
cmp ecx, 32
|
|
jb .bit_test
|
|
|
|
sub ecx, 32
|
|
add ebx, 32
|
|
add esi, 4
|
|
.bit_test:
|
|
shl edx, cl
|
|
and edx, [esi]
|
|
.find:
|
|
bsf edi, edx
|
|
jz .high_mask
|
|
add ebx, edi
|
|
mov edi, [mem_block_list+ebx*4]
|
|
.check_size:
|
|
cmp eax, [edi+block_size]
|
|
ja .next
|
|
ret
|
|
|
|
.high_mask:
|
|
add esi, 4
|
|
cmp esi, mem_block_mask+8
|
|
jae .err
|
|
add ebx, 32
|
|
mov edx, [esi]
|
|
jmp .find
|
|
.next:
|
|
mov edi, [edi+list_fd]
|
|
test edi, edi
|
|
jnz .check_size
|
|
.err:
|
|
xor edi, edi
|
|
ret
|
|
|
|
align 4
|
|
alloc_mem_block:
|
|
|
|
mov ebx, [mem_block_start]
|
|
mov ecx, [mem_block_end]
|
|
.l1:
|
|
bsf eax,[ebx];
|
|
jnz found
|
|
add ebx,4
|
|
cmp ebx, ecx
|
|
jb .l1
|
|
xor eax,eax
|
|
ret
|
|
|
|
found:
|
|
btr [ebx], eax
|
|
mov [mem_block_start],ebx
|
|
sub ebx, mem_block_map
|
|
lea eax,[eax+ebx*8]
|
|
shl eax, 5
|
|
add eax, [mem_block_arr]
|
|
dec [free_blocks]
|
|
ret
|
|
align 4
|
|
free_mem_block:
|
|
mov dword [eax], 0
|
|
mov dword [eax+4], 0
|
|
mov dword [eax+8], 0
|
|
mov dword [eax+12], 0
|
|
mov dword [eax+16], 0
|
|
; mov dword [eax+20], 0
|
|
mov dword [eax+24], 0
|
|
mov dword [eax+28], 0
|
|
|
|
sub eax, [mem_block_arr]
|
|
shr eax, 5
|
|
|
|
mov ebx, mem_block_map
|
|
bts [ebx], eax
|
|
inc [free_blocks]
|
|
shr eax, 3
|
|
and eax, not 3
|
|
add eax, ebx
|
|
cmp [mem_block_start], eax
|
|
ja @f
|
|
ret
|
|
@@:
|
|
mov [mem_block_start], eax
|
|
ret
|
|
.err:
|
|
xor eax, eax
|
|
ret
|
|
|
|
align 4
|
|
proc alloc_kernel_space stdcall, size:dword
|
|
local block_ind:DWORD
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
mov eax, [size]
|
|
add eax, 4095
|
|
and eax, not 4095
|
|
mov [size], eax
|
|
|
|
mov ebx, heap_mutex
|
|
call wait_mutex ;ebx
|
|
|
|
cmp eax, [heap_free]
|
|
ja .error
|
|
|
|
call get_small_block ; eax
|
|
test edi, edi
|
|
jz .error
|
|
|
|
cmp [edi+block_flags], FREE_BLOCK
|
|
jne .error
|
|
|
|
mov [block_ind], ebx ;index of allocated block
|
|
|
|
mov eax, [edi+block_size]
|
|
cmp eax, [size]
|
|
je .m_eq_size
|
|
|
|
call alloc_mem_block
|
|
and eax, eax
|
|
jz .error
|
|
|
|
mov esi, eax ;esi - splitted block
|
|
|
|
mov [esi+block_next], edi
|
|
mov eax, [edi+block_prev]
|
|
mov [esi+block_prev], eax
|
|
mov [edi+block_prev], esi
|
|
mov [esi+list_fd], 0
|
|
mov [esi+list_bk], 0
|
|
and eax, eax
|
|
jz @f
|
|
mov [eax+block_next], esi
|
|
@@:
|
|
mov ebx, [edi+block_base]
|
|
mov [esi+block_base], ebx
|
|
mov edx, [size]
|
|
mov [esi+block_size], edx
|
|
add [edi+block_base], edx
|
|
sub [edi+block_size], edx
|
|
|
|
mov eax, [edi+block_size]
|
|
shr eax, 12
|
|
sub eax, 1
|
|
cmp eax, 63
|
|
jna @f
|
|
mov eax, 63
|
|
@@:
|
|
cmp eax, [block_ind]
|
|
je .m_eq_ind
|
|
|
|
remove_from_list edi
|
|
|
|
mov ecx, [block_ind]
|
|
mov [mem_block_list+ecx*4], edx
|
|
|
|
test edx, edx
|
|
jnz @f
|
|
btr [mem_block_mask], ecx
|
|
@@:
|
|
mov edx, [mem_block_list+eax*4]
|
|
mov [edi+list_fd], edx
|
|
test edx, edx
|
|
jz @f
|
|
mov [edx+list_bk], edi
|
|
@@:
|
|
mov [mem_block_list+eax*4], edi
|
|
bts [mem_block_mask], eax
|
|
.m_eq_ind:
|
|
mov ecx, mem_used.fd-MEM_LIST_OFFSET
|
|
mov edx, [ecx+list_fd]
|
|
mov [esi+list_fd], edx
|
|
mov [esi+list_bk], ecx
|
|
mov [ecx+list_fd], esi
|
|
mov [edx+list_bk], esi
|
|
|
|
mov [esi+block_flags], USED_BLOCK
|
|
mov eax, [esi+block_base]
|
|
mov ebx, [size]
|
|
sub [heap_free], ebx
|
|
and [heap_mutex], 0
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.m_eq_size:
|
|
remove_from_list edi
|
|
mov [mem_block_list+ebx*4], edx
|
|
and edx, edx
|
|
jnz @f
|
|
btr [mem_block_mask], ebx
|
|
@@:
|
|
mov ecx, mem_used.fd-MEM_LIST_OFFSET
|
|
mov edx, [ecx+list_fd]
|
|
mov [edi+list_fd], edx
|
|
mov [edi+list_bk], ecx
|
|
mov [ecx+list_fd], edi
|
|
mov [edx+list_bk], edi
|
|
|
|
mov [edi+block_flags], USED_BLOCK
|
|
mov eax, [edi+block_base]
|
|
mov ebx, [size]
|
|
sub [heap_free], ebx
|
|
and [heap_mutex], 0
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.error:
|
|
xor eax, eax
|
|
mov [heap_mutex], eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc free_kernel_space stdcall uses ebx ecx edx esi edi, base:dword
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
mov ebx, heap_mutex
|
|
call wait_mutex ;ebx
|
|
|
|
mov eax, [base]
|
|
mov esi, [mem_used.fd]
|
|
@@:
|
|
cmp esi, mem_used.fd-MEM_LIST_OFFSET
|
|
je .fail
|
|
|
|
cmp [esi+block_base], eax
|
|
je .found
|
|
mov esi, [esi+list_fd]
|
|
jmp @b
|
|
.found:
|
|
cmp [esi+block_flags], USED_BLOCK
|
|
jne .fail
|
|
|
|
mov eax, [esi+block_size]
|
|
add [heap_free], eax
|
|
|
|
mov edi, [esi+block_next]
|
|
test edi, edi
|
|
jz .prev
|
|
|
|
cmp [edi+block_flags], FREE_BLOCK
|
|
jne .prev
|
|
|
|
remove_from_free edi
|
|
|
|
mov edx, [edi+block_next]
|
|
mov [esi+block_next], edx
|
|
test edx, edx
|
|
jz @f
|
|
|
|
mov [edx+block_prev], esi
|
|
@@:
|
|
mov ecx, [edi+block_size]
|
|
add [esi+block_size], ecx
|
|
|
|
mov eax, edi
|
|
call free_mem_block
|
|
.prev:
|
|
mov edi, [esi+block_prev]
|
|
test edi, edi
|
|
jz .insert
|
|
|
|
cmp [edi+block_flags], FREE_BLOCK
|
|
jne .insert
|
|
|
|
remove_from_used esi
|
|
|
|
mov edx, [esi+block_next]
|
|
mov [edi+block_next], edx
|
|
test edx, edx
|
|
jz @f
|
|
mov [edx+block_prev], edi
|
|
@@:
|
|
mov eax, esi
|
|
call free_mem_block
|
|
|
|
mov ecx, [edi+block_size]
|
|
mov eax, [esi+block_size]
|
|
add eax, ecx
|
|
mov [edi+block_size], eax
|
|
|
|
calc_index eax
|
|
calc_index ecx
|
|
cmp eax, ecx
|
|
je .m_eq
|
|
|
|
push ecx
|
|
remove_from_list edi
|
|
pop ecx
|
|
|
|
cmp [mem_block_list+ecx*4], edi
|
|
jne @f
|
|
mov [mem_block_list+ecx*4], edx
|
|
@@:
|
|
cmp [mem_block_list+ecx*4], 0
|
|
jne @f
|
|
btr [mem_block_mask], ecx
|
|
@@:
|
|
mov esi, [mem_block_list+eax*4]
|
|
mov [mem_block_list+eax*4], edi
|
|
mov [edi+list_fd], esi
|
|
test esi, esi
|
|
jz @f
|
|
mov [esi+list_bk], edi
|
|
@@:
|
|
bts [mem_block_mask], eax
|
|
.m_eq:
|
|
xor eax, eax
|
|
mov [heap_mutex], eax
|
|
dec eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.insert:
|
|
remove_from_used esi
|
|
|
|
mov eax, [esi+block_size]
|
|
calc_index eax
|
|
|
|
mov edi, [mem_block_list+eax*4]
|
|
mov [mem_block_list+eax*4], esi
|
|
mov [esi+list_fd], edi
|
|
test edi, edi
|
|
jz @f
|
|
mov [edi+list_bk], esi
|
|
@@:
|
|
bts [mem_block_mask], eax
|
|
mov [esi+block_flags],FREE_BLOCK
|
|
xor eax, eax
|
|
mov [heap_mutex], eax
|
|
dec eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.fail:
|
|
xor eax, eax
|
|
mov [heap_mutex], eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc kernel_alloc stdcall, size:dword
|
|
locals
|
|
lin_addr dd ?
|
|
pages_count dd ?
|
|
endl
|
|
|
|
push ebx
|
|
push edi
|
|
|
|
mov eax, [size]
|
|
add eax, 4095
|
|
and eax, not 4095;
|
|
mov [size], eax
|
|
and eax, eax
|
|
jz .err
|
|
mov ebx, eax
|
|
shr ebx, 12
|
|
mov [pages_count], ebx
|
|
|
|
stdcall alloc_kernel_space, eax
|
|
test eax, eax
|
|
jz .err
|
|
mov [lin_addr], eax
|
|
|
|
mov ecx, [pages_count]
|
|
mov edx, eax
|
|
mov ebx, ecx
|
|
|
|
shr ecx, 3
|
|
jz .next
|
|
|
|
and ebx, not 7
|
|
push ebx
|
|
stdcall alloc_pages, ebx
|
|
pop ecx ; yes ecx!!!
|
|
and eax, eax
|
|
jz .err
|
|
|
|
mov edi, eax
|
|
mov edx, [lin_addr]
|
|
@@:
|
|
stdcall map_page,edx,edi,dword [KERNEL_ALLOC_FLAG]
|
|
add edx, 0x1000
|
|
add edi, 0x1000
|
|
dec ecx
|
|
jnz @B
|
|
.next:
|
|
mov ecx, [pages_count]
|
|
and ecx, 7
|
|
jz .end
|
|
@@:
|
|
push ecx
|
|
call alloc_page
|
|
pop ecx
|
|
test eax, eax
|
|
jz .err
|
|
|
|
stdcall map_page,edx,eax,dword PG_SW
|
|
add edx, 0x1000
|
|
dec ecx
|
|
jnz @B
|
|
.end:
|
|
mov eax, [lin_addr]
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
.err:
|
|
xor eax, eax
|
|
pop edi
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc kernel_free stdcall, base:dword
|
|
push ebx esi
|
|
|
|
mov ebx, heap_mutex
|
|
call wait_mutex ;ebx
|
|
|
|
mov eax, [base]
|
|
mov esi, [mem_used.fd]
|
|
@@:
|
|
cmp esi, mem_used.fd-MEM_LIST_OFFSET
|
|
je .fail
|
|
|
|
cmp [esi+block_base], eax
|
|
je .found
|
|
mov esi, [esi+list_fd]
|
|
jmp @b
|
|
.found:
|
|
cmp [esi+block_flags], USED_BLOCK
|
|
jne .fail
|
|
|
|
and [heap_mutex], 0
|
|
|
|
push ecx
|
|
mov ecx, [esi+block_size];
|
|
shr ecx, 12
|
|
call release_pages ;eax, ecx
|
|
pop ecx
|
|
stdcall free_kernel_space, [base]
|
|
pop esi ebx
|
|
ret
|
|
.fail:
|
|
xor eax, eax
|
|
mov [heap_mutex], eax
|
|
pop esi ebx
|
|
ret
|
|
endp
|
|
|
|
restore block_next
|
|
restore block_prev
|
|
restore block_list
|
|
restore block_base
|
|
restore block_size
|
|
restore block_flags
|
|
|
|
;;;;;;;;;;;;;; USER ;;;;;;;;;;;;;;;;;
|
|
|
|
HEAP_TOP equ 0x5FC00000
|
|
|
|
align 4
|
|
proc init_heap
|
|
|
|
mov ebx,[current_slot]
|
|
mov eax, [ebx+APPDATA.heap_top]
|
|
test eax, eax
|
|
jz @F
|
|
sub eax,[ebx+APPDATA.heap_base]
|
|
sub eax, 4096
|
|
ret
|
|
@@:
|
|
mov esi, [ebx+APPDATA.mem_size]
|
|
add esi, 4095
|
|
and esi, not 4095
|
|
mov [ebx+APPDATA.mem_size], esi
|
|
mov eax, HEAP_TOP
|
|
mov [ebx+APPDATA.heap_base], esi
|
|
mov [ebx+APPDATA.heap_top], eax
|
|
|
|
sub eax, esi
|
|
shr esi, 10
|
|
mov ecx, eax
|
|
sub eax, 4096
|
|
or ecx, FREE_BLOCK
|
|
mov [page_tabs+esi], ecx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc user_alloc stdcall, alloc_size:dword
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
mov ecx, [alloc_size]
|
|
add ecx, (4095+4096)
|
|
and ecx, not 4095
|
|
|
|
mov ebx, [current_slot]
|
|
mov esi, dword [ebx+APPDATA.heap_base] ; heap_base
|
|
mov edi, dword [ebx+APPDATA.heap_top] ; heap_top
|
|
l_0:
|
|
cmp esi, edi
|
|
jae m_exit
|
|
|
|
mov ebx, esi
|
|
shr ebx, 12
|
|
mov eax, [page_tabs+ebx*4]
|
|
test al, FREE_BLOCK
|
|
jz test_used
|
|
and eax, 0xFFFFF000
|
|
cmp eax, ecx ;alloc_size
|
|
jb m_next
|
|
jz @f
|
|
|
|
lea edx, [esi+ecx]
|
|
sub eax, ecx
|
|
or al, FREE_BLOCK
|
|
shr edx, 12
|
|
mov [page_tabs+edx*4], eax
|
|
@@:
|
|
or ecx, USED_BLOCK
|
|
mov [page_tabs+ebx*4], ecx
|
|
shr ecx, 12
|
|
inc ebx
|
|
dec ecx
|
|
jz .no
|
|
@@:
|
|
mov dword [page_tabs+ebx*4], 2
|
|
inc ebx
|
|
dec ecx
|
|
jnz @B
|
|
.no:
|
|
|
|
mov edx, [current_slot]
|
|
mov ebx, [alloc_size]
|
|
add ebx, 0xFFF
|
|
and ebx, not 0xFFF
|
|
add ebx, [edx+APPDATA.mem_size]
|
|
call update_mem_size
|
|
|
|
lea eax, [esi+4096]
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
test_used:
|
|
test al, USED_BLOCK
|
|
jz m_exit
|
|
|
|
and eax, 0xFFFFF000
|
|
m_next:
|
|
add esi, eax
|
|
jmp l_0
|
|
m_exit:
|
|
xor eax, eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc user_alloc_at stdcall, address:dword, alloc_size:dword
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
mov ebx, [current_slot]
|
|
mov edx, [address]
|
|
and edx, not 0xFFF
|
|
mov [address], edx
|
|
sub edx, 0x1000
|
|
jb .error
|
|
mov esi, [ebx+APPDATA.heap_base]
|
|
mov edi, [ebx+APPDATA.heap_top]
|
|
cmp edx, esi
|
|
jb .error
|
|
.scan:
|
|
cmp esi, edi
|
|
jae .error
|
|
mov ebx, esi
|
|
shr ebx, 12
|
|
mov eax, [page_tabs+ebx*4]
|
|
mov ecx, eax
|
|
and ecx, 0xFFFFF000
|
|
add ecx, esi
|
|
cmp edx, ecx
|
|
jb .found
|
|
mov esi, ecx
|
|
jmp .scan
|
|
.error:
|
|
xor eax, eax
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.found:
|
|
test al, FREE_BLOCK
|
|
jz .error
|
|
mov eax, ecx
|
|
sub eax, edx
|
|
sub eax, 0x1000
|
|
cmp eax, [alloc_size]
|
|
jb .error
|
|
|
|
; Here we have 1 big free block which includes requested area.
|
|
; In general, 3 other blocks must be created instead:
|
|
; free at [esi, edx);
|
|
; busy at [edx, edx+0x1000+ALIGN_UP(alloc_size,0x1000));
|
|
; free at [edx+0x1000+ALIGN_UP(alloc_size,0x1000), ecx)
|
|
; First or third block (or both) may be absent.
|
|
mov eax, edx
|
|
sub eax, esi
|
|
jz .nofirst
|
|
or al, FREE_BLOCK
|
|
mov [page_tabs+ebx*4], eax
|
|
.nofirst:
|
|
mov eax, [alloc_size]
|
|
add eax, 0x1FFF
|
|
and eax, not 0xFFF
|
|
mov ebx, edx
|
|
add edx, eax
|
|
shr ebx, 12
|
|
or al, USED_BLOCK
|
|
mov [page_tabs+ebx*4], eax
|
|
shr eax, 12
|
|
dec eax
|
|
jz .second_nofill
|
|
inc ebx
|
|
.fill:
|
|
mov dword [page_tabs+ebx*4], 2
|
|
inc ebx
|
|
dec eax
|
|
jnz .fill
|
|
.second_nofill:
|
|
sub ecx, edx
|
|
jz .nothird
|
|
or cl, FREE_BLOCK
|
|
mov [page_tabs+ebx*4], ecx
|
|
.nothird:
|
|
|
|
mov edx, [current_slot]
|
|
mov ebx, [alloc_size]
|
|
add ebx, 0xFFF
|
|
and ebx, not 0xFFF
|
|
add ebx, [edx+APPDATA.mem_size]
|
|
call update_mem_size
|
|
|
|
mov eax, [address]
|
|
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc user_free stdcall, base:dword
|
|
|
|
push esi
|
|
|
|
mov esi, [base]
|
|
test esi, esi
|
|
jz .exit
|
|
|
|
push ebx
|
|
|
|
xor ebx, ebx
|
|
shr esi, 12
|
|
mov eax, [page_tabs+(esi-1)*4]
|
|
test al, USED_BLOCK
|
|
jz .cantfree
|
|
test al, DONT_FREE_BLOCK
|
|
jnz .cantfree
|
|
|
|
and eax, not 4095
|
|
mov ecx, eax
|
|
or al, FREE_BLOCK
|
|
mov [page_tabs+(esi-1)*4], eax
|
|
sub ecx, 4096
|
|
mov ebx, ecx
|
|
shr ecx, 12
|
|
jz .released
|
|
.release:
|
|
xor eax, eax
|
|
xchg eax, [page_tabs+esi*4]
|
|
test al, 1
|
|
jz @F
|
|
test eax, PG_SHARED
|
|
jnz @F
|
|
call free_page
|
|
mov eax, esi
|
|
shl eax, 12
|
|
invlpg [eax]
|
|
@@:
|
|
inc esi
|
|
dec ecx
|
|
jnz .release
|
|
.released:
|
|
push edi
|
|
|
|
mov edx, [current_slot]
|
|
mov esi, dword [edx+APPDATA.heap_base]
|
|
mov edi, dword [edx+APPDATA.heap_top]
|
|
sub ebx, [edx+APPDATA.mem_size]
|
|
neg ebx
|
|
call update_mem_size
|
|
call user_normalize
|
|
pop edi
|
|
pop ebx
|
|
pop esi
|
|
ret
|
|
.exit:
|
|
xor eax, eax
|
|
inc eax
|
|
pop esi
|
|
ret
|
|
.cantfree:
|
|
xor eax, eax
|
|
pop ebx
|
|
pop esi
|
|
ret
|
|
endp
|
|
|
|
user_normalize:
|
|
; in: esi=heap_base, edi=heap_top
|
|
; out: eax=0 <=> OK
|
|
; destroys: ebx,edx,esi,edi
|
|
shr esi, 12
|
|
shr edi, 12
|
|
@@:
|
|
mov eax, [page_tabs+esi*4]
|
|
test al, USED_BLOCK
|
|
jz .test_free
|
|
shr eax, 12
|
|
add esi, eax
|
|
jmp @B
|
|
.test_free:
|
|
test al, FREE_BLOCK
|
|
jz .err
|
|
mov edx, eax
|
|
shr edx, 12
|
|
add edx, esi
|
|
cmp edx, edi
|
|
jae .exit
|
|
|
|
mov ebx, [page_tabs+edx*4]
|
|
test bl, USED_BLOCK
|
|
jz .next_free
|
|
|
|
shr ebx, 12
|
|
add edx, ebx
|
|
mov esi, edx
|
|
jmp @B
|
|
.next_free:
|
|
test bl, FREE_BLOCK
|
|
jz .err
|
|
and dword [page_tabs+edx*4], 0
|
|
add eax, ebx
|
|
and eax, not 4095
|
|
or eax, FREE_BLOCK
|
|
mov [page_tabs+esi*4], eax
|
|
jmp @B
|
|
.exit:
|
|
xor eax, eax
|
|
inc eax
|
|
ret
|
|
.err:
|
|
xor eax, eax
|
|
ret
|
|
|
|
user_realloc:
|
|
; in: eax = pointer, ebx = new size
|
|
; out: eax = new pointer or NULL
|
|
test eax, eax
|
|
jnz @f
|
|
; realloc(NULL,sz) - same as malloc(sz)
|
|
push ebx
|
|
call user_alloc
|
|
ret
|
|
@@:
|
|
push ecx edx
|
|
lea ecx, [eax - 0x1000]
|
|
shr ecx, 12
|
|
mov edx, [page_tabs+ecx*4]
|
|
test dl, USED_BLOCK
|
|
jnz @f
|
|
; attempt to realloc invalid pointer
|
|
.ret0:
|
|
pop edx ecx
|
|
xor eax, eax
|
|
ret
|
|
@@:
|
|
test dl, DONT_FREE_BLOCK
|
|
jnz .ret0
|
|
add ebx, 0x1FFF
|
|
shr edx, 12
|
|
shr ebx, 12
|
|
; edx = allocated size, ebx = new size
|
|
add edx, ecx
|
|
add ebx, ecx
|
|
cmp edx, ebx
|
|
jb .realloc_add
|
|
; release part of allocated memory
|
|
.loop:
|
|
cmp edx, ebx
|
|
jz .release_done
|
|
dec edx
|
|
xor eax, eax
|
|
xchg eax, [page_tabs+edx*4]
|
|
test al, 1
|
|
jz .loop
|
|
call free_page
|
|
mov eax, edx
|
|
shl eax, 12
|
|
invlpg [eax]
|
|
jmp .loop
|
|
.release_done:
|
|
sub ebx, ecx
|
|
cmp ebx, 1
|
|
jnz .nofreeall
|
|
mov eax, [page_tabs+ecx*4]
|
|
and eax, not 0xFFF
|
|
mov edx, [current_slot]
|
|
mov ebx, [APPDATA.mem_size+edx]
|
|
sub ebx, eax
|
|
add ebx, 0x1000
|
|
or al, FREE_BLOCK
|
|
mov [page_tabs+ecx*4], eax
|
|
push esi edi
|
|
mov esi, [APPDATA.heap_base+edx]
|
|
mov edi, [APPDATA.heap_top+edx]
|
|
call update_mem_size
|
|
call user_normalize
|
|
pop edi esi
|
|
jmp .ret0 ; all freed
|
|
.nofreeall:
|
|
sub edx, ecx
|
|
shl ebx, 12
|
|
or ebx, USED_BLOCK
|
|
xchg [page_tabs+ecx*4], ebx
|
|
shr ebx, 12
|
|
sub ebx, edx
|
|
push ebx ecx edx
|
|
mov edx, [current_slot]
|
|
shl ebx, 12
|
|
sub ebx, [APPDATA.mem_size+edx]
|
|
neg ebx
|
|
call update_mem_size
|
|
pop edx ecx ebx
|
|
lea eax, [ecx+1]
|
|
shl eax, 12
|
|
push eax
|
|
add ecx, edx
|
|
lea edx, [ecx+ebx]
|
|
shl ebx, 12
|
|
jz .ret
|
|
push esi
|
|
mov esi, [current_slot]
|
|
mov esi, [APPDATA.heap_top+esi]
|
|
shr esi, 12
|
|
@@:
|
|
cmp edx, esi
|
|
jae .merge_done
|
|
mov eax, [page_tabs+edx*4]
|
|
test al, USED_BLOCK
|
|
jnz .merge_done
|
|
and dword [page_tabs+edx*4], 0
|
|
shr eax, 12
|
|
add edx, eax
|
|
shl eax, 12
|
|
add ebx, eax
|
|
jmp @b
|
|
.merge_done:
|
|
pop esi
|
|
or ebx, FREE_BLOCK
|
|
mov [page_tabs+ecx*4], ebx
|
|
.ret:
|
|
pop eax edx ecx
|
|
ret
|
|
.realloc_add:
|
|
; get some additional memory
|
|
mov eax, [current_slot]
|
|
mov eax, [APPDATA.heap_top+eax]
|
|
shr eax, 12
|
|
cmp edx, eax
|
|
jae .cant_inplace
|
|
mov eax, [page_tabs+edx*4]
|
|
test al, FREE_BLOCK
|
|
jz .cant_inplace
|
|
shr eax, 12
|
|
add eax, edx
|
|
sub eax, ebx
|
|
jb .cant_inplace
|
|
jz @f
|
|
shl eax, 12
|
|
or al, FREE_BLOCK
|
|
mov [page_tabs+ebx*4], eax
|
|
@@:
|
|
mov eax, ebx
|
|
sub eax, ecx
|
|
shl eax, 12
|
|
or al, USED_BLOCK
|
|
mov [page_tabs+ecx*4], eax
|
|
lea eax, [ecx+1]
|
|
shl eax, 12
|
|
push eax
|
|
push edi
|
|
lea edi, [page_tabs+edx*4]
|
|
mov eax, 2
|
|
sub ebx, edx
|
|
mov ecx, ebx
|
|
cld
|
|
rep stosd
|
|
pop edi
|
|
mov edx, [current_slot]
|
|
shl ebx, 12
|
|
add ebx, [APPDATA.mem_size+edx]
|
|
call update_mem_size
|
|
pop eax edx ecx
|
|
ret
|
|
.cant_inplace:
|
|
push esi edi
|
|
mov eax, [current_slot]
|
|
mov esi, [APPDATA.heap_base+eax]
|
|
mov edi, [APPDATA.heap_top+eax]
|
|
shr esi, 12
|
|
shr edi, 12
|
|
sub ebx, ecx
|
|
.find_place:
|
|
cmp esi, edi
|
|
jae .place_not_found
|
|
mov eax, [page_tabs+esi*4]
|
|
test al, FREE_BLOCK
|
|
jz .next_place
|
|
shr eax, 12
|
|
cmp eax, ebx
|
|
jae .place_found
|
|
add esi, eax
|
|
jmp .find_place
|
|
.next_place:
|
|
shr eax, 12
|
|
add esi, eax
|
|
jmp .find_place
|
|
.place_not_found:
|
|
pop edi esi
|
|
jmp .ret0
|
|
.place_found:
|
|
sub eax, ebx
|
|
jz @f
|
|
push esi
|
|
add esi, ebx
|
|
shl eax, 12
|
|
or al, FREE_BLOCK
|
|
mov [page_tabs+esi*4], eax
|
|
pop esi
|
|
@@:
|
|
mov eax, ebx
|
|
shl eax, 12
|
|
or al, USED_BLOCK
|
|
mov [page_tabs+esi*4], eax
|
|
inc esi
|
|
mov eax, esi
|
|
shl eax, 12
|
|
push eax
|
|
mov eax, [page_tabs+ecx*4]
|
|
and eax, not 0xFFF
|
|
or al, FREE_BLOCK
|
|
sub edx, ecx
|
|
mov [page_tabs+ecx*4], eax
|
|
inc ecx
|
|
dec ebx
|
|
dec edx
|
|
jz .no
|
|
@@:
|
|
xor eax, eax
|
|
xchg eax, [page_tabs+ecx*4]
|
|
mov [page_tabs+esi*4], eax
|
|
mov eax, ecx
|
|
shl eax, 12
|
|
invlpg [eax]
|
|
inc esi
|
|
inc ecx
|
|
dec ebx
|
|
dec edx
|
|
jnz @b
|
|
.no:
|
|
push ebx
|
|
mov edx, [current_slot]
|
|
shl ebx, 12
|
|
add ebx, [APPDATA.mem_size+edx]
|
|
call update_mem_size
|
|
pop ebx
|
|
@@:
|
|
mov dword [page_tabs+esi*4], 2
|
|
inc esi
|
|
dec ebx
|
|
jnz @b
|
|
pop eax edi esi edx ecx
|
|
ret
|
|
|
|
if 0
|
|
align 4
|
|
proc alloc_dll
|
|
pushf
|
|
cli
|
|
bsf eax, [dll_map]
|
|
jnz .find
|
|
popf
|
|
xor eax, eax
|
|
ret
|
|
.find:
|
|
btr [dll_map], eax
|
|
popf
|
|
shl eax, 5
|
|
add eax, dll_tab
|
|
ret
|
|
endp
|
|
|
|
align 4
|
|
proc alloc_service
|
|
pushf
|
|
cli
|
|
bsf eax, [srv_map]
|
|
jnz .find
|
|
popf
|
|
xor eax, eax
|
|
ret
|
|
.find:
|
|
btr [srv_map], eax
|
|
popf
|
|
shl eax,0x02
|
|
lea eax,[srv_tab+eax+eax*8] ;srv_tab+eax*36
|
|
ret
|
|
endp
|
|
|
|
end if
|
|
|
|
|
|
;;;;;;;;;;;;;; SHARED ;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
; param
|
|
; eax= shm_map object
|
|
|
|
align 4
|
|
destroy_smap:
|
|
|
|
pushfd
|
|
cli
|
|
|
|
push esi
|
|
push edi
|
|
|
|
mov edi, eax
|
|
mov esi, [eax+SMAP.parent]
|
|
test esi, esi
|
|
jz .done
|
|
|
|
lock dec [esi+SMEM.refcount]
|
|
jnz .done
|
|
|
|
mov ecx, [esi+SMEM.bk]
|
|
mov edx, [esi+SMEM.fd]
|
|
|
|
mov [ecx+SMEM.fd], edx
|
|
mov [edx+SMEM.bk], ecx
|
|
|
|
stdcall kernel_free, [esi+SMEM.base]
|
|
mov eax, esi
|
|
call free
|
|
.done:
|
|
mov eax, edi
|
|
call destroy_kernel_object
|
|
|
|
pop edi
|
|
pop esi
|
|
popfd
|
|
|
|
ret
|
|
|
|
E_NOTFOUND equ 5
|
|
E_ACCESS equ 10
|
|
E_NOMEM equ 30
|
|
E_PARAM equ 33
|
|
|
|
SHM_READ equ 0
|
|
SHM_WRITE equ 1
|
|
|
|
SHM_ACCESS_MASK equ 3
|
|
|
|
SHM_OPEN equ (0 shl 2)
|
|
SHM_OPEN_ALWAYS equ (1 shl 2)
|
|
SHM_CREATE equ (2 shl 2)
|
|
|
|
SHM_OPEN_MASK equ (3 shl 2)
|
|
|
|
align 4
|
|
proc shmem_open stdcall name:dword, size:dword, access:dword
|
|
locals
|
|
action dd ?
|
|
owner_access dd ?
|
|
mapped dd ?
|
|
endl
|
|
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
|
|
mov [mapped], 0
|
|
mov [owner_access], 0
|
|
|
|
pushfd ;mutex required
|
|
cli
|
|
|
|
mov eax, [access]
|
|
and eax, SHM_OPEN_MASK
|
|
mov [action], eax
|
|
|
|
mov ebx, [name]
|
|
test ebx, ebx
|
|
mov edx, E_PARAM
|
|
jz .fail
|
|
|
|
mov esi, [shmem_list.fd]
|
|
align 4
|
|
@@:
|
|
cmp esi, shmem_list
|
|
je .not_found
|
|
|
|
lea edx, [esi+SMEM.name] ; link , base, size
|
|
stdcall strncmp, edx, ebx, 32
|
|
test eax, eax
|
|
je .found
|
|
|
|
mov esi, [esi+SMEM.fd]
|
|
jmp @B
|
|
|
|
.not_found:
|
|
mov eax, [action]
|
|
|
|
cmp eax, SHM_OPEN
|
|
mov edx, E_NOTFOUND
|
|
je .fail
|
|
|
|
cmp eax, SHM_CREATE
|
|
mov edx, E_PARAM
|
|
je .create_shm
|
|
|
|
cmp eax, SHM_OPEN_ALWAYS
|
|
jne .fail
|
|
|
|
.create_shm:
|
|
|
|
mov ecx, [size]
|
|
test ecx, ecx
|
|
jz .fail
|
|
|
|
add ecx, 4095
|
|
and ecx, -4096
|
|
mov [size], ecx
|
|
|
|
mov eax, SMEM.sizeof
|
|
call malloc
|
|
test eax, eax
|
|
mov esi, eax
|
|
mov edx, E_NOMEM
|
|
jz .fail
|
|
|
|
stdcall kernel_alloc, [size]
|
|
test eax, eax
|
|
mov [mapped], eax
|
|
mov edx, E_NOMEM
|
|
jz .cleanup
|
|
|
|
mov ecx, [size]
|
|
mov edx, [access]
|
|
and edx, SHM_ACCESS_MASK
|
|
|
|
mov [esi+SMEM.base], eax
|
|
mov [esi+SMEM.size], ecx
|
|
mov [esi+SMEM.access], edx
|
|
mov [esi+SMEM.refcount], 0
|
|
mov [esi+SMEM.name+28], 0
|
|
|
|
lea eax, [esi+SMEM.name]
|
|
stdcall strncpy, eax, [name], 31
|
|
|
|
mov eax, [shmem_list.fd]
|
|
mov [esi+SMEM.bk], shmem_list
|
|
mov [esi+SMEM.fd], eax
|
|
|
|
mov [eax+SMEM.bk], esi
|
|
mov [shmem_list.fd], esi
|
|
|
|
mov [action], SHM_OPEN
|
|
mov [owner_access], SHM_WRITE
|
|
|
|
.found:
|
|
mov eax, [action]
|
|
|
|
cmp eax, SHM_CREATE
|
|
mov edx, E_ACCESS
|
|
je .exit
|
|
|
|
cmp eax, SHM_OPEN
|
|
mov edx, E_PARAM
|
|
je .create_map
|
|
|
|
cmp eax, SHM_OPEN_ALWAYS
|
|
jne .fail
|
|
|
|
.create_map:
|
|
|
|
mov eax, [access]
|
|
and eax, SHM_ACCESS_MASK
|
|
cmp eax, [esi+SMEM.access]
|
|
mov [access], eax
|
|
mov edx, E_ACCESS
|
|
ja .fail
|
|
|
|
mov ebx, [CURRENT_TASK]
|
|
shl ebx, 5
|
|
mov ebx, [CURRENT_TASK+ebx+4]
|
|
mov eax, SMAP.sizeof
|
|
|
|
call create_kernel_object
|
|
test eax, eax
|
|
mov edi, eax
|
|
mov edx, E_NOMEM
|
|
jz .fail
|
|
|
|
inc [esi+SMEM.refcount]
|
|
|
|
mov [edi+SMAP.magic], 'SMAP'
|
|
mov [edi+SMAP.destroy], destroy_smap
|
|
mov [edi+SMAP.parent], esi
|
|
mov [edi+SMAP.base], 0
|
|
|
|
stdcall user_alloc, [esi+SMEM.size]
|
|
test eax, eax
|
|
mov [mapped], eax
|
|
mov edx, E_NOMEM
|
|
jz .cleanup2
|
|
|
|
mov [edi+SMAP.base], eax
|
|
|
|
mov ecx, [esi+SMEM.size]
|
|
mov [size], ecx
|
|
|
|
shr ecx, 12
|
|
shr eax, 10
|
|
|
|
mov esi, [esi+SMEM.base]
|
|
shr esi, 10
|
|
lea edi, [page_tabs+eax]
|
|
add esi, page_tabs
|
|
|
|
mov edx, [access]
|
|
or edx, [owner_access]
|
|
shl edx, 1
|
|
or edx, PG_USER+PG_SHARED
|
|
@@:
|
|
lodsd
|
|
and eax, 0xFFFFF000
|
|
or eax, edx
|
|
stosd
|
|
loop @B
|
|
|
|
xor edx, edx
|
|
|
|
cmp [owner_access], 0
|
|
jne .fail
|
|
.exit:
|
|
mov edx, [size]
|
|
.fail:
|
|
mov eax, [mapped]
|
|
|
|
popfd
|
|
pop edi
|
|
pop esi
|
|
pop ebx
|
|
ret
|
|
.cleanup:
|
|
mov [size], edx
|
|
mov eax, esi
|
|
call free
|
|
jmp .exit
|
|
|
|
.cleanup2:
|
|
mov [size], edx
|
|
mov eax, edi
|
|
call destroy_smap
|
|
jmp .exit
|
|
endp
|
|
|
|
align 4
|
|
proc shmem_close stdcall, name:dword
|
|
|
|
mov eax, [name]
|
|
test eax, eax
|
|
jz .fail
|
|
|
|
push esi
|
|
push edi
|
|
pushfd
|
|
cli
|
|
|
|
mov esi, [current_slot]
|
|
add esi, APP_OBJ_OFFSET
|
|
.next:
|
|
mov eax, [esi+APPOBJ.fd]
|
|
test eax, eax
|
|
jz @F
|
|
|
|
cmp eax, esi
|
|
mov esi, eax
|
|
je @F
|
|
|
|
cmp [eax+SMAP.magic], 'SMAP'
|
|
jne .next
|
|
|
|
mov edi, [eax+SMAP.parent]
|
|
test edi, edi
|
|
jz .next
|
|
|
|
lea edi, [edi+SMEM.name]
|
|
stdcall strncmp, [name], edi, 32
|
|
test eax, eax
|
|
jne .next
|
|
|
|
stdcall user_free, [esi+SMAP.base]
|
|
|
|
mov eax,esi
|
|
call [esi+APPOBJ.destroy]
|
|
@@:
|
|
popfd
|
|
pop edi
|
|
pop esi
|
|
.fail:
|
|
ret
|
|
endp
|
|
diff16 "heap code end ",0,$
|
|
diff16 "heap code size",init_kernel_heap,$
|