diff options
Diffstat (limited to 'v4.0/src/DOS/ALLOC.ASM')
| -rw-r--r-- | v4.0/src/DOS/ALLOC.ASM | 392 |
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 | ||
| 2 | TITLE ALLOC.ASM - memory arena manager | ||
| 3 | NAME 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 | ; | ||
| 26 | include dosseg.asm | ||
| 27 | |||
| 28 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 29 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 30 | |||
| 31 | .xcref | ||
| 32 | INCLUDE DOSSYM.INC | ||
| 33 | INCLUDE DEVSYM.INC | ||
| 34 | .cref | ||
| 35 | .list | ||
| 36 | |||
| 37 | .lall | ||
| 38 | |||
| 39 | SUBTTL memory allocation utility routines | ||
| 40 | PAGE | ||
| 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 | |||
| 63 | arena_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 | |||
| 71 | arena_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 | |||
| 78 | EndProc 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 | ||
| 96 | EndProc 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 | |||
| 115 | EndProc 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 | |||
| 131 | coalesce_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 | ||
| 140 | EndProc Coalesce | ||
| 141 | |||
| 142 | SUBTTL $Alloc - allocate space in memory | ||
| 143 | PAGE | ||
| 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 | |||
| 176 | alloc_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 | |||
| 182 | alloc_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 | |||
| 189 | alloc_err: | ||
| 190 | POP AX | ||
| 191 | |||
| 192 | alloc_trashed: | ||
| 193 | LeaveCrit critMem | ||
| 194 | error error_arena_trashed | ||
| 195 | |||
| 196 | alloc_end: | ||
| 197 | CMP [FirstArena],0 | ||
| 198 | JNZ alloc_do_split | ||
| 199 | |||
| 200 | alloc_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 | |||
| 207 | alloc_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 | |||
| 217 | alloc_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 | ||
| 225 | alloc_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 | ||
| 233 | alloc_make_best: | ||
| 234 | MOV [BestArena],DS ; assign best | ||
| 235 | alloc_last: | ||
| 236 | MOV [LastArena],DS ; assign last | ||
| 237 | JMP alloc_next | ||
| 238 | |||
| 239 | ; | ||
| 240 | ; split the block high | ||
| 241 | ; | ||
| 242 | alloc_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 | ; | ||
| 259 | alloc_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] | ||
| 265 | alloc_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 | ||
| 275 | alloc_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 | |||
| 283 | alloc_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 | |||
| 293 | EndProc $alloc | ||
| 294 | |||
| 295 | SUBTTL $SETBLOCK - change size of an allocated block (if possible) | ||
| 296 | PAGE | ||
| 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 | |||
| 320 | setblock_bad: | ||
| 321 | JMP alloc_trashed | ||
| 322 | |||
| 323 | setblock_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 | ||
| 332 | EndProc $setblock | ||
| 333 | |||
| 334 | SUBTTL $DEALLOC - free previously allocated piece of memory | ||
| 335 | PAGE | ||
| 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 | |||
| 358 | dealloc_err: | ||
| 359 | LeaveCrit critMem | ||
| 360 | error error_invalid_block | ||
| 361 | EndProc $DEALLOC | ||
| 362 | |||
| 363 | SUBTTL $AllocOper - get/set allocation mechanism | ||
| 364 | PAGE | ||
| 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 | ||
| 382 | AllocOperGet: | ||
| 383 | MOV AL,BYTE PTR [AllocMethod] | ||
| 384 | XOR AH,AH | ||
| 385 | transfer SYS_RET_OK | ||
| 386 | AllocOperSet: | ||
| 387 | MOV [AllocMethod],BL | ||
| 388 | transfer SYS_RET_OK | ||
| 389 | EndProc $AllocOper | ||
| 390 | |||
| 391 | CODE ENDS | ||
| 392 | END | ||