Headers and library sources from all versions of Lightspeed C and THINK C
at main 308 lines 4.9 kB view raw
1 2/* 3 * alloc.c 4 * 5 * Copyright (c) 1991 Symantec Corporation. All rights reserved. 6 * 7 */ 8 9#include <MacHeaders> 10 11#include "stdlib.h" 12#include "string.h" 13 14static void *alloc(short); 15static void *zoneList, *lastZone, *curZone, *startPtr; 16 17/* requests above this size just use _NewPtr */ 18#define CROSSOVER 15000 19 20 21/* ---------- ANSI routines ---------- */ 22 23 24void * 25malloc(size_t size) 26{ 27 if (size < CROSSOVER) 28 return(alloc(size)); 29 if (size > maxSize) 30 return(NULL); 31 asm { 32 move.l size,d0 33 addq.l #2,d0 34 _NewPtr 35 bmi.s @1 36 move.w #-1,(a0)+ 37@1 move.l a0,d0 38 } 39} 40 41 42void * 43calloc(size_t count, size_t size) 44{ 45 void *p; 46 47 if (size > maxSize) 48 return(NULL); 49 if (size & 1) 50 ++size; 51 size *= count; 52 if (size > maxSize) 53 return(NULL); 54 if (size < CROSSOVER) { 55 if (p = alloc(size)) 56 memset(p, 0, size); 57 return(p); 58 } 59 asm { 60 move.l size,d0 61 addq.l #2,d0 62 _NewPtr CLEAR 63 bmi.s @1 64 move.w #-1,(a0)+ 65@1 move.l a0,d0 66 } 67} 68 69 70void * 71realloc(register void *oldptr, register size_t newsize) 72{ 73 register size_t oldsize, min; 74 register void *newptr; 75 76 /* handle special cases */ 77 78 if (newsize > maxSize) 79 return(NULL); 80 if (oldptr == NULL) 81 return(malloc(newsize)); 82 if (newsize == 0) { 83 free(oldptr); 84 return(NULL); 85 } 86 87 /* compute sizes */ 88 89 if (newsize & 1) 90 ++newsize; 91 asm { 92 movea.l oldptr,a0 93 moveq #0,d0 94 move.w -(a0),d0 95 not.w d0 96 bne.s @1 97 _GetPtrSize 98@1 subq.l #2,d0 99 move.l d0,oldsize 100 } 101 102 /* decide how to resize block */ 103 104 if (newsize < oldsize) { 105 min = newsize; 106 if (oldsize < CROSSOVER) 107 goto shrink; 108 if (newsize < CROSSOVER) 109 goto reallocate; 110 goto resize; 111 } 112 else if (newsize > oldsize) { 113 min = oldsize; 114 if (oldsize >= CROSSOVER) 115 goto resize; 116 if (newsize >= CROSSOVER) 117 goto reallocate; 118 goto grow; 119 } 120resized: 121 return(oldptr); 122 123 /* "shrink" - make a block (in a zone) smaller */ 124 125shrink: 126 asm { 127 movea.l oldptr,a0 128 move.w -(a0),d1 ; A0 ==> this block 129 move.l oldsize,d0 130 sub.l newsize,d0 ; D0.W = # bytes to free 131 add.w d0,d1 132 move.w d1,(a0) 133 not.w d1 ; D1.W = newsize+2 134 adda.w d1,a0 ; A0 ==> new next block 135 move.w d0,(a0) 136 } 137 goto resized; 138 139 /* "grow" - make a block (in a zone) larger */ 140 141grow: 142 asm { 143 movea.l oldptr,a1 144 move.w -(a1),d0 ; A1 ==> this block 145 not.w d0 146 lea 0(a1,d0.w),a0 ; A0 ==> next block 147 move.w (a0),d0 148 bmi.s @reallocate 149 move.l curZone,startPtr 150 moveq #0,d1 151@2 add.w d1,d0 ; coalesce following free blocks 152 move.w 0(a0,d0.w),d1 153 bpl.s @2 154 move.w d0,(a0) ; D0.W = # bytes available 155 move.l newsize,d1 156 sub.l oldsize,d1 ; D1.W = # bytes needed 157 adda.w d1,a0 ; A0 ==> new next block 158 sub.w d1,d0 159 blo.s @reallocate 160 beq.s @3 161 move.w d0,(a0) 162@3 sub.w d1,(a1) 163 } 164 goto resized; 165 166 /* "resize" - make a block (not in a zone) larger or smaller */ 167 168resize: 169 asm { 170 movea.l oldptr,a0 171 subq.l #2,a0 172 move.l newsize,d0 173 addq.l #2,d0 174 _SetPtrSize 175 bpl.s @resized 176 } 177 goto reallocate; 178 179 /* "reallocate" - allocate new block, copy and free old block */ 180 181reallocate: 182 if (newptr = malloc(newsize)) { 183 BlockMove(oldptr, newptr, min); 184 free(oldptr); 185 } 186 return(newptr); 187} 188 189 190void 191free(p) 192void *p; 193{ 194 asm { 195 move.l p,d0 196 beq.s @1 197 movea.l d0,a0 198 not.w -(a0) 199 bne.s @1 200 _DisposPtr 201@1 } 202} 203 204 205/* ---------- storage allocator ---------- */ 206 207 208static void * 209alloc(register short size) 210{ 211 void *startZone, *nextZone; 212 213 asm { 214 addq.w #3,size 215 bclr #0,size 216 move.l curZone,startZone 217 move.l startPtr,d0 218 bne.s @try_alloc 219 } 220 221 /* add a new zone to the list */ 222 223add_zone: 224 asm { 225 move.l #CROSSOVER+8,d0 226 _NewPtr 227 bmi @99 ; allocation failed 228 move.w #-1,CROSSOVER+2(a0) 229 move.l zoneList,CROSSOVER+4(a0) 230 move.l a0,zoneList 231 move.l a0,curZone 232 } 233 234 /* link last zone back to new first zone */ 235 236 asm { 237 move.l lastZone,d0 238 bne.s @11 239 move.l a0,d0 240 move.l d0,lastZone 241@11 movea.l d0,a1 242 move.l a0,CROSSOVER+4(a1) 243 move.w #CROSSOVER+2,d0 244 move.w d0,(a0) 245 bra.s @90 246 } 247 248 /* advance to next zone */ 249 250next_zone: 251 asm { 252 move.l nextZone,d0 253 cmp.l startZone,d0 254 beq.s @add_zone 255 move.l d0,curZone 256 move.l d0,startPtr 257 } 258 259 /* attempt allocation in current zone */ 260 261try_alloc: 262 asm { 263 movea.l d0,a0 264 moveq #-1,d2 ; a very large address 265 bra.s @32 266 } 267 268 /* find next free block */ 269 270 asm { 271@30 not.w d0 272 bne.s @31 273 move.l 2(a0),nextZone 274 movea.l curZone,a0 ; wrap to start of zone 275 move.l startPtr,d2 276@31 adda.w d0,a0 277 cmpa.l d2,a0 278 bhs.s @next_zone ; searched entire zone 279@32 move.w (a0),d0 280 bmi.s @30 281 } 282 283 /* coalesce free blocks */ 284 285 asm { 286 moveq #0,d1 287@41 add.w d1,d0 288 move.w 0(a0,d0.w),d1 289 bpl.s @41 290 move.w d0,(a0) 291 cmp.w size,d0 292 blo.s @31 ; block too small 293 } 294 295 /* success - carve out block */ 296 297 asm { 298@90 movea.l a0,a1 299 adda.w size,a1 300 move.l a1,startPtr 301 sub.w size,d0 302 beq.s @91 303 move.w d0,(a1) 304@91 not.w size 305 move.w size,(a0)+ 306@99 move.l a0,d0 307 } 308}