News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Playing with memory allocations..

Started by K_F, July 21, 2015, 08:46:19 PM

Previous topic - Next topic

K_F

Here's a small memory block handler that I'm using,  that you might find useful and/or improve on.

I made it for my MDI modules that are constantly using and releasing small amounts of memory, so in order not to plague the system allocation..
Each module applies for the expected amount of memory from the local heap.. and this is then sub-managed by these procs and structures.

It currently works for me, with no problems yet... will probably improve on this towards the end of my project.

.Const

.Data?

.Data
;--- LOCAL MEMORY ALLOC CONTROL STRUCTURE ---
MemStruct Struct
MemHandle DD 0 ;Pointer to handle pointer
MemMapPtr DD 0 ;Mem/Handle pointer
MemMapSize DD 0 ;Size of buffer
Dummy DD 0 ;extra to round off 16 bytes
MemStruct Ends

;--- MAIN SYSTEM MEMORY ALLOCATION UNIT ---
my_MemoryMap Struct
MainHeap DD 0 ;Module Local heap handle
MainHeapSize DD 0 ;Module Memory block size

Mem_01 MemStruct <> ;Individual Memory slots
Mem_02 MemStruct <> ;Allocate as many as you want
Mem_03 MemStruct <>
Mem_04 MemStruct <>
Mem_05 MemStruct <>
Mem_06 MemStruct <>
Mem_07 MemStruct <>
Mem_08 MemStruct <>
Mem_09 MemStruct <>
Mem_10 MemStruct <>
Mem_11 MemStruct <>
Mem_12 MemStruct <>
Mem_13 MemStruct <>
Mem_14 MemStruct <>
Mem_15 MemStruct <>
Mem_16 MemStruct <>

MemFin DD 4 DUP (0FFFFFFFFh) ;EOL indicators
my_MemoryMap Ends

ErrorSTR DB 512 DUP(0)
.Code
;------------------------------------------------------------------------------
;INIT_MainHeap: Get MainHeap, and Base Pointers
;------------------------------------------------------------------------------
GET_MainHeap Proc hWnd:DWord

; Invoke GetProcessHeap ;
Invoke HeapCreate, NULL, NULL, NULL ;
Mov h_ProcessHeap, Eax ; This is an external var.
ret

GET_MainHeap EndP
;------------------------------------------------------------------------------
;Allocates memory from the main ProcessHeap for the calling MODULE
;This proc is used first to get a large memory block from the the system,
;which can then be subdivided ect.. for the MODULE needs.
;
;PARAMETERS: ptr_MemStuff -> MemStuff structure
;
;Requirements MemStuff.MainHeapSize must contain required memory size
;
;RETURNS: FALSE if :- 1)Windows HeapAlloc fails
; 2)MemStuff.MainHeapSize = 0
; MemStuff.MainHeap is also set to 0 on return
;
; TRUE if :- Windows HeapAlloc succeeds
; MemStuff.MainHeap contains local heap handle
; The rest of the MemStuff structure is zeroed
;------------------------------------------------------------------------------
FindLocalMemory Proc USES EDI ESI ptr_MemStuff:DWord

ASSUME ESI: PTR my_MemoryMap

mov esi, ptr_MemStuff ;ESI = my_MemoryMap pointer
mov eax, [esi].MainHeapSize ;Check for memory allocation
cmp eax, 0 ;
jne @F ;

FLM_Err_EX: ;Error and exit
mov [esi].MainHeap, eax ;clearing memory handle
Return FALSE ;flag it

@@:
Invoke HeapAlloc, h_ProcessHeap, HEAP_ZERO_MEMORY, eax ;Get mem
cmp eax, 0 ;
je FLM_Err_EX ;
mov [esi].MainHeap, eax ;copy handle (ptr)

lea edi, [esi].Mem_01 ;clear local memstructs
cld ;
mov ecx, 4 * 16 ;
xor eax, eax ;
rep stosd ;

mov eax, 0FFFFFFFFh ;Set End Of Struct indicators
mov ecx, 4 ;
rep stosd ;
Return TRUE ;

ASSUME ESI: NOTHING
FindLocalMemory Endp
;------------------------------------------------------------------------------
;Releases memory back to the main ProcessHeap for the calling MODULE
;
;PARAMETERS: ptr_MemStuff -> MemStuff structure
;
;Requirements MemStuff.MainHeap must contain local heap handle
;
;RETURNS: FALSE if :- 1)Windows HeapFree fails
; 2)MemStuff.MainHeap = 0
; MemStuff.MainHeap is NOT set to 0 on return
; The rest of the MemStuff structure is untouched
;
; TRUE if :- Windows HeapFree succeeds
; MemStuff.MainHeap is also set to 0 on return
; The rest of the MemStuff structure is zeroed
;------------------------------------------------------------------------------
LoseLocalMemory Proc ptr_MemStuff:DWord
ASSUME EDI: PTR my_MemoryMap

mov edi, ptr_MemStuff ;Get Mem handle
mov eax, [edi].MainHeap ;
cmp eax, 0 ;
jne @F ;

LLM_Err_EX: ;
Return FALSE ;It doesn't exist ??

