1 ; SCCSID = @(#)alloc.asm 1.1 85/04/09
2 TITLE ALLOC
.ASM
- memory arena manager
5 ; Memory related system calls and low level routines for MSDOS 2.X.
6 ; I/O specs are defined in DISPATCH.
17 ; Modification history:
19 ; Created: ARR 30 March 1983
24 ; get the appropriate segment definitions
28 CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
39 SUBTTL memory allocation utility routines
44 i_need arena_head
,WORD ; seg address of start of arena
45 i_need CurrentPDB
,WORD ; current process data block addr
46 i_need FirstArena
,WORD ; first free block found
47 i_need BestArena
,WORD ; best free block found
48 i_need LastArena
,WORD ; last free block found
49 i_need AllocMethod
,BYTE ; how to alloc first(best)last
50 I_need EXTERR_LOCUS
,BYTE ; Extended Error Locus
54 ; input: BX - PID of process
55 ; output: free all blocks allocated to that PID
57 procedure arena_free_process
,NEAR
58 ASSUME
DS:NOTHING
,ES:NOTHING
59 MOV DI,arena_signature
61 CALL Check_Signature
; ES <- AX, check for valid block
63 arena_free_process_loop:
67 CMP DS:[arena_owner
],BX ; is block owned by pid?
68 JNZ arena_free_next
; no, skip to next
69 MOV DS:[arena_owner
],DI ; yes... free him
72 CMP BYTE PTR DS:[DI],arena_signature_end
74 retz
; never come back no more
75 CALL arena_next
; next item in ES/AX carry set if trash
76 JMP arena_free_process_loop
78 EndProc arena_free_process
82 ; input: DS - pointer to block head
83 ; output: AX,ES - pointers to next head
84 ; carry set if trashed arena
86 procedure arena_next
,NEAR
87 ASSUME
DS:NOTHING
,ES:NOTHING
88 MOV AX,DS ; AX <- current block
89 ADD AX,DS:[arena_size
] ; AX <- AX + current block length
90 INC AX ; remember that header!
92 ; fall into check_signature and return
94 ; CALL check_signature ; ES <- AX, carry set if error
100 ; input: AX - address of block header
101 ; output: ES=AX, carry set if signature is bad
103 procedure check_signature
,NEAR
104 ASSUME
DS:NOTHING
,ES:NOTHING
106 CMP BYTE PTR ES:[DI],arena_signature_normal
107 ; IF next signature = not_end THEN
109 CMP BYTE PTR ES:[DI],arena_signature_end
110 ; IF next signature = end then
115 EndProc Check_signature
118 ; Coalesce - combine free blocks ahead with current block
119 ; input: DS - pointer to head of free block
120 ; output: updated head of block, AX is next block
121 ; carry set -> trashed arena
123 procedure Coalesce
,NEAR
124 ASSUME
DS:NOTHING
,ES:NOTHING
125 CMP BYTE PTR DS:[DI],arena_signature_end
126 ; IF current signature = END THEN
128 CALL arena_next
; ES, AX <- next block, Carry set if error
129 retc
; IF no error THEN GOTO check
132 CMP ES:[arena_owner
],DI
133 retnz
; IF next block isnt free THEN return
134 MOV CX,ES:[arena_size
] ; CX <- next block size
135 INC CX ; CX <- CX + 1 (for header size)
136 ADD DS:[arena_size
],CX ; current size <- current size + CX
137 MOV CL,ES:[DI] ; move up signature
139 JMP coalesce
; try again
142 SUBTTL $Alloc
- allocate space
in memory
149 ; AX:0 is pointer to allocated memory
150 ; BX is max size if not enough memory
153 ; Alloc returns a pointer to a free block of
154 ; memory that has the requested size in paragraphs.
157 ; AX = error_not_enough_memory
158 ; = error_arena_trashed
160 procedure $ALLOC
,NEAR
161 ASSUME
DS:NOTHING
,ES:NOTHING
167 MOV [FirstArena
],AX ; init the options
171 PUSH AX ; alloc_max <- 0
172 MOV AX,[arena_head
] ; AX <- beginning of arena
173 CALL Check_signature
; ES <- AX, carry set if error
174 JC alloc_err
; IF error THEN GOTO err
179 CMP DS:[arena_owner
],DI
180 JZ alloc_free
; IF current block is free THEN examine
183 CMP BYTE PTR DS:[DI],arena_signature_end
184 ; IF current block is last THEN
185 JZ alloc_end
; GOTO end
186 CALL arena_next
; AX, ES <- next block, Carry set if error
187 JNC alloc_scan
; IF no error THEN GOTO scan
194 error error_arena_trashed
201 invoke get_user_stack
205 error error_not_enough_memory
208 CALL coalesce
; add following free block to current
209 JC alloc_err
; IF error THEN GOTO err
210 MOV CX,DS:[arena_size
]
212 POP DX ; check for max found size
219 CMP BX,CX ; IF BX > size of current block THEN
220 JA alloc_next
; GOTO next
224 MOV [FirstArena
],DS ; save first one found
227 JZ alloc_make_best
; initial best
230 CMP ES:[arena_size
],CX ; is size of best larger than found?
234 MOV [BestArena
],DS ; assign best
236 MOV [LastArena
],DS ; assign last
240 ; split the block high
244 MOV CX,DS:[arena_size
]
247 JE alloc_set_owner
; sizes are equal, no split
248 ADD DX,CX ; point to next block
249 MOV ES,DX ; no decrement!
251 XCHG BX,CX ; bx has size of lower block
252 JMP alloc_set_sizes
; cx has upper (requested) size
255 ; we have scanned memory and have found all appropriate blocks
256 ; check for the type of allocation desired; first and best are identical
257 ; last must be split high
260 CMP BYTE PTR [AllocMethod
], 1
261 JA alloc_do_split_high
266 MOV CX,DS:[arena_size
]
267 SUB CX,BX ; get room left over
269 MOV DX,AX ; save for owner setting
270 JE alloc_set_owner
; IF BX = size THEN (don't split)
272 INC AX ; remember the header
273 MOV ES,AX ; ES <- DS + BX (new header location)
274 DEC CX ; CX <- size of split block
276 MOV DS:[arena_size
],BX ; current size <- BX
277 MOV ES:[arena_size
],CX ; split size <- CX
278 MOV BL,arena_signature_normal
279 XCHG BL,DS:[DI] ; current signature <- 4D
280 MOV ES:[DI],BL ; new block sig <- old block sig
281 MOV ES:[arena_owner
],DI
286 MOV DS:[arena_owner
],AX
295 SUBTTL $SETBLOCK
- change size of an allocated block
(if possible
)
303 ; if setblock fails for growing, BX will have the maximum
306 ; AX = error_invalid_block
307 ; = error_arena_trashed
308 ; = error_not_enough_memory
309 ; = error_invalid_function
311 procedure $SETBLOCK
,NEAR
312 ASSUME
DS:NOTHING
,ES:NOTHING
314 MOV DI,arena_signature
327 MOV CX,DS:[arena_size
]
334 SUBTTL $DEALLOC
- free previously allocated piece of memory
343 ; AX = error_invalid_block
344 ; = error_arena_trashed
346 procedure $DEALLOC
,NEAR
347 ASSUME
DS:NOTHING
,ES:NOTHING
349 MOV DI,arena_signature
354 MOV ES:[arena_owner
],DI
360 error error_invalid_block
363 SUBTTL $AllocOper
- get
/set allocation mechanism
373 ; AX = error_invalid_function
375 procedure $AllocOper
,NEAR
376 ASSUME
DS:NOTHING
,ES:NOTHING
380 MOV EXTERR_LOCUS
,errLoc_mem
; Extended Error Locus
381 error error_invalid_function
383 MOV AL,BYTE PTR [AllocMethod
]