07-09-2022, 06:01 PM
The next challenger is the Dynamic Memory Manager:
Code: (Select All)
' mem64_FAR_DYNAMIC memory manager
/'
(uses a custom "links" based memory manager)
'/
' &HA000 DBLOCK SIZE DBLOCK OFFSET
' 655360 - (65536 + 1280 )=588544 links possible
' links limited to 588544/4=147136 (do not have enough links if avg. block size less than 4 bytes)
' stores blocks, not free memory, because blocks are easier to identify
' always scanned from beginning to end, so prev. pointer is unnecessary
proc SYSTEM_BUS_T.mem64_dynamic_malloc(size as uinteger) as SYSTEM_TYPE ptr
static as integer i
static as SYSTEM_TYPE ptr top
static as mem64_dynamic_link_type ptr link
static as mem64_dynamic_link_type ptr newlink
static as mem64_dynamic_link_type ptr prev_link
if (size > 65536) then
error(505) '>64K
end if
' to avoid mismatches between offsets, all 0-byte blocks are given the special offset A000h (the top of the heap)
if (size) then
' forces blocks to be multiples of 16 bytes so they align with segment boundaries
if (size and 15) then
size = size - (size and 15) + 16
end if
else
return (@mem64(0) + 655360) ' top of heap
end if
' is a space large enough between existing blocks available?
' (if not, memory will be allocated at bottom of heap)
top = @mem64(0) + 655360 ' top is the base of the higher block
prev_link = 0
if (link = mem64_dynamic_link_first) then
mem64_dynamic_findspace:
if ((top - link->top) >= size) then ' gpf
' found free space
goto mem64_dynamic_make_new_link
end if
prev_link = link
top = link->offset ' set top to the base of current block for future comparisons
if (link = link->next_ptr) then
goto mem64_dynamic_findspace
end if
end if
' no space between existing blocks is large enough, alloc below 'top'
if ((top - mem64_static_pointer) < size) then
error(506) ' a large enough block cannot be created!
end if
mem64_dynamic_base = top - size
' get a new link index
mem64_dynamic_make_new_link:
if (mem64_dynamic_free_link) then
mem64_dynamic_free_link = mem64_dynamic_free_link - 1
i = mem64_dynamic_free_list(mem64_dynamic_free_link)
else
mem64_dynamic_next_link = mem64_dynamic_next_link + 1
i = mem64_dynamic_next_link
if (i >= 147136) then
error(507) ' not enough blocks
end if
end if
newlink = peek(mem64_dynamic_link_type ptr,@mem64_dynamic_link(i))
' set link info
newlink->i = i
newlink->offset = top - size
newlink->size = size
newlink->top = top
' attach below prev_link
if (prev_link) then
newlink->next_ptr = prev_link->next_ptr ' NULL if none
prev_link->next_ptr = newlink
else
newlink->next_ptr = mem64_dynamic_link_first ' NULL if none
mem64_dynamic_link_first = newlink'
end if
return newlink->offset
end proc
def SYSTEM_BUS_T.mem64_dynamic_free(block as SYSTEM_TYPE ptr)
static as mem64_dynamic_link_type ptr link
static as mem64_dynamic_link_type ptr prev_link
if (mem64_dynamic_link_first) then
if (block) then
if (block = (@mem64(0) + 655360)) then
return ' to avoid mismatches between offsets, all 0-byte blocks are given the special offset A000h
' (the top of the heap)
end if
else
return
end if
else
return
end if
prev_link = 0
link = mem64_dynamic_link_first
check_next:
if (link->offset = block) then
' unlink
if (prev_link) then
prev_link->next_ptr = link->next_ptr
else
mem64_dynamic_link_first = link->next_ptr
end if
' free link
mem64_dynamic_free_link = mem64_dynamic_free_link + 1
mem64_dynamic_free_list(mem64_dynamic_free_link) = link->i
' memory freed successfully!
return
end if
prev_link = link
if (link = link->next_ptr) then
goto check_next
end if
return
end def
def SYSTEM_BUS_T.sub_defseg(segment as integer, passed as integer)
if (new_error) then
return
end if
if (passed) then
if ((segment < -65536) or (segment > 65535)) then ' same range as QB checks
error(6)
else
defseg = @mem64(0) + (peek(ushort,segment)) * 16
end if
else
defseg = @mem64(1280)
return
end if
end def
proc SYSTEM_BUS_T.func_peek(offset as integer) as integer
if ((offset < -65536) or (offset > 65535)) then ' same range as QB checks
error(6)
return 0
end if
return defseg[peek(ushort,@offset)]
'return defseg[(uint16)offset];
end proc
def SYSTEM_BUS_T.sub_poke(offset as integer, value as integer)
if (new_error) then
return
end if
if ((offset < -65536) or (offset > 65535)) then ' // same range as QB checks
error(6)
return
end if
defseg[peek(ushort,@offset)] = value
end def
def SYSTEM_BUS_T.more_return_points()
if (return_points > 2147483647) then
error(256)
end if
return_points *= 2
return_point = peek(uinteger ptr,realloc(return_point, return_points * 4))
if (return_point = 0) then
error(256)
end if
end def
proc SYSTEM_BUS_T.qbs_new_descriptor() as qbs ptr
' MLP //qbshlp1++;
if (qbs_malloc_freed_num) then
/' MLP
static as qbs ptr s
s=(qbs*)memset((void *)qbs_malloc_freed[--qbs_malloc_freed_num],0,sizeof(qbs));
s->dbgl=dbgline;
return s;
'/
qbs_malloc_freed_num -= 1
return memset(@qbs_malloc_freed[qbs_malloc_freed_num], 0, sizeof(qbs))
end if
if (qbs_malloc_next = 65536) then
qbs_malloc = calloc(sizeof(qbs) * 65536, 1) ' ~1MEG
qbs_malloc_next = 0
end if
/' MLP
dbglist[dbglisti]=(uint32)&qbs_malloc[qbs_malloc_next];
static qbs* s;
s=(qbs*)&qbs_malloc[qbs_malloc_next++];
s->dbgl=dbgline;
dbglisti++;
return s;
'/
qbs_malloc_next += 1
return @qbs_malloc[qbs_malloc_next]
end proc
def SYSTEM_BUS_T.qbs_free_descriptor(str_data as qbs ptr)
' MLP //qbshlp1--;
if (qbs_malloc_freed_num = qbs_malloc_freed_size) then
qbs_malloc_freed_size *= 2
qbs_malloc_freed = realloc(qbs_malloc_freed, qbs_malloc_freed_size * ptrsz)
if (qbs_malloc_freed) then
else
error(508)
end if
end if
qbs_malloc_freed[qbs_malloc_freed_num] = cast(ptrszint,str_data)
qbs_malloc_freed_num += 1
return
end def