home *** CD-ROM | disk | FTP | other *** search
- ;------------------------------------------------------------------------------
- ; Multiple Local Heap Routines
- ; Dan Quigley 10-28-90
- ;------------------------------------------------------------------------------
-
-
- ;;;DEBUG EQU 1
-
- IFDEF DEBUG
- DebugOut MACRO st
- push ds
- push offset DGROUP:st
- cCall OUTPUTDEBUGSTRING
- ENDM
-
- DebugBreak MACRO
- ;;; int 1
- ENDM
- ENDIF
-
- .286 ; Enable 286 instruction set
-
- ;------------------------------------------------------------------------------
- ; Equates and structures
- ;------------------------------------------------------------------------------
-
-
- jmps EQU <jmp short> ; Helper equates
- bptr EQU <byte ptr>
- wptr EQU <word ptr>
- dwptr EQU <dword ptr>
- HSIZE EQU 8192 ; initial heap size
- K EQU 1024
- CRLF EQU <13,10,0>
-
- arena struc
- handle dw ?
- full db ?
- arena ends
-
- ;------------------------------------------------------------------------------
- ; CMACRO Setup
- ;------------------------------------------------------------------------------
-
- .xlist ; Suspend listing
- ?DF = 1 ; Don't generate default segs
- ?PLM = 1 ; Support Pascal calling
- ?WIN = 1 ; Support Windows
- include cmacros.inc
- include windows.inc
- .list
-
- ;------------------------------------------------------------------------------
- ; Segment definitions
- ;------------------------------------------------------------------------------
- createSeg MLOCAL_TEXT,CODE,PARA,PUBLIC,CODE ; Define code segment
- createSeg _DATA,DATA,PARA,PUBLIC,DATA,DGROUP ; Define data segment
- defGrp DGROUP,DATA ; Declare DGROUP
- assumes DS,DATA ; Tell assembler where DS is
- ; to be referenced
-
- ;------------------------------------------------------------------------------
- ; Global variables
- ;------------------------------------------------------------------------------
- sBegin DATA
- FLHeap dw 0 ; Global Handle to Heap
- FLHandle dw 0 ; Handle to Handle Table
- FLSize dw 0 ; Size of Handle Table
- FLOffset dw 0 ; start of handle table
- FLSel dw 0 ; selector to handle table
- FLEnd dw 0 ; end of handle table
- IFDEF DEBUG
- staticB MultFreeHeap,<'MultFreeHeap',CRLF>
- staticB MultLocalAlloc,<'MultLocalAlloc',CRLF>
- staticB MultLocalCompact,<'MultLocalCompact',CRLF>
- staticB MultLocalFlags,<'MultFlags',CRLF>
- staticB MultLocalFree,<'MultLocalFree',CRLF>
- staticB MultLocalHandle,<'MultLocalHandle',CRLF>
- staticB MultLocalInit,<'MultLocalInit',CRLF>
- staticB MultLocalLock,<'MultLocalLock',CRLF>
- staticB MultLocalReAlloc,<'MultLocalReAlloc',CRLF>
- staticB MultLocalSize,<'MultLocalSize',CRLF>
- staticB MultLocalUnlock,<'MultLocalUnlock',CRLF>
- staticB FarLocalAlloc,<'FarLocalAlloc',CRLF>
- staticB FarLocalCompact,<'FarLocalCompact',CRLF>
- staticB FarLocalFree,<'FarLocalFree',CRLF>
- staticB FarLocalInit,<'FarLocalInit',CRLF>
- staticB SetDStoHeap,<'SetDStoHeap',CRLF>
- ENDIF
- sEnd DATA
-
- ;------------------------------------------------------------------------------
- ; External procedures
- ;------------------------------------------------------------------------------
- externFP <GLOBALALLOC>
- externFP <GLOBALFREE>
- externFP <GLOBALLOCK>
- externFP <GLOBALUNLOCK>
-
- externFP <LOCALALLOC>
- externFP <LOCALCOMPACT>
- externFP <LOCALFLAGS>
- externFP <LOCALFREE>
- externFP <LOCALHANDLE>
- externFP <LOCALINIT>
- externFP <LOCALLOCK>
- externFP <LOCALREALLOC>
- externFP <LOCALSIZE>
- externFP <LOCALUNLOCK>
- externFP <OUTPUTDEBUGSTRING>
-
- ;------------------------------------------------------------------------------
- ; _TEXT starts here
- ;------------------------------------------------------------------------------
- sBegin CODE
- assumes CS,CODE ; Reference CS
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalAlloc - Allocates memory from the designated heap
- ;
- ; Returns : AX = Handle
- ;------------------------------------------------------------------------------
- cProc MultLocalAlloc,<PUBLIC,FAR>,<es,ds>
- parmW hHeap
- parmW wFlags
- parmW wBytes
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalAlloc
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je MLAExit
- mov ds,ax
- cCall LocalAlloc <wFlags,wBytes>
- MLAExit:
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalCompact - Compacts the designated heap
- ;
- ; Returns : the largest block of free memory
- ;------------------------------------------------------------------------------
-
- cProc MultLocalCompact,<PUBLIC,FAR>,<es,ds>
- parmW hHeap
- parmW wMinFree
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalCompact
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je LCExit
- mov ds,ax
- cCall LocalCompact <wMinFree>
- LCExit:
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalFlags - Returns the Allocation flags of a local memory object
- ;
- ; Returns :Allocation Flags
- ;------------------------------------------------------------------------------
- cProc MultLocalFlags,<PUBLIC,FAR>,<ds>
- parmW hHeap
- parmW hMem
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalFlags
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je LFExit
- mov ds,ax
- cCall LocalFlags <hMem>
- LFExit:
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalFree - Frees a local memory block from the designated heap
- ;
- ; Returns : NULL on success
- ;------------------------------------------------------------------------------
- cProc MultLocalFree,<PUBLIC,FAR>,<ds>
- parmW hHeap
- parmW hMem
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalFree
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je MLFErr
- mov ds,ax
- cCall LocalFree <hMem>
- jmps MLFExit
- MLFErr: mov ax,-1
- MLFExit:
- cEnd
-
- ;------------------------------------------------------------------------------
- ; MultLocalHandle - Returns the handle of the address of a block
- ;
- ; Returns : HANDLE
- ;------------------------------------------------------------------------------
- cProc MultLocalHandle,<PUBLIC,FAR>,<ds>
- parmD dwAddress
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalHandle
- DebugBreak
- ENDIF
-
- lds ax,dwAddress
- cCall LocalHandle <ax>
- cEnd
-
- ;------------------------------------------------------------------------------
- ; MultLocalInit - Allocates a 64k from the global heap and initializes it
- ;
- ; Returns : HANDLE on success
- ;------------------------------------------------------------------------------
- cProc MultLocalInit,<PUBLIC,FAR>,<es,di,si>
- parmW wSize
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalInit
- DebugBreak
- ENDIF
- push (GMEM_MOVEABLE OR GMEM_ZEROINIT)
-
- and wSize,0FFF0h ; round to 16 byte
- mov ax,0
-
- push ax ; high order word on stack first
- push wSize ; then low order
-
- cCall GlobalAlloc ; allocate the heap
- cmp ax,0 ; success?
- je MLIExit ; no then exit
-
- cCall GlobalLock <ax> ; we need the selector rights
- mov ax,dx
- cmp ax,0
-
- push ax ; yes save the handle for later
- je MLIErr
-
- push ax ; Global handle is in ax
- push 0 ; beging at start of heap
-
- mov ax,wSize ; wSize - 1 for heap length
- dec ax
- push ax
-
- cCall LocalInit ; LocalInit locks the heap
- cmp ax,0 ; did Init fail?
- jne MLIOK ; no then we're done
-
- MLIErr:
- cCall GlobalFree ; handle is still on stack
- mov ax,0
- jmps MLIExit
-
- MLIOK: pop ax ; return the handle
-
- MLIExit:
-
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalLock - Locks a local memory block from the designated heap
- ;
- ; Returns : selector:offset in dx:ax
- ;------------------------------------------------------------------------------
- cProc MultLocalLock,<PUBLIC,FAR>,<es,ds>
- parmW hHeap
- parmW hMem
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalLock
- DebugBreak
- ENDIF
- mov dx,0 ; assume failure
-
- mov ax,hHeap
- cmp ax,0
- je MLLExit
-
- mov ds,ax
- cCall LocalLock <hMem>
- cmp ax,0
- je MLLExit
-
- mov dx,ds
-
- MLLExit:
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; MultLocalReAlloc - Changes the size of the local memory block
- ;
- ; Returns : Handle to
- ;------------------------------------------------------------------------------
- cProc MultLocalReAlloc,<PUBLIC,FAR>,<es,ds>
- parmW hHeap
- parmW hMem
- parmW wBytes
- parmW wFlags
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalReAlloc
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je MLRExit
- mov ds,ax
- cCall LocalReAlloc <hMem, wBytes, wFlags>
- MLRExit:
- cEnd
-
- ;------------------------------------------------------------------------------
- ; MultLocalSize - Returns the size of the memory block
- ;
- ; Returns : Size in bytes
- ;------------------------------------------------------------------------------
- cProc MultLocalSize,<PUBLIC,FAR>,<ds>
- parmW hHeap
- parmW hMem
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalSize
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je MLSExit
- mov ds,ax
- cCall LocalSize <hMem>
- MLSExit:
- cEnd
-
- ;------------------------------------------------------------------------------
- ; MultLocalUnlock - Unlocks an object in the designated heap
- ;
- ; Returns : Lock Count
- ;------------------------------------------------------------------------------
- cProc MultLocalUnlock,<PUBLIC,FAR>,<es,ds>
- parmW hHeap
- parmW hMem
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalUnlock
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je MLUExit
- mov ds,ax
- cCall LocalUnlock <hMem>
- MLUExit:
- cEnd
-
- ;------------------------------------------------------------------------------
- ; MultFreeHeap - Free the Local Heap
- ;
- ; Returns : NULL on success - Heap on Failure
- ;------------------------------------------------------------------------------
- cProc MultFreeHeap,<PUBLIC,FAR>
- parmW hHeap
- cBegin
-
- IFDEF DEBUG
- DebugOut MultFreeHeap
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je FLHExit
- cCall GlobalUnlock <hHeap>
- cCall GlobalFree <hHeap>
-
- FLHExit:
- cEnd
-
- ;------------------------------------------------------------------------------
- ; FarLocalInit - Initializes the FarLocal Heap Routines
- ;
- ; Returns : Success NonZero | Failure FALSE
- ;------------------------------------------------------------------------------
- cProc FarLocalInit,<PUBLIC,FAR>,<di>
- cBegin
-
- IFDEF DEBUG
- DebugOut FarLocalInit
- DebugBreak
- ENDIF
- mov ax,1 ; Assume success
- cmp FLHeap,0 ; Have we initialized before
- jne FLIExit ; Yes, then exit
-
- mov FLSize,HSIZE ; Start with a 8K heap
- cCall MultLocalInit <FLSize> ; Initialize the handle table
- cmp ax,0 ; failure?
- je FLIExit ; then were hosed
- mov FLHeap,ax ; save the handle
-
- push ax
- push (LMEM_MOVEABLE OR LMEM_ZEROINIT)
- push (K * 6) ; start with 2K entries
- cCall MultLocalAlloc
-
- cmp ax,0 ; allocation succeed?
- jne TableOK ; yes
-
- CleanUp: cCall MultFreeHeap <FLHeap> ; clean up
- mov FLHeap,0
- jmps FLIExit ; and get out
-
- TableOK: mov FLHandle,ax ; store the handle
- cCall MultLocalLock <FLHeap,FLHandle>
- cmp dx,0 ; if we cant lock it down
- je CleanUp ; then exit
-
- mov FLOffset,ax ; store offset
- mov FLSel,dx ; store selector
- add ax,FLSize ; add the offset with size
- dec ax ; 0 referenced
- mov FLEnd,ax ; store the table end
-
- cCall MultLocalInit <FLSize> ; Initialize the first heap to 8K
- les di,dwptr FLOffset
- mov es:[di],ax ; store the handle
-
- FLIExit:
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; FarLocalAlloc - Allocates from the FarLocal Heap
- ;
- ; Returns : Success DD HANDLE | Failure FALSE
- ;------------------------------------------------------------------------------
- cProc FarLocalAlloc,<PUBLIC,FAR>,<di,si>
- parmW wFlags
- parmW wSize
-
- cBegin
-
- IFDEF DEBUG
- DebugOut FarLocalAlloc
- DebugBreak
- ENDIF
- cCall FarLocalInit ; initialize arena
-
- mov ax,0 ; assume failure
- mov dx,0
-
-
- tsearch: les di,dwptr FLOffset ; es:di to top of arena
- mov cx,wSize ; cx gets desired size
-
- search: cmp es:[di].full,ch ; is this arena entry full
- jbe found_one ; no then try the allocation
-
- next_entry: add di,3 ; get next arena entry
- cmp di,FLEnd ; are we beyond our limit
- jb search ; no, then continue walk
- ; yes then attempt to resize
- ; the arena
- cCall MultLocalUnlock <FLHeap,FLHandle>
- add FLSize,(K * 6) ; add another 2K entries
- mov ax,(LMEM_MOVEABLE OR LMEM_ZEROINIT)
- cCall MultLocalReAlloc <FLHeap,FLHandle,FLSize,ax>
- cmp ax,0 ; did realloc fail?
- je WeBeHosed ; yes, exit
- cCall MultLocalLock <FLHeap,FLHandle>
- mov FLOffset,ax ; store offset
- mov FLSel,dx ; store selector
- add ax,FLSize ; add the offset with size
- dec ax ; 0 referenced
- mov FLEnd,ax ; store the table end
- jmps tsearch ; no, then start walk
-
- ;;; **** possible optimization: calulate and set di to new area
-
- found_one: cmp es:[di].handle,0 ; has this heap been initialized
- jne do_alloc ; yes, then try the allocation
-
- alloc_new: cCall MultLocalInit <HSIZE> ; Initialize the next heap
- cmp ax,0 ; Init fail?
- je WeBeHosed ; yes, were hosed
- mov es:[di].handle,ax ; Store the new handle
-
- do_alloc: push es:[di].handle ; push heap handle
- push wFlags ; push flags
- push wSize ; then requested size
- cCall MultLocalAlloc ; attempt allocation
-
- cmp ax,0 ; did the alloc fail?
- jne got_it ; no
- mov cx,wSize ; cx gets desired size
- cmp ch,0 ; is size < 255
- jne size_ok ; no, then size ok
- inc ch ; yes, then bump ch
-
- size_ok: mov es:[di].full,ch ; full here so mark it
- jmp next_entry ; go back and search for more
-
- got_it: mov dx,es:[di].handle ; we have 4 byte handles
-
- WeBeHosed:
-
- cEnd
-
- ;------------------------------------------------------------------------------
- ; FarLocalFree - Frees objects from the FarLocal Heap
- ;
- ; Returns : Failure DD HANDLE | Success NULL
- ;------------------------------------------------------------------------------
- cProc FarLocalFree,<PUBLIC,FAR>,<di,si>
- parmD dwHandle
- cBegin
-
- IFDEF DEBUG
- DebugOut FarLocalFree
- DebugBreak
- ENDIF
- mov dx,1 ; assume failure
- mov ax,wptr dwHandle + 2 ; get the heaps global handle
- les di,dwptr FLOffset ; es:di to top of arena
-
- tfsearch: cmp es:[di].handle,ax ; is this the right arena entry
- je found_it ; yes
- add di,3 ; get next arena entry
- cmp di,FLEnd ; are we beyond our limit
- jb tfsearch ; no, then continue walk
- jmps fdone
-
- found_it: mov dx,0 ; signal success finding heap
- push ds ; save ds
- lds si, dwHandle ; get the heap and handle
- cCall LocalSize <si> ; ask for object size
- push ax ; save size
- cCall LocalFree <si> ; si has object handle
- pop cx ; size via pop
- pop ds ; restore ds
- cmp ax,0 ; success
- jne fdone ; no, then error
- cmp es:[di].full,0 ; is this heap marked full?
- je fdone ; no, then were done
- add es:[di].full,ch ; add the freed size (256 byte granularity)
- jnc fdone ; overflow?
- mov es:[di].full,0 ; reset the full byte
- fdone:
-
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; FarLocalCompact - Compacts the FarLocal Heap
- ;
- ; Returns : VOID
- ;------------------------------------------------------------------------------
- cProc FarLocalCompact,<PUBLIC,FAR>,<di>
-
- cBegin
-
- IFDEF DEBUG
- DebugOut FarLocalCompact
- DebugBreak
- ENDIF
-
- les di,dwptr FLOffset ; es:di to top of arena
-
- tfcsearch: cmp es:[di].handle,0 ; arena entry?
- je fcdone ; no then were done
- mov ax,es:[di].handle
- push ds ; change ds
- mov ds,ax
- mov cx,0FFFFh ; max compaction
- cCall LocalCompact <cx> ; do the compaction
- pop ds ; restore ds
- cmp es:[di].full,ah ; last alloc < new size
- jge noreset
- mov es:[di].handle,0 ; reset the full count
-
- noreset: add di,3 ; get next arena entry
- cmp di,FLEnd ; are we beyond our limit
- jb tfcsearch ; no, then continue walk
- jmps fcdone
-
- fcdone:
-
- cEnd
-
-
- ;------------------------------------------------------------------------------
- ; SetDStoHeap - Sets DS to heap
- ;
- ; Returns : Old DS
- ;------------------------------------------------------------------------------
- cProc SetDStoHeap,<PUBLIC,FAR>
- parmW hHeap
- cBegin
-
- IFDEF DEBUG
- DebugOut MultLocalUnlock
- DebugBreak
- ENDIF
- mov ax,hHeap
- cmp ax,0
- je SDSExit
- push ds
- mov ds,ax
- pop ax
- SDSExit:
- cEnd
-
- sEnd CODE
- END
-