Memory allocation: Difference between revisions

Content added Content deleted
No edit summary
Line 1,524: Line 1,524:
* Using <code>string repeat</code> or <code>lrepeat</code> to make a group of entities that work like a block of memory (despite not being); these need marshalling code to bridge to foreign function interfaces.
* Using <code>string repeat</code> or <code>lrepeat</code> to make a group of entities that work like a block of memory (despite not being); these need marshalling code to bridge to foreign function interfaces.
* Using [[:Category:SWIG|SWIG]] or [[:Category:critcl|critcl]] to write a bridge to a standard [[C]] allocator.
* Using [[:Category:SWIG|SWIG]] or [[:Category:critcl|critcl]] to write a bridge to a standard [[C]] allocator.

=={{header|X86 Assembly}}==
This is a bare-bones implementation of a heap memory allocator for x86_64 Linux. We alloctate memory page at a time using brk and divide up the memory in chunks of requested size using a linked list-like block struct. Not optimized for speed or efficiency.

<lang x86asm>
; linux x86_64

struc block
free: resb 1 ; whether or not this block is free
size: resb 2 ; size of the chunk of memory
next: resb 8 ; the next chunk after this one
mem:
endstruc

section .data
hStart: dq 0 ; the beginning of our heap space
break: dq 0 ; the current end of our heap space


section .text

Allocate:

push rdi ; save the size argument

cmp qword [break], 0 ; if breakpoint is zero this
je firstAlloc ; is the first call to allocate

mov rdi, qword [hStart] ; else address of heap start

findBlock: ; look for a suitable block of memory

cmp byte [rdi + free], 2
je newBlock ; end of heap reached, create new block

cmp byte [rdi + free], 0
je skipBlock ; this block taken

; this block is free, make
; sure it's big enough
mov bx, word [rdi + size]
mov rcx, qword [rsp] ; compare against our size arg
cmp cx, bx
jg skipBlock ; keep looking if not big enough

mov byte [rdi + free], 0 ; else mark as taken
add rdi, mem
add rsp, 8 ; discard size arg, we didn't need it
mov rax, rdi ; return pointer to this block
ret

skipBlock:
mov rsi, qword [rdi + next] ; load next
mov rdi, rsi ' block address
jmp findBlock

newBlock:
mov rax, rdi
add rdi, 1024
cmp rdi, qword [break]
jl initAndAllocate
push rax
mov rdi, qword [break] ; if we are getting low on
add rdi, 4096 ; heap space, we ask OS for
mov rax, 12 ; more memory with brk syscall
syscall
cmp rax, qword [break] ; if breakpoint has not increased,
je allocFail ; then memory could not be allocated
mov qword [break], rax
pop rax
jmp initAndAllocate

firstAlloc: ; extra work has to be done on first
mov rax, 12 ; call to this subroutine
mov rdi, 0
syscall
mov qword [hStart], rax ; init heap start
add rax, 4096
mov rdi, rax
mov rax, 12 ; get heap memory with sys brk
syscall
cmp rax, qword [hStart]
je allocFail
mov qword [break], rax
mov rax, qword [hStart]

initAndAllocate:
mov byte [rax + free], 0 ; mark block free
pop rdi ; pop size arg off stack
mov word [rax + size], di ; mark it's size
lea rsi, [rax + mem + rdi]
mov byte [rsi + free], 2 ; mark heap end block
mov qword [rax + next], rsi ; mark next block
add rax, mem ; return pointer to block's memory space
ret

allocFail: ; exit(1) when allocation fails
mov rax, 60
mov rdi, 1
syscall
ret

; free this block so it can be
; reused in a subsequent call to allocate
Release:
sub rdi, mem
mov byte [rdi + free], 1
ret

</lang>


=={{header|XPL0}}==
=={{header|XPL0}}==