220 lines
5.6 KiB
NASM
220 lines
5.6 KiB
NASM
|
;
|
||
|
; --------------------------------------------------
|
||
|
; free - release a block of heap
|
||
|
; --------------------------------------------------
|
||
|
;
|
||
|
IDT cfree
|
||
|
DEF cfree
|
||
|
DEF free
|
||
|
DEF _nfree
|
||
|
IF UPPER
|
||
|
DEF CFREE
|
||
|
DEF FREE
|
||
|
ENDIF
|
||
|
FREF $$FREE$$
|
||
|
;
|
||
|
; free(ptr) - release a block of heap
|
||
|
;
|
||
|
cfree equ $
|
||
|
CFREE EQU $
|
||
|
free equ $
|
||
|
_nfree equ $
|
||
|
FREE MOV SI,SP
|
||
|
MOV BX,[SI][%PARM1-2]
|
||
|
CALLFAR $$FREE$$
|
||
|
XOR AX,AX
|
||
|
RETSEG
|
||
|
END
|
||
|
;
|
||
|
; $_FREE(ptr);
|
||
|
; ptr is address of a pointer
|
||
|
; block is released and pointer set to nil
|
||
|
;
|
||
|
IDT $_free
|
||
|
DEF $_FREE
|
||
|
FREF $$FREE$$
|
||
|
$_FREE PUSH BP
|
||
|
MOV BP,SP
|
||
|
MOV BX,[BP][%PARM1] ; pointer address
|
||
|
MOV BX,[BX] ; value of pointer
|
||
|
CALLFAR $$FREE$$
|
||
|
MOV BX,[BP][%PARM1] ; pointer address
|
||
|
MOV [BX],0
|
||
|
POP BP
|
||
|
RETSEG
|
||
|
END
|
||
|
;
|
||
|
; ------------------------------------------------------------
|
||
|
;
|
||
|
; FREE$$
|
||
|
; RELEASE A HEAP PACKET
|
||
|
; INPUTS:
|
||
|
; BX - POINTER TO THE PACKET BEGIN RETURNED
|
||
|
; OUTPUTS:
|
||
|
; NONE
|
||
|
; REGISTERS USED:
|
||
|
; DI, SI, BP ARE PRESERVED
|
||
|
;
|
||
|
;
|
||
|
IDT $$FREE$$
|
||
|
DEF $$FREE$$
|
||
|
REF $$HPTERM
|
||
|
FREF $_FATAL
|
||
|
REF $$HMIN
|
||
|
REF $$HMAX
|
||
|
REF $$CURH
|
||
|
REF $$FREE
|
||
|
REF errno
|
||
|
;
|
||
|
; CHECK FOR SIZE, NIL POINTER
|
||
|
;
|
||
|
$$FREE$$ TEST BX,BX
|
||
|
JNZ FREE01
|
||
|
RETSEG ; NIL - EXIT
|
||
|
FREE01 SUB BX,%2 ; POINT TO LENGTH FIELD
|
||
|
;
|
||
|
; CHECK POINTER AGAINST LOWER BOUND OF HEAP - ERROR IF LESS
|
||
|
;
|
||
|
CMP BX,[$$HMIN]
|
||
|
JB INVPKT
|
||
|
;
|
||
|
; GET LENGTH OF THE PACKET
|
||
|
;
|
||
|
FR01 MOV CX,[BX]
|
||
|
TEST CL,%1 ; CHECK ALLOCATED FLAG
|
||
|
JZ INVPKT ; NOT ALLOCATED
|
||
|
AND CL,%>FE ; RESET ALLOCATION FLAG
|
||
|
MOV AX,BX
|
||
|
ADD AX,CX ; AX POINTS TO NEXT PACKET
|
||
|
;
|
||
|
; CHECK PTR + SIZE OF PACKET AGAINST HEAP UPPER BOUND
|
||
|
;
|
||
|
CMP AX,[$$HMAX]
|
||
|
JA INVPKT
|
||
|
;
|
||
|
; BX = ADDRESS OF RELEASED PACKET
|
||
|
; CX = SIZE OF RELEASED PACKET
|
||
|
; AX = ADDRESS OF NEXT PACKET
|
||
|
;
|
||
|
; PACKET IS VALID, RELEASE IT
|
||
|
;
|
||
|
FR02 SUB [$$CURH],CX ; SUBTRACT FROM CURRENT
|
||
|
;
|
||
|
; IS NEXT PACKET ALLOCATED?
|
||
|
;
|
||
|
MOV DX,BX
|
||
|
MOV BX,AX
|
||
|
TEST [BX],%1 ; CHECK ALLOCATION FLAG
|
||
|
JNZ FR03 ; ALLOCATED
|
||
|
;
|
||
|
; NEXT PACKET IS AVAILABLE, MERGE CURRENT AND NEXT PACKETS
|
||
|
;
|
||
|
MOV AX,[BX] ; GET SIZE OF NEXT PACKET
|
||
|
TEST AX,AX ; CHECK FOR ZERO
|
||
|
JZ FR03 ; DON'T MERGE WITH ANCHOR
|
||
|
ADD CX,AX ; CX = SIZE OF COMBINATION
|
||
|
;
|
||
|
; ASSIGN FREELIST TO NEW PACKET
|
||
|
;
|
||
|
MOV [$$FREE],DX
|
||
|
;
|
||
|
; FIND THE PREVIOUS PACKET THAT IS FREE AND CLOSEST
|
||
|
; TO THE PACKET BEING RELEASED
|
||
|
;
|
||
|
MOV AX,[BX][2] ; GET NEXT FIELD FOR CURRENT
|
||
|
MOV BX,[BX][4] ; PREV LINK OF NEXT FREE PKT
|
||
|
;
|
||
|
; AT THIS POINT:
|
||
|
; DX = CURRENT PACKET
|
||
|
; AX = NEXT PACKET
|
||
|
; BX = PREVIOUS PACKET
|
||
|
; CX = LENGTH OF CURRENT
|
||
|
;
|
||
|
JMPS FR05 ; CHECK FOR LAST PACKET FREE
|
||
|
;
|
||
|
; NEXT PACKET IS NOT AVAILABLE
|
||
|
; FIND THE NEXT PACKET THAT IS AVAILABLE TO GET
|
||
|
; ITS LAST PACKET POINTER
|
||
|
; BX = NEXT PACKET
|
||
|
; CX = PACKET SIZE
|
||
|
; DX = CURRENT PACKET
|
||
|
;
|
||
|
FR03 MOV AX,[BX] ; GET SIZE OF NEXT PACKET
|
||
|
AND AL,%>FE ; REMOVE ALLOCATION FLAG
|
||
|
ADD BX,AX ; POINT TO FOLLOWING
|
||
|
TEST [BX],%1 ; CHECK NEXT PACKET ALLOCATION
|
||
|
JNZ FR03 ; LOOP UNTIL FREE
|
||
|
;
|
||
|
; BX NOW POINTS TO THE NEXT FREE PACKET
|
||
|
; GET THE LAST POINTER FROM THE NEXT PACKET
|
||
|
;
|
||
|
MOV AX,BX
|
||
|
MOV BX,[BX][4] ; GET PREV POINTER
|
||
|
;
|
||
|
; AT THIS POINT:
|
||
|
; AX = NEXT PACKET
|
||
|
; CX = PACKET LENGTH
|
||
|
; DX = CURRENT PACKET
|
||
|
; BX = LAST PACKET
|
||
|
;
|
||
|
;
|
||
|
; CHECK LAST PACKET. IF THE LAST FREE PACKET IS CONTIGUOUS
|
||
|
; WITH THE CURRENT PACKET, THEY CAN BE MERGED INTO A SINGLE
|
||
|
; PACKET.
|
||
|
;
|
||
|
FR05 PUSH AX ; SAVE
|
||
|
MOV AX,[BX] ; LENGTH OF PREVIOUS PKT
|
||
|
ADD AX,BX ; AX <-- LAST+SIZE(LAST)
|
||
|
CMP AX,DX
|
||
|
JNZ FR06 ; CAN NOT JOIN
|
||
|
;
|
||
|
; THE LAST PACKET IS CONTIGUOUS WITH THE CURRENT PACKET,
|
||
|
; MERGE THEM.
|
||
|
;
|
||
|
ADD CX,[BX] ; ADD LENGTHS
|
||
|
MOV [BX],CX ; SET TOTAL LENGTH
|
||
|
POP AX
|
||
|
MOV [BX][2],AX ; SET NEXT PKT POINTER
|
||
|
XCHG BX,AX
|
||
|
MOV [BX][4],AX ; SET NEXT@.LAST TO MERGED PKT
|
||
|
;
|
||
|
; SET FREE LIST TO MERGED PACKET
|
||
|
;
|
||
|
MOV [$$FREE],AX
|
||
|
RETSEG ; DONE
|
||
|
;
|
||
|
;
|
||
|
; THE LAST PACKET IS NOT CONTIGUOUS WITH THE CURRENT PACKET
|
||
|
; A NEW PACKET IS CREATED FOR THE PACKET BEING RELEASED.
|
||
|
;
|
||
|
; TOS = NEXT
|
||
|
; DX = CURRENT
|
||
|
; BX = PREVIOUS
|
||
|
; CX = LENGTH
|
||
|
;
|
||
|
FR06 XCHG BX,DX
|
||
|
MOV [BX],CX ; SET SIZE
|
||
|
POP AX
|
||
|
MOV [BX][2],AX ; SET NEXT POINTER
|
||
|
MOV [BX][4],DX ; SET PREVIOUS
|
||
|
XCHG BX,DX
|
||
|
MOV [BX][2],DX ; SET PREV@.NEXT
|
||
|
MOV BX,AX
|
||
|
MOV [BX][4],DX ; SET NEXT@.LAST
|
||
|
;
|
||
|
; DONE
|
||
|
;
|
||
|
FREEX RETSEG
|
||
|
;
|
||
|
; INVALID PACKET POINTER
|
||
|
;
|
||
|
INVPKT MOV AX,E$PACKET
|
||
|
MOV %[errno],AL
|
||
|
TEST %[$$HPTERM],%>FF
|
||
|
JZ FREEX
|
||
|
PUSH AX
|
||
|
CALLFAR $_FATAL
|
||
|
POP AX
|
||
|
RETSEG
|
||
|
END
|