summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/ALLOC.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS/ALLOC.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-2d04cacc5322951f187bb17e017c12920ac8ebe2.tar.gz
ms-dos-2d04cacc5322951f187bb17e017c12920ac8ebe2.tar.xz
ms-dos-2d04cacc5322951f187bb17e017c12920ac8ebe2.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/DOS/ALLOC.ASM')
-rw-r--r--v4.0/src/DOS/ALLOC.ASM392
1 files changed, 392 insertions, 0 deletions
diff --git a/v4.0/src/DOS/ALLOC.ASM b/v4.0/src/DOS/ALLOC.ASM
new file mode 100644
index 0000000..37b6298
--- /dev/null
+++ b/v4.0/src/DOS/ALLOC.ASM
@@ -0,0 +1,392 @@
1; SCCSID = @(#)alloc.asm 1.1 85/04/09
2TITLE ALLOC.ASM - memory arena manager
3NAME Alloc
4;
5; Memory related system calls and low level routines for MSDOS 2.X.
6; I/O specs are defined in DISPATCH.
7;
8; $ALLOC
9; $SETBLOCK
10; $DEALLOC
11; $AllocOper
12; arena_free_process
13; arena_next
14; check_signature
15; Coalesce
16;
17; Modification history:
18;
19; Created: ARR 30 March 1983
20;
21
22.xlist
23;
24; get the appropriate segment definitions
25;
26include dosseg.asm
27
28CODE SEGMENT BYTE PUBLIC 'CODE'
29 ASSUME SS:DOSGROUP,CS:DOSGROUP
30
31.xcref
32INCLUDE DOSSYM.INC
33INCLUDE DEVSYM.INC
34.cref
35.list
36
37.lall
38
39SUBTTL memory allocation utility routines
40PAGE
41;
42; arena data
43;
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
51
52;
53; arena_free_process
54; input: BX - PID of process
55; output: free all blocks allocated to that PID
56;
57 procedure arena_free_process,NEAR
58 ASSUME DS:NOTHING,ES:NOTHING
59 MOV DI,arena_signature
60 MOV AX,[arena_head]
61 CALL Check_Signature ; ES <- AX, check for valid block
62
63arena_free_process_loop:
64 retc
65 PUSH ES
66 POP DS
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
70
71arena_free_next:
72 CMP BYTE PTR DS:[DI],arena_signature_end
73 ; end of road, Jack?
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
77
78EndProc arena_free_process
79
80;
81; arena_next
82; input: DS - pointer to block head
83; output: AX,ES - pointers to next head
84; carry set if trashed arena
85;
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!
91;
92; fall into check_signature and return
93;
94; CALL check_signature ; ES <- AX, carry set if error
95; RET
96EndProc arena_next
97
98;
99; check_signature
100; input: AX - address of block header
101; output: ES=AX, carry set if signature is bad
102;
103 procedure check_signature,NEAR
104 ASSUME DS:NOTHING,ES:NOTHING
105 MOV ES,AX ; ES <- AX
106 CMP BYTE PTR ES:[DI],arena_signature_normal
107 ; IF next signature = not_end THEN
108 retz ; GOTO ok
109 CMP BYTE PTR ES:[DI],arena_signature_end
110 ; IF next signature = end then
111 retz ; GOTO ok
112 STC ; set error
113 return
114
115EndProc Check_signature
116
117;
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
122;
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
127 retz ; GOTO ok
128 CALL arena_next ; ES, AX <- next block, Carry set if error
129 retc ; IF no error THEN GOTO check
130
131coalesce_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
138 MOV DS:[DI],CL
139 JMP coalesce ; try again
140EndProc Coalesce
141
142SUBTTL $Alloc - allocate space in memory
143PAGE
144;
145; Assembler usage:
146; MOV BX,size
147; MOV AH,Alloc
148; INT 21h
149; AX:0 is pointer to allocated memory
150; BX is max size if not enough memory
151;
152; Description:
153; Alloc returns a pointer to a free block of
154; memory that has the requested size in paragraphs.
155;
156; Error return:
157; AX = error_not_enough_memory
158; = error_arena_trashed
159;
160 procedure $ALLOC,NEAR
161 ASSUME DS:NOTHING,ES:NOTHING
162
163 EnterCrit critMem
164 XOR AX,AX
165 MOV DI,AX
166
167 MOV [FirstArena],AX ; init the options
168 MOV [BestArena],AX
169 MOV [LastArena],AX
170
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
175
176alloc_scan:
177 PUSH ES
178 POP DS ; DS <- ES
179 CMP DS:[arena_owner],DI
180 JZ alloc_free ; IF current block is free THEN examine
181
182alloc_next:
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
188
189alloc_err:
190 POP AX
191
192alloc_trashed:
193 LeaveCrit critMem
194 error error_arena_trashed
195
196alloc_end:
197 CMP [FirstArena],0
198 JNZ alloc_do_split
199
200alloc_fail:
201 invoke get_user_stack
202 POP BX
203 MOV [SI].user_BX,BX
204 LeaveCrit critMem
205 error error_not_enough_memory
206
207alloc_free:
208 CALL coalesce ; add following free block to current
209 JC alloc_err ; IF error THEN GOTO err
210 MOV CX,DS:[arena_size]
211
212 POP DX ; check for max found size
213 CMP CX,DX
214 JNA alloc_test
215 MOV DX,CX
216
217alloc_test:
218 PUSH DX
219 CMP BX,CX ; IF BX > size of current block THEN
220 JA alloc_next ; GOTO next
221
222 CMP [FirstArena],0
223 JNZ alloc_best
224 MOV [FirstArena],DS ; save first one found
225alloc_best:
226 CMP [BestArena],0
227 JZ alloc_make_best ; initial best
228 PUSH ES
229 MOV ES,[BestArena]
230 CMP ES:[arena_size],CX ; is size of best larger than found?
231 POP ES
232 JBE alloc_last
233alloc_make_best:
234 MOV [BestArena],DS ; assign best
235alloc_last:
236 MOV [LastArena],DS ; assign last
237 JMP alloc_next
238
239;
240; split the block high
241;
242alloc_do_split_high:
243 MOV DS,[LastArena]
244 MOV CX,DS:[arena_size]
245 SUB CX,BX
246 MOV DX,DS
247 JE alloc_set_owner ; sizes are equal, no split
248 ADD DX,CX ; point to next block
249 MOV ES,DX ; no decrement!
250 DEC CX
251 XCHG BX,CX ; bx has size of lower block
252 JMP alloc_set_sizes ; cx has upper (requested) size
253
254;
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
258;
259alloc_do_split:
260 CMP BYTE PTR [AllocMethod], 1
261 JA alloc_do_split_high
262 MOV DS,[FirstArena]
263 JB alloc_get_size
264 MOV DS,[BestArena]
265alloc_get_size:
266 MOV CX,DS:[arena_size]
267 SUB CX,BX ; get room left over
268 MOV AX,DS
269 MOV DX,AX ; save for owner setting
270 JE alloc_set_owner ; IF BX = size THEN (don't split)
271 ADD AX,BX
272 INC AX ; remember the header
273 MOV ES,AX ; ES <- DS + BX (new header location)
274 DEC CX ; CX <- size of split block
275alloc_set_sizes:
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
282
283alloc_set_owner:
284 MOV DS,DX
285 MOV AX,[CurrentPDB]
286 MOV DS:[arena_owner],AX
287 MOV AX,DS
288 INC AX
289 POP BX
290 LeaveCrit critMem
291 transfer SYS_RET_OK
292
293EndProc $alloc
294
295SUBTTL $SETBLOCK - change size of an allocated block (if possible)
296PAGE
297;
298; Assembler usage:
299; MOV ES,block
300; MOV BX,newsize
301; MOV AH,setblock
302; INT 21h
303; if setblock fails for growing, BX will have the maximum
304; size possible
305; Error return:
306; AX = error_invalid_block
307; = error_arena_trashed
308; = error_not_enough_memory
309; = error_invalid_function
310;
311 procedure $SETBLOCK,NEAR
312 ASSUME DS:NOTHING,ES:NOTHING
313 EnterCrit critMem
314 MOV DI,arena_signature
315 MOV AX,ES
316 DEC AX
317 CALL check_signature
318 JNC setblock_grab
319
320setblock_bad:
321 JMP alloc_trashed
322
323setblock_grab:
324 MOV DS,AX
325 CALL coalesce
326 JC setblock_bad
327 MOV CX,DS:[arena_size]
328 PUSH CX
329 CMP BX,CX
330 JBE alloc_get_size
331 JMP alloc_fail
332EndProc $setblock
333
334SUBTTL $DEALLOC - free previously allocated piece of memory
335PAGE
336;
337; Assembler usage:
338; MOV ES,block
339; MOV AH,dealloc
340; INT 21h
341;
342; Error return:
343; AX = error_invalid_block
344; = error_arena_trashed
345;
346 procedure $DEALLOC,NEAR
347 ASSUME DS:NOTHING,ES:NOTHING
348 EnterCrit critMem
349 MOV DI,arena_signature
350 MOV AX,ES
351 DEC AX
352 CALL check_signature
353 JC dealloc_err
354 MOV ES:[arena_owner],DI
355 LeaveCrit critMem
356 transfer SYS_RET_OK
357
358dealloc_err:
359 LeaveCrit critMem
360 error error_invalid_block
361EndProc $DEALLOC
362
363SUBTTL $AllocOper - get/set allocation mechanism
364PAGE
365;
366; Assembler usage:
367; MOV AH,AllocOper
368; MOV BX,method
369; MOV AL,func
370; INT 21h
371;
372; Error return:
373; AX = error_invalid_function
374;
375 procedure $AllocOper,NEAR
376 ASSUME DS:NOTHING,ES:NOTHING
377 CMP AL,1
378 JB AllocOperGet
379 JZ AllocOperSet
380 MOV EXTERR_LOCUS,errLoc_mem ; Extended Error Locus
381 error error_invalid_function
382AllocOperGet:
383 MOV AL,BYTE PTR [AllocMethod]
384 XOR AH,AH
385 transfer SYS_RET_OK
386AllocOperSet:
387 MOV [AllocMethod],BL
388 transfer SYS_RET_OK
389EndProc $AllocOper
390
391CODE ENDS
392 END