@@:
Invoke HeapFree, h_ProcessHeap, HEAP_NO_SERIALIZE, eax ;Let it go
cmp eax, 0 ;
je LLM_Err_EX ;any errors in that ?

mov edi, ptr_MemStuff ;Clear local memstructs
cld ;
mov ecx, 4 * 16 + 2 ;
xor eax, eax ;
rep stosd ;

mov eax, 0FFFFFFFFh ;Set End Of Struct indicators
mov ecx, 4 ;
rep stosd ;

Return TRUE ;We're happy

ASSUME EDI: NOTHING
LoseLocalMemory Endp
;------------------------------------------------------------------------------
;Cycles through MemStruct slots in the my_MemoryMap structure, shifting memory
;up over empty slots.
;
;PARAMETERS: ptr_MemStuff -> MemStuff structure
;
;RETURNS: FALSE if :- my_MemoryMap.MainHeap == 0
;
; TRUE if :- not False
;
;NOTE: Shifted MemStructs have an allocated handle ptr which is
; updated, causing no problems :-) :-)...
;
;------------------------------------------------------------------------------
ShakeMemory Proc ptr_MemStuff:DWord
LOCAL ThatPtr:Dword
LOCAL ThisPtr:Dword

mov esi, ptr_MemStuff ;Struct ptr
mov eax, (my_MemoryMap PTR [esi]).MainHeap ;Local heap
cmp eax, 0 ;Valid
jne @F ;

SMM_Err_EX: ;LOCAL HEAP INVALID
Return FALSE ;

@@: ;
add esi, 8 ;Start of mem structs

SMLoop1: ;LOOP 1
mov ThatPtr, esi ;Current full structure
mov eax, [esi] ;MemStruct.MemHandle
cmp eax, 0FFFFFFFFh ;EOL
jne @F ;Nope

SM_Fin:
Return TRUE ;Klaar
@@:
cmp eax, 0 ;Blank mem spot
je SMLoop2 ;Yep
add esi, sizeof MemStruct ;No.. next one
jmp SMLoop1 ;Loopy

SMLoop2: ;BLANK MEM SPOT
mov ThisPtr, esi ;Next Full Structure ?
mov eax, [esi] ;MemStruct.MemHandle
cmp eax, 0FFFFFFFFh ;EOL
je SM_Fin ;Yes jump

cmp eax, 0 ;Blank Mem Spot
jne @F ;Nah.. found a mem spot
add esi, sizeof MemStruct ;Yes.. Next slot
jmp SMLoop2 ;Loopy

@@: ;MEM BLOCK TO MOVE
mov ebx, ThatPtr ;EBX => THAT Last full struct
mov edi, (MemStruct PTR[ebx]).MemMapPtr ;Calc next mem location
add edi, (MemStruct PTR[ebx]).MemMapSize ;
add edi, 8 ;Add a bit extra

add ebx, sizeof MemStruct ;THAT+16 Struct to save in
mov (MemStruct PTR[ebx]).MemMapPtr, edi ;NewMem ptr
push edi ;Save it

mov edx, ThisPtr ;EDX => THIS Struct to be moved
mov esi, (MemStruct PTR[edx]).MemMapPtr ;Source ptr
mov ecx, (MemStruct PTR[edx]).MemMapSize ;Size of buffer
mov (MemStruct PTR[ebx]).MemMapSize, ecx ;NewMem size

shr ecx,2 ;Adjust for DD
cld ;upwards
rep movsd ;MEM MOVE

mov eax, (MemStruct PTR[edx]).MemHandle ;Handle Ptr
mov (MemStruct PTR[ebx]).MemHandle, eax ;
pop edi ;NewMem ptr restored
mov [eax], edi ;

xor eax, eax ;Zero THIS structure
mov (MemStruct PTR[edx]).MemHandle, eax ;
mov (MemStruct PTR[edx]).MemMapPtr, eax ;
mov (MemStruct PTR[edx]).MemMapSize, eax ;
mov (MemStruct PTR[edx]).Dummy, eax ;

mov esi, ebx ;Recently(THAT+16) filled structure
jmp SMLoop1 ;check it anyway

ret
ShakeMemory Endp
;------------------------------------------------------------------------------
;Call ShakeMemory before this proc.
;
;Searches my_MemoryMap structure for an empty slot, check memory limit and then
;allocates memory.
;
;------------------------------------------------------------------------------
GetLocalMemory Proc ptr_MemStuff:DWord, ptr_Handle:Dword, iMemSize:Dword, i_IDTag:Dword
LOCAL MemLimit:Dword
LOCAL ThatPtr:Dword
LOCAL ThisPtr:Dword

mov esi, ptr_MemStuff ;Struct ptr
mov eax, [esi] ;my_MemoryMap.MainHeap
cmp eax, 0 ;Valid
jne @F ;

GLM_Err_EX: ;LOCAL HEAP INVALID
Return FALSE ;

@@:
add eax, DWORD PTR [esi+4] ;my_MemoryMap.MainHeapSize
mov MemLimit, eax ;Memlimit

