home *** CD-ROM | disk | FTP | other *** search
- opt l+,o+,ow-
-
- *-- AutoRev header do NOT edit!
- *
- * Program : memfunc.s
- * Copyright : © 1991 Jaba Development
- * Author : Jan van den Baard
- * Creation Date : 06-Apr-91
- * Current version : 2.1
- * Translator : Devpac version 2.14
- *
- * REVISION HISTORY
- *
- * Date Version Comment
- * --------- ------- ------------------------------------------
- * 19-May-91 2.1 Added 'Vec' routines.
- * 06-Apr-91 1.1 Initial version!
- *
- *-- REV_END --*
-
- incdir 'sys:Devpac_INC/'
- include 'mymacros.i'
- include 'libraries/nofrag.i'
- include 'exec/exec_lib.i'
-
- xdef GetMemoryChain
- xdef AllocItem
- xdef FreeItem
- xdef FreeMemoryChain
- xdef AllocVecItem
- xdef FreeVecItem
-
- ROUND MACRO
- addq.l #7,\1
- and.l #-8,\1
- ENDM
-
- ;
- ; Allocate and initialize a MemoryChain for use. It allocates the structure
- ; from the system free memory pool and then initializes it.
- ;
- GetMemoryChain:
- pushem.l d2/a2/a6
- move.l d0,d2 ; block size to d2
- move.l (_SysBase).w,a6
- moveq #mc_SIZEOF,d0
- move.l #MEMF_PUBLIC!MEMF_CLEAR,d1
- libcall AllocMem ; allocate chain structure
- move.l d0,a2 ; put it in a2
- beq.s NoChain ; FAILED !?!?!
- lea.l mc_Blocks(a2),a0
- NEWLIST a0 ; initialize block list
- lea.l mc_Items(a2),a0
- NEWLIST a0 ; initialize item list
- ROUND d2 ; allign the block size
- move.l d2,mc_BlockSize(a2) ; put it in the structure
- move.l a2,d0
- NoChain: popem.l d2/a2/a6
- rts
-
- ;
- ; Deallocate a block of memory. It removes all "Free Items" from the
- ; chain it's "Free Item List" and then deallocates the memory the
- ; block used.
- ;
- FreeBlock: pushem.l a2-a3/a5-a6
- move.l a0,a2 ; chain to a2
- move.l a1,a3 ; block to a3
- lea.l mc_Items(a2),a5
- move.l il_First(a5),a5 ; first item in a5
- FBLoop: tst.l mit_Next(a5) ; is there a next item ?
- beq.s FBDone ; no.. done
- cmp.l mit_Block(a5),a3 ; item in the block ?
- bne.s FBNotSame ; no.. get next item
- move.l a5,a1
- REMOVE ; remove item from the list
- lea.l mc_Items(a2),a5
- move.l il_First(a5),a5
- bra.s FBLoop ; start from the begin
- FBNotSame: move.l mit_Next(a5),a5
- bra.s FBLoop ; try the next item
- FBDone: move.l a3,a1
- REMOVE ; remove block from the list
- move.l (_SysBase).w,a6
- move.l a3,a1
- move.l mc_BlockSize(a2),d0
- add.l #mb_SIZEOF,d0
- libcall FreeMem ; free the block's memory
- popem.l a2-a3/a5-a6
- rts
-
- ;
- ; Allocate a block of memory for a chain. This routine allocates enough
- ; memory from the system free memory pool to hold the MemoryBlock
- ; structure and the number of bytes specified with GetMemoryChain().
- ; Then it initializes the MemoryBlock structure and creates one "Free Item"
- ; the size of the whole block. Then it hangs this item in the chain it's
- ; "Free Item List"
- ;
- AllocBlock: pushem.l d2/a2-a3/a5-a6
- move.l a0,a2 ; chain to a2
- move.l d0,d2 ; reqs to d2
- move.l d2,d1
- move.l mc_BlockSize(a2),d0
- add.l #mb_SIZEOF,d0 ; add room for Block structure
- move.l (_SysBase).w,a6
- libcall AllocMem ; allocate the memory
- move.l d0,a3 ; put it in a3
- beq.s ABNoMem ; FAILED !?!?!
- move.l d2,mb_Requirements(a3) ; set block reqs
- clr.l mb_BytesUsed(a3) ; clear bytes used counter
- lea.l mc_Blocks(a2),a0
- move.l a3,a1
- ADDHEAD ; add block in the list
- move.l a3,a5
- add.l #mb_SIZEOF,a5 ; get first item in a5
- move.l a3,mit_Block(a5) ; set it's block
- move.l mc_BlockSize(a2),mit_Size(a5) ; set it's size
- lea.l mc_Items(a2),a0
- move.l a5,a1
- ADDHEAD ; add item in the list
- move.l a3,d0 ; return the block
- ABEnd: popem.l d2/a2-a3/a5-a6
- rts
- ABNoMem: cldat d0 ; alloc failed.. return 0
- bra.s ABEnd
-
- ;
- ; This routine optimizes a MemoryBlock. It looks up all "Free Items"
- ; located in the block and hangs them in a seperate list. Then it starts
- ; to look for items that are located directly after eachother in memory.
- ; If it find such items it will merge them together into on bigger item.
- ; It continues to do this until it doesn't find items located after each-
- ; other anymore. This will prevent the fragmentizing in the memory chain
- ; itself.
- ;
- OptimizeBlock:
- link a6,#-il_SIZEOF ; create stack space
- pushem.l d2/a2-a6
- move.l a0,a2 ; chain to a2
- move.l a1,a3 ; block to a3
- lea.l -il_SIZEOF(a6),a0
- NEWLIST a0 ; init buffer list
- lea.l mc_Items(a2),a4
- move.l il_First(a4),a4 ; first item to a4
- OBLoop1: tst.l mit_Next(a4) ; is there a next item ?
- beq.s OBDone1 ; no.. done
- cmp.l mit_Block(a4),a3 ; item in the block ?
- bne.s OBNotSame1 ; no.. skip it
- move.l a4,a1
- REMOVE ; remove item
- lea.l -il_SIZEOF(a6),a0
- move.l a4,a1
- ADDTAIL ; put item in buffer list
- lea.l mc_Items(a2),a4
- move.l il_First(a4),a4
- bra.s OBLoop1 ; start from the begin
- OBNotSame1: move.l mit_Next(a4),a4
- bra.s OBLoop1 ; try the next item
- OBDone1: lea.l -il_SIZEOF(a6),a0
- move.l il_First(a0),a4 ; first buffer item in a4
- OBLoop2: tst.l mit_Next(a4) ; is there a next item ?
- beq.s OBDone2 ; no.. done
- move.l a4,d2
- add.l mit_Size(a4),d2 ; addres behind item to d2
- move.l a4,a5
- OBLoop3: tst.l mit_Next(a5) ; is there a next item ?
- beq.s OBDone3 ; no.. done
- cmp.l d2,a5 ; d2 is a5 ?
- bne.s OBNotSame2 ; no.. skip it
- move.l mit_Size(a5),d0
- add.l d0,mit_Size(a4) ; join a4 with a5
- add.l d0,d2
- move.l a5,a1
- REMOVE ; remove a5 from the list
- lea.l -il_SIZEOF(a6),a0
- move.l il_First(a0),a5
- bra.s OBLoop3 ; start from the begin
- OBNotSame2: move.l mit_Next(a5),a5
- bra.s OBLoop3 ; try the next item
- OBDone3: move.l mit_Next(a4),a4
- bra.s OBLoop2 ; try the next item
- OBDone2: lea.l -il_SIZEOF(a6),a0
- REMHEAD ; remove item from the buffer
- tst.l d0 ; is it 0 ?
- beq.s NoMore ; yes.. all done
- move.l d0,a1
- lea.l mc_Items(a2),a0
- ADDHEAD ; add it to the list
- bra.s OBDone2
- NoMore: popem.l d2/a2-a6
- unlk a6
- rts
-
- ;
- ; This routines looks through the "Free Item List" of the chain to find
- ; a "Free Item" that meets the requested size and requirements.
- ;
- FindSpace: pushem.l d2-d3/a2-a3
- move.l a0,a2 ; chain to a2
- move.l d0,d2 ; size to d2
- move.l d1,d3 ; reqs to d3
- lea.l mc_Items(a2),a3
- move.l il_First(a3),a3 ; first item to a3
- FSLoop: tst.l mit_Next(a3) ; is there a next item ?
- beq.s FSDone ; no.. done
- move.l mit_Block(a3),a0
- cmp.l mb_Requirements(a0),d3 ; requirements OK ?
- bne.s FSNotSame ; no.. skip it
- cmp.l mit_Size(a3),d2 ; size OK ?
- bhi.s FSNotSame ; no.. skip it
- move.l a3,d0 ; return the item
- bra.s FSEnd
- FSNotSame: move.l mit_Next(a3),a3
- bra.s FSLoop ; try the next item
- FSDone: cldat d0 ; no item found
- FSEnd: popem.l d2-d3/a2-a3
- rts
-
- ;
- ; Allocate memory from a chain. This routine uses FindSpace() to find a
- ; suitable "Free Item" in the chain. If it does not find such an item it
- ; will allocate a new MemoryBlock.
- ;
- AllocItem: pushem.l d2-d4/a2-a5
- move.l a0,a2 ; chain to a2
- move.l d0,d2 ; size to d2
- move.l d1,d3 ; reqs to d3
- bclr.l #16,d3 ; clear MEMF_CLEAR bit
- bclr.l #17,d3 ; clear MEMF_LARGEST bit
- cmp.l #mit_SIZEOF,D2 ; size > mit_SIZEOF ?
- bhi.s ASOK ; yes.. ok
- move.l #mit_SIZEOF,d2 ; else make it that big
- ASOK: ROUND d2 ; allign the size
- cmp.l mc_BlockSize(a2),d2
- bhi.s NoMem
- move.l d3,d1
- move.l d2,d0
- move.l a2,a0
- bsr FindSpace ; find a suitable item
- move.l d0,a4 ; put it in a4
- bne.s HaveSpace ; found one..
- move.l d3,d0
- move.l a2,a0
- bsr AllocBlock ; allocate a block
- move.l d0,a4 ; put it in a4
- beq NoMem ; no more memory (wheeee)
- add.l #mb_SIZEOF,a4 ; get first item
- ;
- ; NOTE: This routine will split up the item if the size left
- ; is big enough to hold a "MemoryItem" structure. If not it won't
- ; split the item up the size left will not be used again. This means
- ; that after a chain has been used for some time to (de)allocate items
- ; in it is possible that not all bytes of a block can be used.
- ;
- HaveSpace: move.l mit_Block(a4),a3 ; get block in a3
- cmp.l mit_Size(a4),d2 ; size equals item size ?
- beq.s NoSplit ; yes.. don't split it
- move.l mit_Size(a4),d4
- sub.l d2,d4
- cmp.l #mit_SIZEOF,d4 ; size left < mit_SIZEOF ?
- bcs.s NoSplit ; yes.. don't split it
- move.l a4,a5
- add.l d2,a5 ; new item in a5
- move.l d4,mit_Size(a5) ; set new item size
- move.l a3,mit_Block(a5) ; set new item block
- lea.l mc_Items(a2),a0
- move.l a5,a1
- ADDHEAD ; add it in the list
- NoSplit: move.l a4,a1
- REMOVE ; remove it from the list
- move.l a4,a0
- move.l d2,d0
- bsr ClearAlloc ; clear memory
- add.l d2,mb_BytesUsed(a3) ; increase bytes used counter
- move.l a4,d0 ; return the pointer
- AIEnd: popem.l d2-d4/a2-a5
- rts
- NoMem: cldat d0 ; no memory.. return 0
- bra.s AIEnd
-
- ;
- ; Free memory in a MemoryChain. This routine takes the pointer it has
- ; been passed and check to see what block it was allocated in. Then it
- ; will convert the memory pointed to in a "Free Item" and hang it in the
- ; "Free Item List" of the chain. If the MemoryBlock is empty after this
- ; the routine will deallocate the block.
- ;
- FreeItem: pushem.l d2/a2-a4
- move.l a0,a2 ; chain to a2
- move.l a1,a3 ; memptr to a3
- move.l d0,d2 ; size to d2
- cmp.l #mit_SIZEOF,d2 ; size > mit_SIZEOF ?
- bhi.s FSOK ; yes.. ok
- move.l #mit_SIZEOF,d2 ; else make it that big
- FSOK: ROUND d2 ; allign the size
- bsr FindBlock ; find it's block
- move.l d0,a4 ; and put it in a4
- beq FRDone ; block 0.. don't free
- move.l a4,mit_Block(a3) ; set item block
- move.l d2,mit_Size(a3) ; set item size
- sub.l d2,mb_BytesUsed(a4) ; decrease bytes used count
- move.l a3,a1
- lea.l mc_Items(a2),a0
- ADDHEAD ; add item in the list
- tst.l mb_BytesUsed(a4)
- bne.s FROpt ; block not free
- move.l mit_Block(a3),a1
- move.l a2,a0
- bsr FreeBlock ; free the block
- bra.s FRDone
- FROpt: move.l a2,a0
- move.l a4,a1
- bsr OptimizeBlock ; optimize the block
- FRDone: popem.l d2/a2-a4
- rts
-
- ;
- ; This routine looks for the block in which memory was allocated.
- ;
- FindBlock: push.l a2
- lea.l mc_Blocks(a0),a2
- move.l bl_First(a2),a2 ; first block to a2
- FBBLoop: tst.l mb_Next(a2) ; is there a next block ?
- beq.s FBBDone ; no.. done
- move.l a2,d0
- cmp.l d0,a1 ; memptr < block start ?
- bmi.s FBBNotSame ; yes.. skip it
- add.l #mb_SIZEOF,d0
- add.l mc_BlockSize(a0),d0
- cmp.l d0,a1 ; memptr > block end ?
- bhi.s FBBNotSame ; yes.. skip it
- move.l a2,d0 ; return block
- bra.s EndFBB
- FBBNotSame: move.l mb_Next(a2),a2
- bra.s FBBLoop ; try the next block
- FBBDone: cldat d0 ; block not found.. return 0
- EndFBB: pop.l a2
- rts
-
- ;
- ; Deallocate all MemoryBlocks from the chain and, if requested,
- ; deallocate the chain to.
- ;
- FreeMemoryChain:
- pushem.l d2/a2-a3/a6
- move.l a0,a2 ; chain to a2
- move.l d0,d2 ; struct free flag
- move.l (_SysBase).w,a6
- FMCLoop: lea.l mc_Blocks(a2),a0
- REMHEAD ; remove a block
- move.l d0,a1 ; put it in a1
- beq.s ChkDone ; block 0 then done
- move.l mc_BlockSize(a2),d0
- add.l #mb_SIZEOF,d0
- libcall FreeMem ; free it's memory
- bra.s FMCLoop
- ChkDone: tst.l d2
- bne.s AllDone ; free structure!
- lea.l mc_Items(a2),a0
- NEWLIST a0
- lea.l mc_Blocks(a2),a0
- NEWLIST a0
- bra.s FMCEnd
- AllDone: move.l a2,a1
- moveq #mc_SIZEOF,d0
- libcall FreeMem ; free the chain structure
- FMCEnd: popem.l d2/a2-a3/a6
- rts
-
- ;
- ; Fill the allocated item with zero's.
- ;
- ClearAlloc: lsr.l #2,d0 ; size / 4
- dec.l d0
- Loop: clr.l (a0)+ ; clear a long word
- dbra d0,Loop
- rts
-
- ;
- ; The same as AllocItem() exept that it remebers the size
- ; allocated.
- ;
- AllocVecItem:
- push.l d2
- addq.w #4,d0 ; make room to store size
- ROUND d0 ; round it all up
- move.l d0,d2 ; save to size
- bsr AllocItem ; allocate the item
- move.l d0,a0 ; result to a0
- beq.s NoVecMem ; failed !?!?!
- move.l d2,(a0)+ ; store size
- move.l a0,d0 ; return memory pointer
- NoVecMem: pop.l d2
- rts
-
- ;
- ; Free the memory allocated with AllocVecItem()
- ;
- FreeVecItem:
- subq.w #4,a1 ; get orig alloc address
- move.l (a1),d0 ; get the size
- bsr FreeItem ; free the memory
- rts
-