;this is internal procedure to be used with heap manager's mem.init.
;Don't call this procedure directly.

;; @name mem.alloc_heap
;; @desc
;;    This is internal procedure of heap manager, that handles
;;    platform-dependent aspect of allocating entire heap.
;;    Do not call this procedure.
;; @arg size
;;    Initial size of heap to allocate.
;; @ret
;;    CF set on error, otherwise
;;    EAX = pointer to allocated memory block
;; @err ERR_OUT_OF_MEM
;;     Not enough memory
;; @err ERR_ZERO_SIZE
;;     size = 0
;; @err ERR_OUT_OF_RANGE
;;     size is negative (or larger than 7FFFFFFFh if viewed as unsigned)
;; @err ERR_UNKNOWN
;;     System returned error that wasn't translated to FASMLIB error.
;;     You can {contact} author about this, and translation can be added.
;; @warn Don't call this procedure!
;; @note Returned pointer is always >= 10000h to make it easily distinguishable from handles.
;; @note This procedure is used only on platforms where FASM heap manager is used.
proc mem.alloc_heap, .size
begin
        push    ebx ecx

        ;error if size=0
        cmp     [.size], 0
        je      .error_size_zero

        ;error is size>=80000000h
        cmp     [.size], 70000000h
        ja      .error_size_too_big

        ;call brk(0) to find beginning of heap
        xor   ebx, ebx
        mov     eax, sys_brk
        int     80h
        cmp     eax, -4096
        ja      .error_brk
        mov     ecx, eax

        ;call brk(ecx+.size) to set up heap size
        mov     ebx, ecx
        add     ebx, [.size]
        mov     eax, sys_brk
        int     80h
        cmp     eax, -4096
        ja      .error_brk

        ;return address of heap
        mov     eax, ecx

.rnc:   clc
.r:     pop     ecx ebx
        return

.rc:    stc
        jmp     .r

.error_brk:

        ;catch out-of-memory
        cmp     eax, -12 ;ENOMEM
        jne     @f
        mov     eax, ERR_OUT_OF_MEM
        jmp     .rc
@@:
        mov     eax, ERR_UNKNOWN
        jmp     .rc

.error_size_zero:
        mov     eax, ERR_ZERO_SIZE
        jmp     .rc

.error_size_too_big:
        mov     eax, ERR_OUT_OF_RANGE
        jmp     .rc
endp




;internal procedure to be used with heap manager's mem.init.
;Don't call this procedure directly.

;; @name mem.realloc_heap
;; @desc
;;    This is internal procedure of heap manager, that handles
;;    platform-dependent aspect of resizing entire heap.
;;    Do not call this procedure.
;; @arg heapptr
;;    Pointer to heap block returned by {mem.alloc_heap} or by this procedure.
;; @arg oldsize
;;    Current size of heap. Must be provided by caller.
;; @arg newsize
;;    Desired size of heap.
;; @ret
;;    CF set on error, otherwise
;;    EAX = heapptr
;; @err ERR_INVALID_POINTER
;;    Heap pointer is invalid
;; @err ERR_OUT_OF_MEM
;;     Not enough memory
;; @err ERR_ZERO_SIZE
;;     newsize = 0
;; @err ERR_OUT_OF_RANGE
;;     size is negative (or larger than 7FFFFFFFh if viewed as unsigned)
;; @err ERR_UNKNOWN
;;     System returned error that wasn't translated to FASMLIB error.
;;     You can {contact} author about this, and translation can be added.
;; @warn Don't call this procedure!
;; @warn Heap cannot be moved during resizing.
;; @note Data in heap must be preserved.
;; @note If block is enlarging, then contents of added memory are unknown
proc mem.realloc_heap, .heapptr, .newsize, .oldsize
begin
        push    ebx

        ;call sys_brk(blockptr)
        mov     ebx, [.heapptr] ;pointer to block
        add     ebx, [.newsize]
        mov     eax, sys_brk        ;sys_brk
        int     80h

        ;check error
        cmp     eax, -4096
        ja      .error_brk

.rnc:   clc
.r:     pop     ebx
        return
.rc:    stc
        jmp     .r

.error_brk:
        ;catch invalid block pointer
        cmp     eax, -22 ;EINVAL
        jne     @f
        mov     eax, ERR_INVALID_POINTER
        jmp     .rc
@@:

        ;catch out-of-memory
        cmp     eax, -12 ;ENOMEM
        jne     @f
        mov     eax, ERR_OUT_OF_MEM
        jmp     .rc
@@:

        mov     eax, ERR_UNKNOWN
        jmp     .rc

.error_newsize_zero:
        mov     eax, ERR_ZERO_SIZE
        jmp     .rc

.error_newsize_too_big:
        mov     eax, ERR_OUT_OF_RANGE
        jmp     .rc
endp






;internal procedure to be used with heap manager's mem.init.
;Don't call this procedure directly.


;; @name mem.free_heap
;; @desc
;;    This is internal procedure of heap manager, that handles
;;    platform-dependent aspect of deallocating entire heap.
;;    Do not call this procedure.
;; @arg heapptr
;;    Pointer to heap, returned by {mem.alloc_heap} or {mem.realloc_heap}.
;; @arg heapsize
;;    Current size of heap. Must be provided by caller.
;; @err ERR_INVALID_POINTER
;;    Heap pointer is invalid
;; @err ERR_UNKNOWN
;;     System returned error that wasn't translated to FASMLIB error.
;;     You can {contact} author about this, and translation can be added.
proc mem.free_heap, .heapptr, .heapsize
begin
        push    ebx ecx

        ;call sys_brk(heapptr)
        mov     ebx, [.heapptr]  ;pointer to block
        mov     eax, sys_brk
        int     80h

        ;check error
        cmp     eax, -4096
        ja      .error_brk

        clc

.r:     pop     ecx ebx
        return

.error_brk:

        ;catch invalid block pointer
        cmp eax, -22 ;EINVAL
        jne @f
        mov eax, ERR_INVALID_POINTER
        stc
        jmp .r
@@:
        mov eax, ERR_UNKNOWN
        stc
        jmp     .r

endp