add esi, 8
mov ThatPtr, esi ;First slot ptr

GLM_Loop1: ;Find a blank slot
mov ThisPtr, esi ;This slot ptr
mov eax, [esi] ;MemStruct.MemHandle = ?
cmp eax, 0FFFFFFFFh ;EOL
jne @F ;No
jmp GLM_Err_EX ;Yes - flag fail

@@:
cmp eax, 0 ;blank = 0
je @F ;Yesss
mov ThatPtr, esi ;Last slot ptr
add esi, 16 ;No next MemStruct block
jmp GLM_Loop1 ;loopy

@@: ;First allocation special condition
cmp esi, ThatPtr ;
jne @F ;


;--- SPECIAL CASE WHERE FIRST SLOT IS EMPTY ----
mov eax, iMemSize ;check requested for overflow
cmp eax, MemLimit ;
jg GLM_Err_EX ;OVERFLOW

add eax, 8 ;Add teeny weeny
mov [esi+8], eax ;MemMapSize
mov eax, [esi-8] ;
mov [esi+4], eax ;MemMapPtr
mov ebx, ptr_Handle ;pointer to memory handle
mov [esi], ebx ;save as ptr-ptr
mov [ebx], eax ;Handle = MemMapPtr
mov eax, i_IDTag ;
mov [esi+12], eax ;
Return TRUE

@@: ;CALC START OF NEW blcok
mov esi, ThatPtr ;Get previous block
mov eax, [esi+4] ;THAT.MemMapPtr
add eax, [esi+8] ;add THAT.MemMapSize

;---CHECK MEM LIMIT ---
mov ebx, eax ;
add eax, iMemSize ;
cmp eax, MemLimit ;
jg GLM_Err_EX ;OVERFLOW

;--- NEW BLOCK ---
mov eax, ebx ;
mov esi, ThisPtr ;
mov [esi+4], eax ;THIS.MemMapPtr
push eax

add eax, iMemSize ;Add requested
add eax, 8 ;Add a tenny weeeny bit
mov [esi+8], eax ;THIS.MemMapSize

mov ebx, ptr_Handle ;pointer to memory handle
mov [esi], ebx ;save as ptr-ptr
pop eax
mov [ebx], eax ;Handle = MemMapPtr
mov eax, i_IDTag ;
mov [esi+12], eax ;

Return TRUE
GetLocalMemory Endp
;------------------------------------------------------------------------------
;ClearLocalMemory: Searches my_MemoryMap structure for ptr_Handle, then zeroes
; that MemStruct, effectively deallocating the mem block.
;
;------------------------------------------------------------------------------
ClearLocalMemory Proc ptr_MemStuff:DWord, ptr_Handle:Dword

mov edi, ptr_MemStuff ;Struct ptr
mov eax, (my_MemoryMap PTR [edi]).MainHeap ;Local heap
cmp eax, 0 ;Valid
jne @F ;

CLM_Err_EX: ;LOCAL HEAP INVALID
Return FALSE ;

@@:
add esi, 8 ;First block

CLM_Loop1:
mov eax, [edi] ;Check Handle pointer
cmp eax, 0FFFFFFFFh ;EOL
je CLM_Err_EX ;Yes - flag fail

cmp eax, ptr_Handle ;Is it?
je @F ;Yeah
add edi, 16 ;nooooo
jmp CLM_Loop1 ;loopy
@@:
mov ecx, 4 ;
xor eax, eax ;Clear MemStruct
cld ;
rep stosd ;
Return TRUE ;

ClearLocalMemory Endp
;------------------------------------------------------------------------------
;FlushLocalMemory: Deallocates all MemStruct blocks containing the i_IDTag,
; then shakes the memory tree.
;------------------------------------------------------------------------------
FlushLocalMemory Proc ptr_MemStuff:DWord, i_IDTag:Dword

mov edi, ptr_MemStuff ;Memmap
mov esi, edi ;Save for later
add edi, 8 ;Memstruct
mov ecx, 16 ;16 slots

FLM_Loop: ;
mov eax, [edi+12] ;Get IDTag
cmp eax, i_IDTag ;compare
jne @F ;no - next

;--- TAG MATCH ---
xor eax, eax ;Zero memstruct
mov [edi],eax ;
mov [edi+4],eax ;
mov [edi+8],eax ;
mov [edi+12],eax ;

@@: ;
add edi, 16 ;Next slot
loop FLM_Loop ;again
Invoke ShakeMemory, esi ;shake it
ret ;

FlushLocalMemory Endp
'Sire, Sire!... the peasants are Revolting !!!'
'Yes, they are.. aren't they....'

hutch--

Hi Van,

This looks like the right way to manage a collection of known memory blocks. A single allocation that is divided into blocks that are in turn managed by the application (in this instance an MDI app).

K_F

Hutch.. what is the format (tabs.. spaces..ect) for the Code html sections..?

I'm using EasyCode with Tabs = 4 spaces.. but it comes out unaligned here.. can one set the Code section formats - me being 'HTML challenged'  :badgrin:
'Sire, Sire!... the peasants are Revolting !!!'
'Yes, they are.. aren't they....'