bdmgr.asm
资源名称:DOS系统的源代码.rar [点击查看]
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:46k
源码类别:
操作系统开发
开发平台:
Visual C++
- TITLE BdMgr.asm - Buffer Descriptor Management Routines
- COMMENT
- --------- --- ---- -- ---------- ----
- COPYRIGHT (C) 1985 BY MICROSOFT, INC.
- --------- --- ---- -- ---------- ----
- ;============================================================================
- ; Module: BdMgr.asm - Buffer Descriptor Management Routines
- ; This is a layer of routines which depends on the BASCOM Runtime Heap
- ; Management routines in source file (strutl.asm).
- ; It manages entries in the Interpreter and Far heap.
- ; System: Quick BASIC Interpreter
- ;============================================================================
- .xlist
- include version.inc
- BDMGR_ASM = ON
- includeOnce architec
- includeOnce context
- includeOnce heap
- includeOnce parser
- includeOnce txtmgr
- includeOnce util
- .list
- ; .sall
- assumes DS,DATA
- assumes ES,DATA
- assumes SS,DATA
- sBegin DATA
- ; HMEM_ constants used by SBMGR allocation routines
- HMEM_FIXED EQU 0000H
- HMEM_MOVEABLE EQU 0002H
- HMEM_NOCOMPACT EQU 0010H
- HMEM_ZEROINIT EQU 0040H
- HMEM_DISCARDABLE EQU 0F00H
- externW b$fVarHeapActive ;non-0 when variable heap is active
- DbOMCnt MACRO label
- ENDM
- sEnd DATA
- EXTRN AdjustCommon:FAR
- EXTRN AdjustVarTable:FAR
- sBegin RT
- assumes CS,RT
- EXTRN B$ILHALC:NEAR
- EXTRN B$LHREALC:NEAR
- EXTRN B$LHDALC:NEAR
- EXTRN B$LHChgBakPtr:NEAR
- EXTRN B$ILHADJ:NEAR
- EXTRN B$LHForEachEntry:NEAR
- EXTRN B$NHCPCT:NEAR
- EXTRN B$TglHeapSpt:FAR
- EXTRN B$IFHAlloc:NEAR
- EXTRN B$FHDealloc:NEAR
- EXTRN B$FHRealloc:NEAR
- EXTRN B$FHAdjDesc:NEAR
- EXTRN B$FHAdjOneDesc:NEAR
- CBBUFBLOCK equ 512 ;Never grow a near heap by less than this
- ; number of bytes to reduce heap thrashing.
- VAR_EXTRA equ 30 ;we want to keep up to this much free space beyond
- ; cbLogical in IT_VAR (variable) tables when compressing
- ; other bd's all the way back to cbLogical. This is to
- ; help the user's chances of edit and CONTinuing.
- ;------------------------------------------------------------
- ;--- Interpreter Buffer Descriptor Management Routines ---
- ;------------------------------------------------------------
- ;***
- ;B$IHeapEntryMoved - handle movement of Interpreter-specific Heap entry
- ;Purpose:
- ; This routine is called by the Runtime Heap management
- ; code just before it moves an Interpreter-specific Heap entry.
- ; This routine performs any updating necessary due to
- ; the movement of an Interpreter-specific Heap entry
- ; it does not need to update entry pointer in the bd[p] for
- ; the entry being moved; it just dispatches based on the
- ; heap entry type to a routine which finds all string/heap
- ; owners within the heap entry being moved, and calls the heap
- ; management code to update the backpointers. Note that each
- ; such routine will be located in it's own component; these
- ; routines will call the runtime heap manager directly, but
- ; will do so via a macro to keep runtime heap interface knowledge
- ; confined to this module and associated header files.
- ;Entry:
- ; AX = number of bytes the heap entry has moved.
- ; A positive number indicates the entry has moved
- ; to a higher address.
- ; BX = pointer to the bd[p].pb field of the buffer descriptor for
- ; the heap entry being moved.
- ; CL = type constant for the heap type being moved (IT_MRS, ... etc.)
- ;
- ;Exit:
- ; none.
- ;Modifies:
- ; May modify BX, CX, or PSW - no others
- ;***************************************************************************
- cProc B$IHeapEntryMoved,<PUBLIC,NEAR,NODATA>,<AX,DX,ES,SI,DI>
- cBegin
- mov si,bx
- cmp cl,IT_NO_OWNERS_BDP ;a bdp entry being moved?
- jnz Not_Bdp ;brif not
- add [bx.BDP_pbCur-2],ax ;adjust the pbCur field
- jmp short Entry_Moved_Exit ;that's all, folks
- Not_Bdp:
- mov di,ax ;communicate adjustment factor in DI
- mov ax,[bx-2] ;put cbLogical (table end offset) in ax
- mov bx,[bx]
- push ax ;save until Entry_Moved_Cont
- push bx ;save until Entry_Moved_Cont
- push cx ;save until Entry_Moved_Cont
- cmp cl,IT_COMMON_VALUE
- jae Update_Stack_Ptrs ;brif we have to update stack ptrs, or
- ;var or common table
- cmp cl,IT_PRS ; no bd's in prs tables
- jz Entry_Moved_Cont ; brif prs table
- cCall AdjustITable,<bx,ax,cx> ;adjust the table, whatever it is.
- Entry_Moved_Cont:
- pop cx ;restore type constant
- pop bx ;restore start of range
- pop dx
- FHD_TBL EQU NOT IT_M_INTERP AND (IT_MRS OR IT_PRS OR IT_COMMON_VALUE OR IT_VAR)
- test cl,FHD_TBL
- jz Entry_Moved_Exit ;brif entry can't contain far heap desc.
- ;prs and mrs tables contain bdl's - - - get far heap to update these
- add dx,bx ;dx is now end of range
- mov ax,di ;adjustment factor
- call B$FHAdjDesc
- Entry_Moved_Exit:
- cEnd
- Update_Stack_Ptrs:
- jnz Upd_Stk_Ptrs_Cont ;brif cl != IT_COMMON_VALUE
- call AdjustCommon ;update backpointers to any string
- ;descriptors or string array descriptors
- ;in given IT_COMMON_VALUE heap entry
- jmp short Entry_Moved_Cont
- Upd_Stk_Ptrs_Cont:
- DbAssertRelB cl,z,IT_VAR,RT,<B$IHeapEntryMoved: cl == IT_VAR expected>
- call AdjustVarTable ;update backpointers to any string
- ;descriptors or string array descriptors
- ;in given IT_VAR heap entry
- jmp short Entry_Moved_Cont
- ;***
- ;BdCompress - Compress a Runtime Heap entry
- ;Purpose:
- ; Call B$LhRealloc to reduce cbPhysical to cbLogical for a Bd whose
- ; pb field is at a given location.
- ; Called via B$LHForEachEntry by BdCompressAll.
- ;
- ; Note that variable tables are handled specially - - they're trimmed
- ; back so that they keep up to VAR_EXTRA free space at the end of the
- ; table to maximize the change of CONTinuing after variables are added.
- ;Entry:
- ; BX = pointer to owner of a local heap entry - - - for interpreter
- ; buffers, that amounts to a pointer to the 'pb' field of the
- ; owning bd.
- ; DL = heap entry type.
- ;Exit:
- ; none.
- ;Preserves:
- ; CX,SI
- ;Exceptions:
- ; none.
- ;
- ;***************************************************************************
- cProc BdCompress,<NEAR,NODATA>
- cBegin BdCompress
- DbChk Heaps ;ife RELEASE & checking enabled, check
- ; Local & Far Heaps for problems
- test dl,IT_M_INTERP ;is this an interpreter buffer?
- jz BdCompress_Exit
- dec bx ;turn bx into a real pBd (for cmp below)
- dec bx
- mov ax,[bx.BD_cbLogical]
- cmp dl,IT_VAR ;is this a variable table?
- jnz BdCompress_Cont ; brif not
- add ax,VAR_EXTRA ;want to have up to VAR_EXTRA bytes
- ; left in each var table to improve
- ; chances of user adding a few
- ; variables and still CONTinuing
- cmp ax,[bx.BD_cbPhysical]
- jae BdCompress_Exit ;brif cbPhysical <= size we want buffer
- ; to be - - - leave buffer alone
- BdCompress_Cont:
- lea dx,[ps.PS_bdpDst.BDP_cbLogical]
- cmp bx,dx ;brif not special parser buffer that
- jnz BdCompress_Cont1 ; must always have a minimal amount
- cmp ax,CB_PCODE_MIN ;never trim below this minimum
- ja BdCompress_Cont1 ;brif cbLogical > Minimum required
- DbAssertRel [bx.BD_cbPhysical],ae,CB_PCODE_MIN,RT,<BdCompress:Parser buffer is too small>
- mov ax,CB_PCODE_MIN
- BdCompress_Cont1:
- push cx ;preserve for caller
- push si ;preserve for caller
- mov [bx.BD_cbPhysical],ax ;set new desired cbPhysical
- mov si,[bx.BD_pb] ;pointer to start of data in buffer
- call B$LHREALC ;reduce entry to cbLogical size
- ; MUST succeed and CANNOT cause
- ; heap movement, because it is either
- ; reducing entry size or doing nothing
- pop si
- pop cx
- BdCompress_Exit:
- cEnd BdCompress
- ;***
- ;BdCompressHeap - Compress all Runtime Heap entries in currently active heap
- ;Purpose:
- ; Same as BdCompressAll (below), but only crunches bd's in the currently
- ; active heap (either the local heap or the variable heap).
- ;Input:
- ; none.
- ;Output:
- ; none.
- ;Modifies:
- ; no permanent registers.
- ;Exceptions:
- ; Chance of string space corrupt.
- ;***************************************************************************
- cProc BdCompressHeap,<NEAR,NODATA>
- cBegin
- mov cx,RTOFFSET BdCompress
- call B$LHForEachEntry ;compress all bd's down to cbLogical
- ; (effect is to create free blocks
- ; out of extraneous space in bd's)
- cmp [b$fVarHeapActive],FALSE
- jnz BdCompressHeap_Exit ;don't compact the variable heap
- ; only runtime init. does that - -
- ; B$NHCPCT assumes local heap active.
- call B$NHCPCT ;compact Local Heap and String Space
- BdCompressHeap_Exit:
- DbChk Heaps
- cEnd
- ;***
- ;BdCompressAll - Compress all Runtime Heap entries
- ;Purpose:
- ; To increase the speed of BdGrow, we keep a little free
- ; space at the end of each heap entry. When the program
- ; begins execution, this routine is called to
- ; release all this space and compact interpreter-specific entries
- ; to the top of the Runtime Heap.
- ; Note that this routine is ONLY called by interpreter code,
- ; and never by the shared-runtime code.
- ;
- ; NOTE: after this operation is complete, the 'pbCurrent' field in
- ; bdp's will still be correct and useable, assuming that
- ; such pointers weren't pointing beyond cbLogical ...
- ;Input:
- ; none.
- ;Output:
- ; none.
- ;Modifies:
- ; no permanent registers.
- ;Exceptions:
- ; Chance of string space corrupt.
- ;
- ;***************************************************************************
- cProc BdCompressAll,<PUBLIC,FAR,NODATA>
- cBegin
- call BdCompressHeap ;compress the active heap
- call B$TglHeapSpt ;activate the other heap
- call BdCompressHeap ;compress the active heap
- call B$TglHeapSpt ;reactivate the originally active heap
- cEnd
- ;***
- ;BdAdjust(pBd)
- ; This routine takes a pointer to a bd as a parameter and assumes
- ; that an adjustment factor (the bd is being moved) is in DI.
- ; It calls a heap manager routine which updates the entry backpointer,
- ; if the bd is an owner (i.e., if the pb field is not NULL).
- ;Entry:
- ; pBd - pointer to a bd that's being moved
- ; DI contains adjustment factor it's being moved by
- ;Exit:
- ; none.
- ;Modifies:
- ; none. (no permanent registers)
- ;Exceptions:
- ; if anything wrong with heap entry for this bd, can end up calling
- ; the non-trapable "String Space Corrupt" error.
- ;***************************************************************************
- cProc BdAdjust,<PUBLIC,FAR,NODATA>
- parmW pBd
- cBegin BdAdjust
- mov bx,[pBd]
- mov ax,[bx.BD_pb]
- cmp ax,NULL
- jz BdAdjust_Done
- call B$ILHADJ ;get heap manager to do adjustment
- BdAdjust_Done:
- cEnd BdAdjust
- page
- ;***
- ;BdAllocVar - Allocate a Runtime Heap entry in the variable heap
- ;Purpose:
- ; Allocate an Interpreter-specific Heap entry from the variable heap.
- ; Uses the same interface and BdAlloc (see below).
- ;Entry, Exit, Modifies:
- ; Same as BdAlloc (see below).
- ;Note: Shares and exits via BdAlloc, below
- ;***************************************************************************
- cProc BdAllocVar,<PUBLIC,FAR,NODATA>
- cBegin <nogen>
- DbAssertRel grs.GRS_otxCONT,z,UNDEFINED,RT,<BdAllocVar: CAN continue>
- call B$TglHeapSpt ;make variable heap the active one
- cEnd <nogen> ;fall into BdAlloc, below
- ;***
- ;BdAlloc - Allocate a Runtime Heap entry
- ;Purpose:
- ; Allocate an Interpreter-specific Heap entry from the Runtime
- ; Heap.
- ; Note that this routine should ask for only the amount of space asked
- ; for; growing a buffer will increase requests to some minimal block size,
- ; but many buffers need to be initially allocated to some minimal
- ; (possibly zero) size.
- ; NOTE: current heap manager interface demands that the owner-to-be
- ; should not be subject to heap movement (i.e., not in heap, or
- ; heap locked).
- ;Entry:
- ; parm: bd *pbdOwner - points to owner-to-be of new heap entry
- ; parm: ushort cbSize - number of bytes needed
- ;if NOT FV_LMEM
- ; parm: char interpType - type of interp. table (IT_VALUE etc)
- ;endif
- ;Exit:
- ; if entry was successfully allocated:
- ; pbdOwner->cbLogical = cbSize
- ;if FV_LMEM
- ; pbdOwner->ppb = ptr to ptr to new heap entry (and is now owner)
- ;else
- ; pbdOwner->pb = pointer to new heap entry (and is now a heap owner)
- ; pbdOwner->cbPhysical = cbSize
- ;endif
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;Modifies:
- ; none (NOTE: DOES modify ES)
- ;
- ;***************************************************************************
- cProc BdAlloc,<PUBLIC,FAR,NODATA>,<SI>
- parmW pbdOwner
- parmW cbSize
- parmB interpType
- cBegin
- DbShiftLH ;ife RELEASE cause some heap movement
- DbChk Heaps
- mov dl,[interpType]
- mov cx,[cbSize]
- mov bx,[pbdOwner]
- DbChk BdNotOwner,bx ;ensure that given bd isn't an owner now
- mov [bx.BD_pb],NULL ;in case allocation fails and caller
- ; blindly calls BdFree with this bd
- DbOMCnt BD_END
- xchg bx,cx ;input order required by B$ILHALC
- inc cx ;'owner' to heap manager is the actual
- inc cx ; pointer to the heap entry, not a pbd
- call B$ILHALC ;call heap manager to allocate memory
- jc BD_Crunch_BDs ;brif OM return; trim bd's, try again
- BdAlloc_Success:
- mov bx,[pbdOwner] ;assumes bdOwner not moved by allocation
- mov [bx.BD_pb],si ;SI is data ptr returned from B$ILHALC
- mov ax,[cbSize] ;save requested size as both logical
- mov [bx.BD_cbLogical],ax ; and physical size, and return it as
- mov [bx.BD_cbPhysical],ax ; our non-zero (i.e., 'TRUE') result
- mov al,TRUE ;in case input size was zero
- BD_END:
- cmp [b$fVarHeapActive],FALSE
- jz BdAlloc_Exit ;brif variable heap not active
- call B$TglHeapSpt ;reactivate the local heap
- BdAlloc_Exit:
- cEnd
- BD_Crunch_BDs:
- push dx
- push cx
- call far ptr BdCompressAll ;trim bd's, compress heap space
- pop cx
- pop dx
- call B$ILHALC ;try allocation again
- jnc BdAlloc_Success ; brif it worked this time
- xor ax,ax ;OM error return
- jmp short BD_END
- ;***
- ;BdFree(pbdOwner) - Release a Heap entry
- ;Purpose:
- ; Release a Runtime Heap entry. If pbdOwner.BD_pb is NULL,
- ; just return (as input wasn't really an owner).
- ;Entry:
- ; parm: bd *pbdOwner - points to owner of new heap entry
- ;
- ;***************************************************************************
- cProc BdFree,<PUBLIC,FAR,NODATA>,<SI>
- parmW pbdOwner
- cBegin
- mov bx,[pbdOwner]
- mov si,[bx.BD_pb]
- cmp si,NULL
- jz BdFree_Exit ;brif bd isn't an owner
- mov [bx.BD_pb],NULL
- call B$LHDALC
- BdFree_Exit:
- cEnd
- ;***
- ;BdChgContents(pbd, psdNew) - Change contents of a buffer
- ;Purpose:
- ; Change the contents of a given buffer. Note that the buffer may or
- ; may not be an owner already; if it is an owner, it will be Free'd.
- ; The buffer will then be allocated, and the input sd contents copied in.
- ;
- ; NOTE: psdNew must not point into a heap entry!
- ;Entry:
- ; parm: bd *pbd - points to current owner of heap entry
- ; parm: bd *psdNew - points to sd, contents of which are to be put
- ; in the input bd.
- ;Exit:
- ; if operation successful
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory), and the original contents
- ; of the bd are lost.
- ;***************************************************************************
- cProc BdChgContents,<PUBLIC,FAR,NODATA>,<SI,DI>
- parmW pbd
- parmW psdNew
- cBegin
- mov si,[pbd]
- cCall BdFree,<si> ;free original contents if any
- mov di,[psdNew]
- DbChk PtrNotInHeap,di
- mov cx,[di.SD_cb]
- push cx ;save across call
- push si
- push cx
- PUSHI dx,IT_NO_OWNERS
- call BdAlloc ;alloc to size of desired contents
- pop cx
- or ax,ax
- jz BdChgContents_Exit ;brif OM error on allocation
- mov ax,[si.BD_pb]
- mov bx,[di.SD_pb]
- cCall CopyBlk,<bx,ax,cx> ;copy sd contents into bd
- BdChgContents_Exit:
- cEnd
- ;***
- ;BdChgOwner(pbdOwner, pbdNew) - Change the owner of a Heap entry
- ;BdChgOwner_NoCopy(pbdOwner, pbdNew) - Change the owner of a Heap entry
- ;Purpose:
- ; Change the owner of an Interpreter-specific Heap entry. If
- ; pbdOwner.BD_pb is NULL, just return (as it wasn't really an owner to
- ; begin with).
- ; BdChgOwner copies the bd contents to the new bd.
- ; BdChgOwner_NoCopy is provided as a speed improvement, and should be
- ; called in cases where the bd has already been copied BEFORE
- ; this routine is called.
- ;
- ; NOTE: This routine is guaranteed not to cause heap movement to occur.
- ;
- ; NOTE: This routine must be called AFTER a block containing the bd is
- ; moved if such movement is to take place, because this routine
- ; changes the contents of bdOwner to indicate that it's no longer
- ; an owner.
- ;Entry:
- ; parm: bd *pbdOwner - points to current owner of heap entry
- ; parm: bd *pbdNew - points to new owner of heap entry
- ;
- ;***************************************************************************
- PUBLIC BdChgOwner
- BdChgOwner:
- mov cx,SIZE BD ;non-zero - - - do the copy
- SKIP2_PSW ;skip to start of common code
- PUBLIC BdChgOwner_NoCopy
- BdChgOwner_NoCopy:
- xor cx,cx
- cProc Chg_The_Owner,<FAR,NODATA>,<SI>
- parmW pbdOwner
- parmW pbdNew
- cBegin
- mov si,[pbdOwner]
- cmp [si.BD_pb],NULL
- jz BdChg_Exit
- DbChk BdOwner,si ;ensure that given bd is an owner
- jcxz BdChg_CopyDone ;brif caller already did this copy
- push si
- push pbdNew
- push cx ;set to SIZE BD for BdChgOwner
- call CopyBlk
- BdChg_CopyDone:
- mov cx,[pbdNew]
- inc cx ;to heap manager, 'owner' is the actual
- inc cx ; pointer to heap data, not a pbd
- push si ;si is an input to B$LHChgBakPtr
- mov si,[si.BD_pb]
- call B$LHChgBakPtr
- pop si ;so we can set bd.pb to NULL
- mov [si.BD_pb],NULL ;mark that this is no longer an owner
- BdChg_Exit:
- cEnd
- ;***
- ;EnsPhysicalSize - ensure physical size of near heap >= ax
- ;Purpose:
- ; Change physical size of an Interpreter-specific Heap entry if necessary.
- ; This is used by BdGrow and BdCheckFree.
- ; Note that this is not an external entry point, only for use
- ; within this module, and can thus use register calling conventions.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;Entry:
- ; [di] - points to owner of heap entry
- ; [ax] = new total size requested for the buffer (i.e., new minimum
- ; cbPhysical desired).
- ;Exit:
- ; if enough memory is available:
- ; [ax] = TRUE (non-zero)
- ; [bx] = new value for cbLogical (i.e., [ax] exit = entry)
- ; otherwise,
- ; [ax] = 0
- ;
- ;***************************************************************************
- EnsPhysicalSize PROC NEAR
- DbChk BdOwner,di ;ensure that given bd is an owner
- DbChk Heaps
- push ax ;save input requested size
- DbOMCnt Ens_End2
- cmp ax,[di.BD_cbPhysical]
- jbe NoChange ;branch if already big enough
- push si ;save caller's si
- push ax ;in case initial try fails
- sub ax,[di.BD_cbPhysical] ;ax=amount to grow
- cmp ax,CBBUFBLOCK
- jae Big_Enough ;branch if growing by significant amount
- mov ax,CBBUFBLOCK ;never grow by less than this amount
- Big_Enough:
- add ax,[di.BD_cbPhysical] ;ax=(hopefully) new cbPhysical
- push ax ;save (hopefully) new cbPhysical
- mov si,[di.BD_pb]
- call B$LHREALC ;call heap manager to realloc
- pop bx ;size we realloced to
- or ax,ax ;test result
- jz Ens_Crunch_BDs ;brif realloc failed
- pop cx ;clean stack
- Ens_Phy_Success:
- mov [di.BD_cbPhysical],bx
- mov [di.BD_pb],si ;in case realloc moved the entry
- Ens_End1:
- pop si ;restore caller's si
- Ens_End2:
- pop bx ;restore input size for retval
- ret
- NoChange:
- mov al,TRUE ;ensure TRUE return, even if passed ax=0
- jmp short Ens_End2
- EnsPhysicalSize ENDP
- Ens_Crunch_BDs:
- call far ptr BdCompressAll ;trim all bd's, compress heaps
- pop ax ;input to B$LHREALC
- push ax ;save for return
- mov si,[di.BD_pb] ;may be trashed on error return
- call B$LHREALC
- pop bx ;cb we tried to realloc to
- or ax,ax ;did we succeed this time?
- jz Ens_End1 ; brif not
- jmp short Ens_Phy_Success ;succeeded this time - - go wrap up
- ;***
- ;BdGrowVar - Grow a Runtime Heap entry in the variable heap
- ;Purpose:
- ; Same as BdGrow (below), but for an entry in the variable heap.
- ; Uses the same interface and BdGrow (see below).
- ;Entry, Exit, Modifies:
- ; Same as BdGrow (see below).
- ;Note: Shares and exits via BdGrow, below
- ;***************************************************************************
- cProc BdGrowVar,<PUBLIC,FAR,NODATA>
- cBegin <nogen>
- DbAssertRel grs.GRS_otxCONT,z,UNDEFINED,RT,<BdlGrowVar: CAN continue>
- call B$TglHeapSpt ;make variable heap the active one
- cEnd <nogen> ;fall into BdGrow, below
- ;***
- ;BdGrow - Increase the logical size of a Heap entry
- ;Purpose:
- ; Change logical size of an Interpreter-specific Heap entry. This can
- ; result in the movement of this and other heap entries as well
- ; as strings.
- ; When this routine actually needs to grow the physical size
- ; of the heap, it grows more than needed for this request, to
- ; reduce heap thrashing.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;Entry:
- ; parm: bd *pbdOwner - points to owner of heap entry
- ; parm: ushort cbGrow - number of bytes needed
- ;Exit:
- ; if enough memory is available:
- ; pbdOwner->cbLogical += cbGrow,
- ; pbdOwner->cbPhysical >= pbdOwner->cbLogical
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdGrow,<PUBLIC,FAR,NODATA>,<di>
- parmW pbdOwner
- parmW cbGrow
- cBegin
- mov di,[pbdOwner] ;di points to bd descriptor
- mov ax,[cbGrow] ;[AX] == increase desired
- add ax,[di.BD_cbLogical] ;[AX] == new logical size
- jc GrowOmErr ;branch if overflow (can't grow > 64k)
- ;*****************************
- ;NOTE: BdRealloc jumps in here
- ;*****************************
- BdRealloc1:
- call EnsPhysicalSize ;change physical size (inputs ax & di)
- or ax,ax ;test boolean result
- jz BdGrow_End ;brif out-of-memory case
- mov [di.BD_cbLogical],bx ;new cbLogical - successful return
- BdGrow_End:
- cmp [b$fVarHeapActive],FALSE
- jz BdGrow_Exit ;brif variable heap not active
- call B$TglHeapSpt ;reactivate the local heap
- BdGrow_Exit:
- cEnd
- GrowOmErr:
- xor ax,ax
- jmp short BdGrow_End
- ;***
- ;BdRealloc - Change the logical size of a Heap entry
- ;Purpose:
- ; Change logical size of an Interpreter-specific Heap entry. This can
- ; result in the movement of this and other heap entries as well
- ; as strings.
- ; When this routine actually needs to grow the physical size
- ; of the heap, it grows more than needed for this request, to
- ; reduce heap thrashing.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;Entry:
- ; parm: bd *pbdOwner - points to owner of heap entry
- ; parm: ushort cbLogicalNew - new size of heap entry
- ;Exit:
- ; if enough memory is available:
- ; pbdOwner->cbLogical = cbLogicalNew,
- ; pbdOwner->cbPhysical >= pbdOwner->cbLogical
- ; [AX] = TRUE (non-zero)
- ; else
- ; pbdOwner->cbLogical is unchanged
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdRealloc,<PUBLIC,FAR,NODATA>,<di>
- parmW pbdOwner
- parmW cbNew
- cBegin
- mov di,[pbdOwner] ;di points to bd descriptor
- mov ax,[cbNew] ;[AX] == increase desired
- jmp SHORT BdRealloc1
- cEnd <nogen>
- ;***
- ;BdCheckFree - Make sure buffer has some free space
- ;Purpose:
- ; This is identical to BdGrow, but it does not alter the
- ; descriptor's cbLogical field. Some typical cases when it is
- ; called include:
- ; 1- Before calling BdAppend to copy from one bd to another.
- ; By calling this first, we know BdAppend won't have to
- ; grow the heap entry, causing movement, which could invalidate
- ; BdAppend's pb argument.
- ; 2- When the caller is about to do an operation which will
- ; append information to a bd, but the caller doesn't know
- ; exactly how many bytes will be added, but an upper limit is known.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;Entry:
- ; parm: bd *pbdOwner - points to owner of heap entry
- ; parm: ushort cbFree - number of free bytes needed
- ;Exit:
- ; pbdOwner->cbLogical is ALWAYS UNCHANGED
- ; If enough memory is available:
- ; pbdOwner->cbPhysical >= pbdOwner->cbLogical + cbFree
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdCheckFree,<PUBLIC,FAR,NODATA>,<DI>
- parmW pbdOwner
- parmW cbFree
- cBegin
- mov di,[pbdOwner] ;di points to bd descriptor
- mov ax,[cbFree] ;[AX] == increase desired
- add ax,[di.BD_cbLogical] ;[AX] == resulting size
- jc CheckOmErr ;branch if overflow (can't grow > 64k)
- call EnsPhysicalSize ;change physical size (inputs ax & di)
- BdCheck_End:
- cEnd
- CheckOmErr:
- xor ax,ax
- jmp short BdCheck_End
- ;***
- ; boolean BdShiftRight(pbd, obStart, cb)
- ;
- ; Purpose:
- ; Grow the buffer descriptor, and shift its contents right
- ; (copying content to higher addresses) starting at offset
- ; obStart until the end of the buffer.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;
- ; Entry:
- ; parmW pbd points to the buffer descriptor
- ; parmW obStart = byte offset for 1st byte to be shifted right
- ; parmW cb = number of bytes each byte is to be shifted
- ;
- ; Exit:
- ; If not enough memory can be obtained,
- ; [AX] = FALSE
- ; else
- ; pbdDst->cbLogical is updated
- ; [AX] = TRUE
- ;
- ; Before BdShiftRight(pbd, 2, 2):
- ; high memory
- ; pbd->cbLogical------->+-----+
- ; | E |
- ; | D |
- ; | C |
- ; | B |
- ; | A |
- ; low memory +-----+
- ;
- ; After:
- ; high memory
- ; pbd->cbLogical------->+-----+
- ; | E |
- ; | D |
- ; | C |
- ; | D |
- ; | C |
- ; | B |
- ; | A |
- ; low memory +-----+
- ;
- ;***************************************************************************
- cProc BdShiftRight,<PUBLIC,FAR,NODATA>,<SI,DI>
- parmW pbd
- parmW obStart
- parmW cb
- cBegin
- push pbd
- push cb
- call BdCheckFree ;1st grow the buffer
- or ax,ax
- je BdShiftExit ;branch if out-of-memory, return 0
- mov bx,pbd ;bx -> descriptor
- mov cx,[bx.BD_cbLogical] ;[CX] = current size of buffer
- mov si,[bx.BD_pb] ;si points to start of buffer
- add si,cx ;si points beyond end of current content
- dec si ;si points to 1st byte to copy
- mov di,si
- mov ax,cb
- add di,ax ;di points to dst for 1st byte to copy
- add [bx.BD_cbLogical],ax ;update size of buffer
- sub cx,obStart ;[CX] = number of bytes to copy
- jcxz Copy0Bytes
- push ds
- pop es ;es=ds
- std ;copy from high to low address
- rep movsb ;do the block copy
- cld
- Copy0Bytes:
- mov ax,TRUE
- BdShiftExit:
- cEnd
- ;***
- ; boolean BdShiftLeft(pbd, obStart, cb)
- ;
- ; Purpose:
- ; Shrink the buffer descriptor, and shift its contents left
- ; (copying content to lower addresses) starting at offset
- ; obStart until the end of the buffer.
- ;
- ; Entry:
- ; parmW pbd points to the buffer descriptor
- ; parmW obStart = byte offset for 1st byte to be deleted
- ; parmW cb = number of bytes to be deleted
- ;
- ; Exit:
- ; pbdDst->cbLogical is updated
- ; no return value
- ;
- ; Before BdShiftLeft(pbd, 2, 2):
- ; high memory
- ; pbd->cbLogical------->+-----+
- ; | E |
- ; | D |
- ; | C |
- ; | B |
- ; | A |
- ; low memory +-----+
- ;
- ; After:
- ; high memory
- ; pbd->cbLogical------->+-----+
- ; | E |
- ; | B |
- ; | A |
- ; low memory +-----+
- ;
- ;***************************************************************************
- cProc BdShiftLeft,<PUBLIC,FAR,NODATA>,<SI,DI>
- parmW pbd
- parmW obStart
- parmW cb
- cBegin
- mov bx,pbd ;bx -> descriptor
- mov di,[bx.BD_pb] ;di points to start of buffer
- add di,obStart ;di points to 1st byte to delete
- mov si,di
- add si,cb ;si points beyond last byte to delete
- mov cx,[bx.BD_cbLogical] ;[CX] = current size of buffer
- sub cx,cb ;cx = new size of buffer
- mov [bx.BD_cbLogical],cx ;update descriptor
- sub cx,obStart ;cx = # bytes to copy
- jcxz LeftExit ;brif 0 bytes to copy
- push ds
- pop es ;es=ds
- rep movsb ;do the block copy
- LeftExit:
- cEnd
- ;***
- ; boolean BdAppend(pbdDst, pbSrc, cb)
- ;
- ; Purpose:
- ; Append a string of bytes to a Buffer Descriptor.
- ; If this is preceeded by a call to BdCheckFree(pbdDst, cb)
- ; then pbSrc can point within another heap entry with no
- ; fear of movement before the copy is complete. Otherwise,
- ; pbSrc had better not point within a heap entry.
- ;
- ; NOTE: current heap manager interface demands that the owner
- ; should not be subject to heap movement.
- ;
- ; Entry:
- ; parmW pbdDst points to the destination buffer descriptor
- ; parmW pbSrc points to 1st byte to be copied into buffer
- ; parmW cb = number of bytes to be copied
- ;
- ; Exit:
- ; If not enough memory can be obtained,
- ; [AX] = FALSE
- ; else
- ; pbdDst->cbLogical is updated
- ; [AX] = TRUE
- ;
- ;***************************************************************************
- cProc BdAppend,<PUBLIC,FAR,NODATA>,<SI,DI>
- parmW pbdDst
- parmW pbSrc
- parmW cb
- localW pbDst
- localW cbTemp
- cBegin
- push pbdDst
- push cb
- call BdCheckFree
- or ax,ax
- je BdAppendExit ;branch if out-of-memory, return 0
- mov cx,cb ;[CX] = # bytes to copy
- mov di,pbdDst ;di -> destination descriptor
- mov ax,[di.BD_cbLogical] ;ax = current size of buffer
- add [di.BD_cbLogical],cx ;update size of buffer
- mov di,[di.BD_pb] ;di points to start of dest buffer
- add di,ax ;add new bytes at end of buffer
- mov si,pbSrc ;si = source byte ptr
- push ds
- pop es ;es=ds
- rep movsb ;do the block copy
- mov ax,TRUE
- BdAppendExit:
- cEnd
- ;-----------------------------------------------------------------
- ;--- Large Far Heap Buffer Descriptor Management Routines ---
- ;-----------------------------------------------------------------
- FAR_EXTRA = 512 ;never grow a far heap entry by less than 512 bytes
- ;***
- ;AllocBdl - Allocate a Far Heap entry (workhorse for BdlAlloc)
- ;AllocBdl_Sb - same, but allocates a given sb for this
- ;Purpose:
- ; Allocate a Heap entry from the Far Heap. This can cause
- ; movement of Runtime and String heap entries.
- ; Note that this routine should ask for only the amount of space asked
- ; for; growing a buffer will increase requests to some minimal block size,
- ; but many buffers need to be initially allocated to some minimal
- ; (possibly zero) size.
- ;Entry:
- ; di = pbdlOwner - points to owner of new heap entry
- ; si = cbSize - number of bytes needed
- ; For EB versions, bx = type constant for type of bdl buffer
- ; For AllocBdl_Sb, cx = sb to use
- ;Exit:
- ; if entry was successfully allocated:
- ; pbdlOwner->cbLogical = cbSize
- ; pbdlOwner->cbPhysical = cbSize
- ; [AX] = TRUE (non-zero)
- ; pbdlOwner->status != NOT_OWNER
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ; PSW.Z is set on exit based on an 'OR AX,AX' instruction
- ;
- ;***************************************************************************
- cProc AllocBdl,<NEAR,NODATA>
- cBegin <nogen>
- mov cx,0 ; use any sb that's free
- cEnd <nogen>
- cProc AllocBdl_Sb,<NEAR,NODATA>
- cBegin
- mov ax,si
- DbAssertRel ax,be,0FFF0H,RT,<BdlAlloc: caller asked for more than FFF0H>
- ;The above assertion is based on the problem where a request to
- ; B$IFHAlloc for greater than 0FFF0H bytes will be rounded UP to past
- ; 64k, with no error reported.
- xor dx,dx ;DX:AX is input size to B$IFHAlloc
- mov bx,di
- DbChk BdlNotOwner,di
- mov [bx.BDL_cbLogical],ax
- call B$IFHAlloc ;allocate a far heap entry (0 if can't)
- or ax,ax ;set zero flag for caller
- cEnd AllocBdl
- ;***
- ;BdlAlloc - Allocate a Far Heap entry
- ;Purpose:
- ; Allocate a Heap entry from the Far Heap. This can cause
- ; movement of Runtime and String heap entries.
- ; Note that this routine should ask for only the amount of space asked
- ; for; growing a buffer will increase requests to some minimal block size,
- ; but many buffers need to be initially allocated to some minimal
- ; (possibly zero) size.
- ;
- ; [5] Note that at least some callers depend on the new block being zero-
- ; [5] filled (EB varmgr code, for one).
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of new heap entry
- ; parm: ushort cbSize - number of bytes needed
- ;Exit:
- ; if entry was successfully allocated:
- ; pbdlOwner->cbLogical = cbSize
- ; pbdlOwner->cbPhysical = cbSize
- ; [AX] = TRUE (non-zero)
- ; pbdlOwner->status != NOT_OWNER
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdlAlloc,<PUBLIC,FAR,NODATA>,<si,di>
- parmW pbdlOwner
- parmW cbSize
- cBegin
- DbOMCnt BdlAlloc_Exit
- mov di,[pbdlOwner]
- mov si,[cbSize]
- cCall AllocBdl
- jnz BdlAlloc_Exit ;brif success
- call far ptr BdCompressAll ;trim bd's, compress heap space
- cCall AllocBdl
- BdlAlloc_Exit:
- cEnd
- ;***
- ;BdlAllocSb - Allocate a Far Heap entry, given a desired sb
- ;Purpose:
- ; Same as BdlAlloc, but accepts as a third parm the sb value that
- ; is to be used.
- ; Added as revision [13].
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of new heap entry
- ; parm: ushort cbSize - number of bytes needed
- ; parm: ushort sbInput - sb we must use for this allocation
- ; (caller guarantees this is unallocated).
- ;Exit:
- ; if entry was successfully allocated:
- ; pbdlOwner->cbLogical = cbSize
- ; pbdlOwner->cbPhysical = cbSize
- ; [AX] = TRUE (non-zero)
- ; pbdlOwner->status != NOT_OWNER
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdlAllocSb,<PUBLIC,FAR,NODATA>,<si,di>
- parmW pbdlOwner
- parmW cbSize
- parmW sbInput
- cBegin
- DbOMCnt BdlAllocSb_Exit
- mov di,[pbdlOwner]
- mov si,[cbSize]
- mov cx,[sbInput]
- cCall AllocBdl_Sb
- BdlAllocSb_Exit:
- cEnd
- ;***
- ;BdlFree - Release a far Heap entry
- ;Purpose:
- ; Release a far Heap entry. If bdl is not an owner, this routine just
- ; returns, with no error.
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of new heap entry
- ;Exit:
- ; bdl is released; pbdlOwner->status = NOT_OWNER
- ;
- ;***************************************************************************
- cProc BdlFree,<PUBLIC,FAR,NODATA>
- parmW pbdlOwner
- cBegin
- mov bx,[pbdlOwner]
- cmp [bx.BDL_status],NOT_OWNER
- jz BdlFree_Exit ;brif bdl already free
- DbChk BdlOwner,bx ;ensure that given bdl is an owner
- push bx
- call B$FHDealloc ;free an allocated far heap entry
- pop bx
- mov [bx.BDL_status],NOT_OWNER ;indicate that bdl is not an owner
- BdlFree_Exit:
- cEnd
- ;***
- ;BdlChgOwner(pbdlOwner, pbdlNew) - Change the owner of a Far Heap entry
- ;Purpose:
- ; Change the owner of a Far Heap entry. If pbdlOwner.BDL_status is
- ; NOT_OWNER, just return (as it wasn't really an owner to begin with).
- ;
- ; NOTE: This routine is guaranteed not to cause heap movement to occur.
- ;
- ; NOTE: This routine must be called AFTER a block containing the bdl is
- ; copied, as the far heap manager modifies the FHD according to
- ; its original location. This copy MUST be done by the caller
- ; prior to this routine being called.
- ; Note also that it is NOT safe to block copy a range containing
- ; multiple bdl's and then call this routine once per bdl - - -
- ; Since the far heap code chains all bdl's together, a call to
- ; BdlChgOwner can cause another bdl to be modified (in the
- ; 'status' a.k.a. 'pNext' field).
- ;Entry:
- ; parm: bdl *pbdlOwner - points to current owner of far heap entry
- ; parm: bdl *pbdlNew - points to new owner of far heap entry
- ;Exit:
- ; none.
- ;
- ;***************************************************************************
- cProc BdlChgOwner,<PUBLIC,FAR,NODATA>,<SI>
- parmW pbdlOwner
- parmW pbdlNew
- cBegin
- mov si,[pbdlOwner]
- cmp [si.BDL_status],NOT_OWNER
- jz BdlChg_Exit ;brif bdl wasn't an owner
- DbChk BdlOwner,si ;ensure that bdlOwner is an owner
- mov dx,si ;pFHD for FHD that's being moved
- mov cx,[pbdlNew]
- sub cx,si ;cx = pNew - pOld (adjustment factor)
- call B$FHAdjOneDesc
- mov [si.BDL_status],NOT_OWNER
- BdlChg_Exit:
- cEnd
- ;***
- ;BdlRealloc - reallocate a Far Heap entry
- ;Purpose:
- ; reallocate a Heap entry from the Far Heap. This can cause
- ; movement of String and Runtime heap entries.
- ;
- ; [5] Note that at least some callers depend on additional space being
- ; [5] zero-filled (EB varmgr code, for one).
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of heap entry
- ; parm: ushort cbNew - new buffer size desired
- ;Exit:
- ; if entry was successfully reallocated:
- ; pbdlOwner->cbLogical = cbNew
- ; pbdlOwner->cbPhysical >= cbNew
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdlRealloc,<PUBLIC,FAR,NODATA>,<di>
- parmW pbdlOwner
- parmW cbNew
- localB fTryAgain
- cBegin
- mov [fTryAgain],TRUE
- DbOMCnt BdlRealloc_Exit
- mov di,[pbdlOwner]
- mov bx,[di.BDL_cPhysical]
- SHIFT H,L,bx,4 ;shift left to convert cPara to cbytes
- mov ax,[cbNew]
- cmp bx,ax
- jae Change_cbLogical ;brif physical size is big enough
- cmp ax,0FFE0H ;if ask far heap for > FFE0H, it will
- ; round request up to para boundary ...
- jbe BdlRealloc_Cont ;brif request not too large
- xor ax,ax ;Out of Memory return
- jmp short BdlRealloc_Exit
- BdlRealloc_Crunch:
- cmp [fTryAgain],FALSE
- jz BdlRealloc_Exit ;brif we've already tried this - give up
- mov [fTryAgain],FALSE ;remember this is the 2nd attempt
- call far ptr BdCompressAll ;trim all bd's, compress heaps,
- mov ax,[cbNew] ;and try again w/o blocking factor
- jmp short BdlRealloc_Cont1
- BdlRealloc_Cont:
- add ax,FAR_EXTRA ;ax = ax + FAR_EXTRA to reduce thrashing
- ;Under DOS 3, we know the heap manager actually allocates in 16-byte
- ; (paragraph) quantities, so to ensure we don't waste an average of
- ; 8 bytes per bdl, pay a few bytes of code here to round up
- jc RealcForMax ;brif this puts us over 64k
- BdlRealloc_Cont1:
- add ax,000FH ;constant for rounding up to paragraph
- jnc TryToRealloc ;brif still under 64k
- RealcForMax:
- mov ax,0FFE0H ; try for maximum - - - note that
- ;'maximum' can't be FFFFH, because
- ;the far heap code will round this
- ;up to the nearest paragraph boundary
- TryToRealloc:
- and al,0F0H ;[9] finish rounding size up to para
- mov dx,0FFE0H
- cmp ax,dx ; is result > legal max?
- jbe ReallocAttempt ; brif not
- xchg ax,dx
- ReallocAttempt:
- DbChk BdlOwner,di ;ensure that bdlOwner is an owner
- xor dx,dx
- mov bx,di
- call B$FHRealloc
- or ax,ax
- jz BdlRealloc_Crunch ;brif insufficient memory
- mov ax,[cbNew] ;requested size
- Change_cbLogical:
- mov [di.BDL_cbLogical],ax ;save new logical size
- mov ax,sp ;signal success (cbNew could be zero ..)
- BdlRealloc_Exit:
- cEnd
- ;***
- ;BdlCheckFree - Make sure far heap entry has some free space
- ;Purpose:
- ; Change size of a far Heap entry if necessary to
- ; ensure that there is a certain number of free bytes at the
- ; end of the entry. This can result in the movement of this
- ; and other heap entries.
- ; This routine does not work with HUGE heap entries (i.e. > 64k)
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of heap entry
- ; parm: ushort cbFree - number of free bytes needed
- ;Exit:
- ; If enough memory is available:
- ; pbdlOwner->cbLogical is unchanged
- ; pbdlOwner->cbPhysical >= pbdlOwner->cbLogical + cbFree
- ; [AX] = TRUE (non-zero) (successful return)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdlCheckFree,<PUBLIC,FAR,NODATA>,<di>
- parmW pbdlOwner
- parmW cbFree
- cBegin
- DbOMCnt BdlCheckFreeExit
- mov di,[pbdlOwner]
- mov ax,[di.BDL_cPhysical] ;ax = current physical size
- SHIFT H,L,ax,4 ;shift left to convert cPara to cbytes
- push ax
- sub ax,[di.BDL_cbLogical] ;ax = current free size
- sub ax,cbFree ;ax = new free size
- jnc SizeIsOk ;brif we're already big enough
- neg ax
- pop bx
- add ax,bx ;ax = minimum new free size
- jc BdlCheckDenied ;error if attempting to grow > 64k
- push [di.BDL_cbLogical] ;save this across call to BdlRealloc
- cCall BdlRealloc,<di,ax>
- pop [di.BDL_cbLogical]
- BdlCheckFreeExit:
- cEnd
- BdlCheckDenied:
- xor ax,ax ;return ERROR result (zero)
- SKIP1_PSW ;this 'eats' the next instruction
- SizeIsOk:
- pop ax ;cPhysical known to be non-zero
- jmp short BdlCheckFreeExit
- ;***
- ;BdlGrow - Increase the logical size of a Heap entry
- ;Purpose:
- ; Change logical size of a bdl. This can result in the movement of this
- ; and other heap entries.
- ; When this routine actually needs to grow the physical size
- ; of the bdl, it grows more than needed for this request, to
- ; reduce heap thrashing.
- ;
- ; Added as part of revision [9].
- ;Entry:
- ; parm: bd *pbdlOwner
- ; parm: ushort cbGrow - number of additional bytes needed
- ;Exit:
- ; if enough memory is available:
- ; pbdlOwner->cbLogical += cbGrow,
- ; pbdlOwner->cPhysical increased to account for >= cbLogical bytes
- ; [AX] = TRUE (non-zero)
- ; else
- ; [AX] = FALSE (0) (Out of memory)
- ;
- ;***************************************************************************
- cProc BdlGrow,<PUBLIC,FAR>
- parmW pbdlOwner
- parmW cbGrow
- cBegin
- mov bx,[pbdlOwner]
- mov ax,[cbGrow]
- add ax,[bx.BDL_cbLogical]
- cCall BdlRealloc,<bx,ax>
- cEnd
- ;***
- ;BdlCopyFrom - Copy data from a far Heap entry to DS
- ;Purpose:
- ; Copy data from a far Heap entry to DS
- ; Does not work with HUGE heap entries (i.e. > 64k)
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of new heap entry
- ; parm: ushort oSrc - 16 bit offset into bdl to source
- ; parm: char *pbDst - points to 1st byte of destination
- ; parm: ushort cb - number of bytes to copy
- ;
- ;***************************************************************************
- cProc BdlCopyFrom,<PUBLIC,FAR,NODATA>,<si,di>
- parmW pbdlOwner
- parmW oSrc
- parmW pbDst
- parmW cb
- cBegin
- mov si,[oSrc] ;si = source offset
- mov di,[pbDst] ;di = destination offset
- mov bx,[pbdlOwner]
- DbChk BdlOwner,bx ;ensure that bdlOwner is an owner
- GETSEG ax,[bx.BDL_seg],,<SIZE,LOAD> ;[4] seg of far heap entry
- mov bx,ds ;bx -> DGROUP
- mov ds,ax ;set up source seg (heap entry)
- mov es,bx ;set up destination seg (DGROUP)
- CopyCommon:
- mov cx,cb ;cx = byte count
- shr cx,1 ;convert to word count
- rep movsw ;transfer from ds:si to es:di
- jnc CopyFrom_Even ;no carry if count was even
- movsb ;move the last (odd) byte
- CopyFrom_Even:
- mov ds,bx ;restore ds->DGROUP
- cEnd
- ;***
- ;BdlCopyTo - Copy data from DS into a far Heap entry
- ;Purpose:
- ; Copy data from DS into a far Heap entry
- ; Does not work with HUGE heap entries (i.e. > 64k)
- ;Entry:
- ; parm: bdl *pbdlOwner - points to owner of new heap entry
- ; parm: ushort oDst - 16 bit offset into bdl to destination
- ; parm: char *pbSrc - points to 1st byte of source
- ; parm: ushort cb - number of bytes to copy
- ;
- ;***************************************************************************
- cProc BdlCopyTo,<PUBLIC,FAR,NODATA>,<si,di>
- parmW pbdlOwner
- parmW oDst
- parmW pbSrc
- parmW cb
- cBegin
- mov si,[pbSrc] ;si = source offset
- mov di,[oDst] ;di = destination offset
- mov bx,[pbdlOwner]
- DbChk BdlOwner,bx ;ensure that bdlOwner is an owner
- GETSEG ax,[bx.BDL_seg],,<SIZE,LOAD> ;[4] seg of far heap entry
- mov es,ax ;set up destination seg
- mov bx,ds
- jmp short CopyCommon
- cEnd nogen
- ;***
- ;BdlCopyFromTo - Copy data from one bdl to another
- ;Purpose:
- ; Copy data from one far heap entry into another.
- ; Does not work with HUGE heap entries (i.e. > 64k)
- ;
- ; Added as part of revison [7]
- ;Entry:
- ; parm: bdl *pbdlSrc - points to source bdl
- ; parm: ushort oSrc - 16 bit offset into bdl to source
- ; parm: bdl *pbdlDst - points to destination bdl
- ; parm: ushort oDst - 16 bit offset into bdl to destination
- ; parm: ushort cb - number of bytes to copy
- ;Exit:
- ; none.
- ;***************************************************************************
- cProc BdlCopyFromTo,<PUBLIC,FAR,NODATA>,<si,di,ds>
- parmW pbdlSrc
- parmW oSrc
- parmW pbdlDst
- parmW oDst
- parmW cb
- cBegin
- mov si,[pbdlDst]
- DbChk BdlOwner,si ;ensure that bdlDst is an owner
- GETSEG dx,[si.BDL_seg],,<SIZE,LOAD>
- ; dx = seg of far heap entry (dst)
- mov bx,[pbdlSrc]
- DbChk BdlOwner,bx ;ensure that bdlSrc is an owner
- GETSEG ds,[bx.BDL_seg],,<SIZE,LOAD,NOFLUSH>
- ; ds = seg of far heap entry (src)
- assumes DS,NOTHING
- mov es,dx
- mov si,[oSrc] ;si = source offset
- mov di,[oDst] ;di = destination offset
- mov cx,[cb]
- shr cx,1 ;convert to word count
- rep movsw ;transfer from ds:si to es:di
- jnc CopyFrom_Even2 ;no carry if count was even
- movsb ;move the last (odd) byte
- CopyFrom_Even2:
- cEnd
- assumes DS,DATA
- ;***
- ;BdlTrim - trim given bdl down to cbLogical
- ;Purpose:
- ; Releases excess space in a given bdl
- ;Entry:
- ; parm: bdl *pbdl
- ;
- ;***************************************************************************
- cProc BdlTrim,<PUBLIC,FAR,NODATA>,<si,di>
- parmW pbdl
- cBegin
- mov bx,[pbdl]
- DbChk BdlOwner,bx ;ensure that bdlOwner is an owner
- mov ax,[bx.BDL_cbLogical] ;size to realloc to
- xor dx,dx
- call B$FHRealloc ;must succeed; we're either reducing
- ; or asking for existing entry size
- cEnd
- ;seg_rt = segment address for the RT segment
- ;It can be referenced from any module as follows:
- ; EXTRN seg_rt:abs
- ; mov ax,SEG seg_rt
- PUBLIC seg_rt
- seg_rt EQU SEG BdlTrim
- sEnd RT
- ;------------------------------------------------------------
- ;--- Interpreter Buffer Descriptor Management Routines ---
- ;------------------------------------------------------------
- sBegin DATA
- staticB bdGrabSpace,NULL,<SIZE BD>
- sEnd DATA
- sBegin CODE
- assumes CS,CODE
- CBNEAR_GRAB equ 2 * CBBUFBLOCK
- ;***
- ;GrabSpace - grab some heap space
- ;Purpose:
- ; Allocates CBNEAR_GRAB bytes via BdAlloc.
- ; Called to lock up a chunk of heap space so we ensure that
- ; enough space exists to do simple things like CLEAR for more memory!
- ;
- ; NOTE: It's important that grabspace just grab space from the near
- ; heap, not the far heap; if we grabbed far space instead,
- ; this could allow the user to tie up all of DGROUP with
- ; variable tables with plenty of DGROUP space free.
- ;Entry:
- ; none.
- ;Exit:
- ; ax = 0 if insufficient memory, else ax != 0
- ;***************************************************************************
- cProc GrabSpace,<PUBLIC,FAR,NODATA>
- cBegin
- mov ax,[bdGrabSpace.BD_pb]
- or ax,ax
- jnz GotSpace ;return ax<>0 if already have space
- PUSHI ax,<dataOFFSET bdGrabSpace>
- PUSHI ax,CBNEAR_GRAB
- PUSHI ax,IT_NO_OWNERS
- call BdAlloc
- or ax,ax
- GotSpace:
- cEnd
- ;***
- ;ReleaseSpace - Release the space grabbed by GrabSpace
- ;Purpose:
- ; Deallocates the bd allocated by GrabSpace if it is currently allocated.
- ; Note that it's perfectly o.k. to call this even when no space has
- ; been grabbed.
- ;Entry:
- ; none.
- ;Exit:
- ; ax = 0.
- ;***************************************************************************
- cProc ReleaseSpace,<PUBLIC,FAR,NODATA>
- cBegin
- PUSHI ax,<dataOFFSET bdGrabSpace>
- call BdFree ;deallocate bd if couldn't allocate bdl
- cEnd
- sEnd CODE
- end