summaryrefslogtreecommitdiff
path: root/v2.0/source/ALLOC.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v2.0/source/ALLOC.ASM')
-rw-r--r--v2.0/source/ALLOC.ASM371
1 files changed, 371 insertions, 0 deletions
diff --git a/v2.0/source/ALLOC.ASM b/v2.0/source/ALLOC.ASM
new file mode 100644
index 0000000..7b69826
--- /dev/null
+++ b/v2.0/source/ALLOC.ASM
@@ -0,0 +1,371 @@
1;
2; xenix memory calls for MSDOS
3;
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.
6;
7INCLUDE DOSSEG.ASM
8
9CODE SEGMENT BYTE PUBLIC 'CODE'
10 ASSUME SS:DOSGROUP,CS:DOSGROUP
11
12.xlist
13.xcref
14INCLUDE DOSSYM.ASM
15INCLUDE DEVSYM.ASM
16.cref
17.list
18
19TITLE ALLOC.ASM - memory arena manager
20NAME Alloc
21
22SUBTTL memory allocation utility routines
23PAGE
24;
25; arena data
26;
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
33
34;
35; arena_free_process
36; input: BX - PID of process
37; output: free all blocks allocated to that PID
38;
39 procedure arena_free_process,NEAR
40 ASSUME DS:NOTHING,ES:NOTHING
41 MOV DI,arena_signature
42 MOV AX,[arena_head]
43 CALL Check_Signature ; ES <- AX, check for valid block
44
45arena_free_process_loop:
46 retc
47 PUSH ES
48 POP DS
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
52
53arena_free_next:
54 CMP BYTE PTR DS:[DI],arena_signature_end
55 ; end of road, Jack?
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
59
60arena_free_process ENDP
61
62;
63; arena_next
64; input: DS - pointer to block head
65; output: AX,ES - pointers to next head
66; carry set if trashed arena
67;
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!
73;
74; fall into check_signature and return
75;
76; CALL check_signature ; ES <- AX, carry set if error
77; RET
78arena_next ENDP
79
80;
81; check_signature
82; input: AX - address of block header
83; output: ES=AX, carry set if signature is bad
84;
85 procedure check_signature,NEAR
86 ASSUME DS:NOTHING,ES:NOTHING
87 MOV ES,AX ; ES <- AX
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
94 STC ; set error
95 return
96
97check_signature_ok:
98 CLC
99 return
100Check_signature ENDP
101
102;
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
107;
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
112 retz ; GOTO ok
113 CALL arena_next ; ES, AX <- next block, Carry set if error
114 retc ; IF no error THEN GOTO check
115
116coalesce_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
123 MOV DS:[DI],CL
124 JMP coalesce ; try again
125Coalesce ENDP
126
127SUBTTL $Alloc - allocate space in memory
128PAGE
129;
130; Assembler usage:
131; MOV BX,size
132; MOV AH,Alloc
133; INT 21h
134; AX:0 is pointer to allocated memory
135; BX is max size if not enough memory
136;
137; Description:
138; Alloc returns a pointer to a free block of
139; memory that has the requested size in paragraphs.
140;
141; Error return:
142; AX = error_not_enough_memory
143; = error_arena_trashed
144;
145 procedure $ALLOC,NEAR
146 ASSUME DS:NOTHING,ES:NOTHING
147
148 XOR AX,AX
149 MOV DI,AX
150
151 MOV [FirstArena],AX ; init the options
152 MOV [BestArena],AX
153 MOV [LastArena],AX
154
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
159
160alloc_scan:
161 PUSH ES
162 POP DS ; DS <- ES
163 CMP DS:[arena_owner],DI
164 JZ alloc_free ; IF current block is free THEN examine
165
166alloc_next:
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
172
173alloc_err:
174 POP AX
175
176alloc_trashed:
177 error error_arena_trashed
178
179alloc_end:
180 CMP [FirstArena],0
181 JNZ alloc_do_split
182
183alloc_fail:
184 invoke get_user_stack
185 POP BX
186 MOV [SI].user_BX,BX
187 error error_not_enough_memory
188
189alloc_free:
190 CALL coalesce ; add following free block to current
191 JC alloc_err ; IF error THEN GOTO err
192 MOV CX,DS:[arena_size]
193
194 POP DX ; check for max found size
195 CMP CX,DX
196 JNA alloc_test
197 MOV DX,CX
198
199alloc_test:
200 PUSH DX
201 CMP BX,CX ; IF BX > size of current block THEN
202 JA alloc_next ; GOTO next
203
204 CMP [FirstArena],0
205 JNZ alloc_best
206 MOV [FirstArena],DS ; save first one found
207alloc_best:
208 CMP [BestArena],0
209 JZ alloc_make_best ; initial best
210 PUSH ES
211 MOV ES,[BestArena]
212 CMP ES:[arena_size],CX ; is size of best larger than found?
213 POP ES
214 JBE alloc_last
215alloc_make_best:
216 MOV [BestArena],DS ; assign best
217alloc_last:
218 MOV [LastArena],DS ; assign last
219 JMP alloc_next
220
221;
222; split the block high
223;
224alloc_do_split_high:
225 MOV DS,[LastArena]
226 MOV CX,DS:[arena_size]
227 SUB CX,BX
228 MOV DX,DS
229 JE alloc_set_owner ; sizes are equal, no split
230 ADD DX,CX ; point to next block
231 MOV ES,DX ; no decrement!
232 DEC CX
233 XCHG BX,CX ; bx has size of lower block
234 JMP alloc_set_sizes ; cx has upper (requested) size
235
236;
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
240;
241alloc_do_split:
242 CMP BYTE PTR [AllocMethod], 1
243 JA alloc_do_split_high
244 MOV DS,[FirstArena]
245 JB alloc_get_size
246 MOV DS,[BestArena]
247alloc_get_size:
248 MOV CX,DS:[arena_size]
249 SUB CX,BX ; get room left over
250 MOV AX,DS
251 MOV DX,AX ; save for owner setting
252 JE alloc_set_owner ; IF BX = size THEN (don't split)
253 ADD AX,BX
254 INC AX ; remember the header
255 MOV ES,AX ; ES <- DS + BX (new header location)
256 DEC CX ; CX <- size of split block
257alloc_set_sizes:
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
264
265alloc_set_owner:
266 MOV DS,DX
267 MOV AX,[CurrentPDB]
268 MOV DS:[arena_owner],AX
269 MOV AX,DS
270 INC AX
271 POP BX
272 transfer SYS_RET_OK
273
274$alloc ENDP
275
276SUBTTL $SETBLOCK - change size of an allocated block (if possible)
277PAGE
278;
279; Assembler usage:
280; MOV ES,block
281; MOV BX,newsize
282; MOV AH,setblock
283; INT 21h
284; if setblock fails for growing, BX will have the maximum
285; size possible
286; Error return:
287; AX = error_invalid_block
288; = error_arena_trashed
289; = error_not_enough_memory
290; = error_invalid_function
291;
292 procedure $SETBLOCK,NEAR
293 ASSUME DS:NOTHING,ES:NOTHING
294 MOV DI,arena_signature
295 MOV AX,ES
296 DEC AX
297 CALL check_signature
298 JNC setblock_grab
299
300setblock_bad:
301 JMP alloc_trashed
302
303setblock_grab:
304 MOV DS,AX
305 CALL coalesce
306 JC setblock_bad
307 MOV CX,DS:[arena_size]
308 PUSH CX
309 CMP BX,CX
310 JBE alloc_get_size
311 JMP alloc_fail
312$setblock ENDP
313
314SUBTTL $DEALLOC - free previously allocated piece of memory
315PAGE
316;
317; Assembler usage:
318; MOV ES,block
319; MOV AH,dealloc
320; INT 21h
321;
322; Error return:
323; AX = error_invalid_block
324; = error_arena_trashed
325;
326 procedure $DEALLOC,NEAR
327 ASSUME DS:NOTHING,ES:NOTHING
328 MOV DI,arena_signature
329 MOV AX,ES
330 DEC AX
331 CALL check_signature
332 JC dealloc_err
333 MOV ES:[arena_owner],DI
334 transfer SYS_RET_OK
335
336dealloc_err:
337 error error_invalid_block
338$DEALLOC ENDP
339
340SUBTTL $AllocOper - get/set allocation mechanism
341PAGE
342;
343; Assembler usage:
344; MOV AH,AllocOper
345; MOV BX,method
346; MOV AL,func
347; INT 21h
348;
349; Error return:
350; AX = error_invalid_function
351;
352 procedure $AllocOper,NEAR
353 ASSUME DS:NOTHING,ES:NOTHING
354 CMP AL,1
355 JB AllocOperGet
356 JZ AllocOperSet
357 error error_invalid_function
358AllocOperGet:
359 MOV AL,BYTE PTR [AllocMethod]
360 XOR AH,AH
361 transfer SYS_RET_OK
362AllocOperSet:
363 MOV [AllocMethod],BL
364 transfer SYS_RET_OK
365$AllocOper ENDP
366
367do_ext
368
369CODE ENDS
370 END
371