kolibrios/kernel/branches/Kolibri-acpi/core/test_malloc.asm

250 lines
5.9 KiB
NASM
Raw Permalink Normal View History

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2009-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Tests of malloc()/free() from the kernel heap.
; This file is not included in the kernel, it is just test application.
use32
db 'MENUET01'
dd 1, start, i_end, mem, mem, 0, 0
start:
; Zero-initialize uglobals (as in kernel at boot)
mov ecx, (zeroend - zerostart + 3) / 4
xor eax, eax
mov edi, zerostart
rep stosd
; Initialize small heap (as in kernel at boot)
call init_malloc
; Run tests
call run_test1
call run_test2
call run_test3
; All is OK, return
or eax, -1
int 0x40
run_test1:
; basic test
mov eax, 1
call malloc_with_test
mov byte [eax], 0xDD
mov esi, eax
mov eax, 1
call malloc_with_test
cmp byte [esi], 0xDD
jnz memory_destroyed
mov byte [eax], 0xEE
xchg eax, esi
call free
cmp byte [esi], 0xEE
jnz memory_destroyed
xchg eax, esi
call free
ret
run_test2:
ret
run_test3:
; 1024 times run random operation.
; Randomly select malloc(random size from 1 to 1023)
; or free(random of previously allocated areas)
mov edi, 0x12345678
xor esi, esi ; 0 areas allocated
mov ebx, 1024
.loop:
imul edi, 1103515245
add edi, 12345
mov eax, edi
shr eax, 16
test ebx, 64
jz .prefer_free
.prefer_malloc:
test eax, 3
jz .free
jmp @f
.prefer_free:
test eax, 3
jnz .free
@@:
shr eax, 2
and eax, 1023
jz .loop
push ebx
push eax
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8], eax
push edi
call malloc_with_test
pop ecx
cmp ecx, edi
jnz edi_destroyed
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8+4], eax
; inc [saved_state_num]
pop ecx
pop ebx
inc esi
push ecx eax
push edi
mov edi, eax
mov eax, esi
rep stosb
pop edi
jmp .common
.free:
test esi, esi
jz .loop
xor edx, edx
div esi
sub edx, esi
neg edx
dec edx
mov eax, [esp+edx*8]
; mov ecx, [saved_state_num]
; mov [saved_state+ecx*8], -1
; mov [saved_state+ecx*8+4], eax
; inc [saved_state_num]
mov ecx, [esp+edx*8+4]
push edi eax
mov edi, eax
mov al, [edi]
repz scasb
jnz memory_destroyed
pop eax edi
push ebx edx
push edi
call free
pop ecx
cmp ecx, edi
jnz edi_destroyed
pop edx ebx
dec esi
pop eax ecx
push edi
lea edi, [esp+4]
@@:
dec edx
js @f
xchg eax, [edi]
xchg ecx, [edi+4]
add edi, 8
jmp @b
@@:
pop edi
.common:
dec ebx
jnz .loop
@@:
dec esi
js @f
pop eax ecx
call free
jmp @b
@@:
ret
malloc_with_test:
; calls malloc() and checks returned value
call malloc
test eax, eax
jz generic_malloc_fail
call check_mutex
call check_range
ret
; Stubs for kernel procedures used by heap code
mutex_init:
and dword [ecx], 0
ret
mutex_lock:
inc dword [ecx]
ret
mutex_unlock:
dec dword [ecx]
ret
kernel_alloc:
cmp dword [esp+4], bufsize
jnz error1
mov eax, buffer
ret 4
macro $Revision [args]
{
}
; Error handlers
error1:
mov eax, 1
jmp error_with_code
generic_malloc_fail:
mov eax, 2
jmp error_with_code
check_mutex:
cmp dword [mst.mutex], 0
jnz @f
ret
@@:
mov eax, 3
jmp error_with_code
check_range:
cmp eax, buffer
jb @f
cmp eax, buffer+bufsize
jae @f
ret
@@:
mov eax, 4
jmp error_with_code
memory_destroyed:
mov eax, 5
jmp error_with_code
edi_destroyed:
mov eax, 6
jmp error_with_code
error_with_code:
mov edx, saved_state_num
; eax = error code
; 1 signals error in testing code (wrong bufsize)
; 2 = malloc() returned NULL
; 3 = mutex not released
; 4 = weird returned value from malloc()
; 5 = memory destroyed by malloc() or free()
int3 ; simplest way to report error
jmp $-1 ; just in case
; Include main heap code
include '../proc32.inc'
include '../struct.inc'
include '../const.inc'
include 'malloc.inc'
i_end:
align 4
zerostart:
mst MEM_STATE
align 16
bufsize = 0x40000 ; change if malloc.inc changes
buffer rb bufsize
zeroend:
saved_state_num dd ?
saved_state rd 0x10000
align 4
rb 0x10000 ; for stack
mem: