2 ; xenix memory calls for MSDOS
4 ; CAUTION: The following routines rely on the fact that arena_signature and
5 ; arena_owner_system are all equal to zero and are contained in DI.
9 CODE SEGMENT BYTE PUBLIC 'CODE'
10 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
19 TITLE ALLOC
.ASM
- memory arena manager
22 SUBTTL memory allocation utility routines
27 i_need arena_head
,WORD ; seg address of start of arena
28 i_need CurrentPDB
,WORD ; current process data block addr
29 i_need FirstArena
,WORD ; first free block found
30 i_need BestArena
,WORD ; best free block found
31 i_need LastArena
,WORD ; last free block found
32 i_need AllocMethod
,BYTE ; how to alloc first(best)last
36 ; input: BX - PID of process
37 ; output: free all blocks allocated to that PID
39 procedure arena_free_process
,NEAR
40 ASSUME
DS:NOTHING
,ES:NOTHING
41 MOV DI,arena_signature
43 CALL Check_Signature
; ES <- AX, check for valid block
45 arena_free_process_loop:
49 CMP DS:[arena_owner
],BX ; is block owned by pid?
50 JNZ arena_free_next
; no, skip to next
51 MOV DS:[arena_owner
],DI ; yes... free him
54 CMP BYTE PTR DS:[DI],arena_signature_end
56 retz
; never come back no more
57 CALL arena_next
; next item in ES/AX carry set if trash
58 JMP arena_free_process_loop
60 arena_free_process ENDP
64 ; input: DS - pointer to block head
65 ; output: AX,ES - pointers to next head
66 ; carry set if trashed arena
68 procedure arena_next
,NEAR
69 ASSUME
DS:NOTHING
,ES:NOTHING
70 MOV AX,DS ; AX <- current block
71 ADD AX,DS:[arena_size
] ; AX <- AX + current block length
72 INC AX ; remember that header!
74 ; fall into check_signature and return
76 ; CALL check_signature ; ES <- AX, carry set if error
82 ; input: AX - address of block header
83 ; output: ES=AX, carry set if signature is bad
85 procedure check_signature
,NEAR
86 ASSUME
DS:NOTHING
,ES:NOTHING
88 CMP BYTE PTR ES:[DI],arena_signature_normal
89 ; IF next signature = not_end THEN
90 JZ check_signature_ok
; GOTO ok
91 CMP BYTE PTR ES:[DI],arena_signature_end
92 ; IF next signature = end then
93 JZ check_signature_ok
; GOTO ok
103 ; Coalesce - combine free blocks ahead with current block
104 ; input: DS - pointer to head of free block
105 ; output: updated head of block, AX is next block
106 ; carry set -> trashed arena
108 procedure Coalesce
,NEAR
109 ASSUME
DS:NOTHING
,ES:NOTHING
110 CMP BYTE PTR DS:[DI],arena_signature_end
111 ; IF current signature = END THEN
113 CALL arena_next
; ES, AX <- next block, Carry set if error
114 retc
; IF no error THEN GOTO check
117 CMP ES:[arena_owner
],DI
118 retnz
; IF next block isnt free THEN return
119 MOV CX,ES:[arena_size
] ; CX <- next block size
120 INC CX ; CX <- CX + 1 (for header size)
121 ADD DS:[arena_size
],CX ; current size <- current size + CX
122 MOV CL,ES:[DI] ; move up signature
124 JMP coalesce
; try again
127 SUBTTL $Alloc
- allocate space
in memory
134 ; AX:0 is pointer to allocated memory
135 ; BX is max size if not enough memory
138 ; Alloc returns a pointer to a free block of
139 ; memory that has the requested size in paragraphs.
142 ; AX = error_not_enough_memory
143 ; = error_arena_trashed
145 procedure $ALLOC
,NEAR
146 ASSUME
DS:NOTHING
,ES:NOTHING
151 MOV [FirstArena
],AX ; init the options
155 PUSH AX ; alloc_max <- 0
156 MOV AX,[arena_head
] ; AX <- beginning of arena
157 CALL Check_signature
; ES <- AX, carry set if error
158 JC alloc_err
; IF error THEN GOTO err
163 CMP DS:[arena_owner
],DI
164 JZ alloc_free
; IF current block is free THEN examine
167 CMP BYTE PTR DS:[DI],arena_signature_end
168 ; IF current block is last THEN
169 JZ alloc_end
; GOTO end
170 CALL arena_next
; AX, ES <- next block, Carry set if error
171 JNC alloc_scan
; IF no error THEN GOTO scan
177 error error_arena_trashed
184 invoke get_user_stack
187 error error_not_enough_memory
190 CALL coalesce
; add following free block to current
191 JC alloc_err
; IF error THEN GOTO err
192 MOV CX,DS:[arena_size
]
194 POP DX ; check for max found size
201 CMP BX,CX ; IF BX > size of current block THEN
202 JA alloc_next
; GOTO next
206 MOV [FirstArena
],DS ; save first one found
209 JZ alloc_make_best
; initial best
212 CMP ES:[arena_size
],CX ; is size of best larger than found?
216 MOV [BestArena
],DS ; assign best
218 MOV [LastArena
],DS ; assign last
222 ; split the block high
226 MOV CX,DS:[arena_size
]
229 JE alloc_set_owner
; sizes are equal, no split
230 ADD DX,CX ; point to next block
231 MOV ES,DX ; no decrement!
233 XCHG BX,CX ; bx has size of lower block
234 JMP alloc_set_sizes
; cx has upper (requested) size
237 ; we have scanned memory and have found all appropriate blocks
238 ; check for the type of allocation desired; first and best are identical
239 ; last must be split high
242 CMP BYTE PTR [AllocMethod
], 1
243 JA alloc_do_split_high
248 MOV CX,DS:[arena_size
]
249 SUB CX,BX ; get room left over
251 MOV DX,AX ; save for owner setting
252 JE alloc_set_owner
; IF BX = size THEN (don't split)
254 INC AX ; remember the header
255 MOV ES,AX ; ES <- DS + BX (new header location)
256 DEC CX ; CX <- size of split block
258 MOV DS:[arena_size
],BX ; current size <- BX
259 MOV ES:[arena_size
],CX ; split size <- CX
260 MOV BL,arena_signature_normal
261 XCHG BL,DS:[DI] ; current signature <- 4D
262 MOV ES:[DI],BL ; new block sig <- old block sig
263 MOV ES:[arena_owner
],DI
268 MOV DS:[arena_owner
],AX
276 SUBTTL $SETBLOCK
- change size of an allocated block
(if possible
)
284 ; if setblock fails for growing, BX will have the maximum
287 ; AX = error_invalid_block
288 ; = error_arena_trashed
289 ; = error_not_enough_memory
290 ; = error_invalid_function
292 procedure $SETBLOCK
,NEAR
293 ASSUME
DS:NOTHING
,ES:NOTHING
294 MOV DI,arena_signature
307 MOV CX,DS:[arena_size
]
314 SUBTTL $DEALLOC
- free previously allocated piece of memory
323 ; AX = error_invalid_block
324 ; = error_arena_trashed
326 procedure $DEALLOC
,NEAR
327 ASSUME
DS:NOTHING
,ES:NOTHING
328 MOV DI,arena_signature
333 MOV ES:[arena_owner
],DI
337 error error_invalid_block
340 SUBTTL $AllocOper
- get
/set allocation mechanism
350 ; AX = error_invalid_function
352 procedure $AllocOper
,NEAR
353 ASSUME
DS:NOTHING
,ES:NOTHING
357 error error_invalid_function
359 MOV AL,BYTE PTR [AllocMethod
]