1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 /* 33 * UNIX shell 34 */ 35 36 #include "defs.h" 37 38 39 /* 40 * storage allocator 41 * (circular first fit strategy) 42 */ 43 44 #define BUSY 01 45 #define busy(x) (Rcheat((x)->word) & BUSY) 46 47 unsigned brkincr = BRKINCR; 48 struct blk *blokp; /* current search pointer */ 49 struct blk *bloktop; /* top of arena (last blok) */ 50 51 unsigned char *brkbegin; 52 unsigned char *setbrk(); 53 54 #ifdef __STDC__ 55 void * 56 #else 57 char * 58 #endif 59 alloc(nbytes) 60 size_t nbytes; 61 { 62 register unsigned rbytes = round(nbytes+BYTESPERWORD, BYTESPERWORD); 63 64 if (stakbot == 0) { 65 addblok((unsigned)0); 66 } 67 68 for (;;) 69 { 70 int c = 0; 71 register struct blk *p = blokp; 72 register struct blk *q; 73 74 do 75 { 76 if (!busy(p)) 77 { 78 while (!busy(q = p->word)) 79 p->word = q->word; 80 if ((char *)q - (char *)p >= rbytes) 81 { 82 blokp = (struct blk *) 83 ((char *)p + rbytes); 84 if (q > blokp) 85 blokp->word = p->word; 86 p->word = (struct blk *) 87 (Rcheat(blokp) | BUSY); 88 return ((char *)(p + 1)); 89 } 90 } 91 q = p; 92 p = (struct blk *)(Rcheat(p->word) & ~BUSY); 93 } while (p > q || (c++) == 0); 94 addblok(rbytes); 95 } 96 } 97 98 addblok(reqd) 99 unsigned reqd; 100 { 101 if (stakbot == 0) 102 { 103 brkbegin = setbrk(3 * BRKINCR); 104 bloktop = (struct blk *)brkbegin; 105 } 106 107 if (stakbas != staktop) 108 { 109 register unsigned char *rndstak; 110 register struct blk *blokstak; 111 112 if (staktop >= brkend) 113 growstak(staktop); 114 pushstak(0); 115 rndstak = (unsigned char *)round(staktop, BYTESPERWORD); 116 blokstak = (struct blk *)(stakbas) - 1; 117 blokstak->word = stakbsy; 118 stakbsy = blokstak; 119 bloktop->word = (struct blk *)(Rcheat(rndstak) | BUSY); 120 bloktop = (struct blk *)(rndstak); 121 } 122 reqd += brkincr; 123 reqd &= ~(brkincr - 1); 124 blokp = bloktop; 125 /* 126 * brkend points to the first invalid address. 127 * make sure bloktop is valid. 128 */ 129 if ((unsigned char *)&bloktop->word >= brkend) 130 { 131 if (setbrk((unsigned)((unsigned char *) 132 (&bloktop->word) - brkend + sizeof (struct blk))) == 133 (unsigned char *)-1) 134 error(nospace); 135 } 136 bloktop = bloktop->word = (struct blk *)(Rcheat(bloktop) + reqd); 137 if ((unsigned char *)&bloktop->word >= brkend) 138 { 139 if (setbrk((unsigned)((unsigned char *) 140 (&bloktop->word) - brkend + sizeof (struct blk))) == 141 (unsigned char *)-1) 142 error(nospace); 143 } 144 bloktop->word = (struct blk *)(brkbegin + 1); 145 { 146 register unsigned char *stakadr = (unsigned char *) 147 (bloktop + 2); 148 register unsigned char *sp = stakadr; 149 if (reqd = (staktop-stakbot)) 150 { 151 if (stakadr + reqd >= brkend) 152 growstak(stakadr + reqd); 153 while (reqd-- > 0) 154 *sp++ = *stakbot++; 155 sp--; 156 } 157 staktop = sp; 158 if (staktop >= brkend) 159 growstak(staktop); 160 stakbas = stakbot = stakadr; 161 } 162 } 163 164 void 165 free(ap) 166 void *ap; 167 { 168 register struct blk *p; 169 170 if ((p = (struct blk *)ap) && p < bloktop && p > (struct blk *)brkbegin) 171 { 172 #ifdef DEBUG 173 chkbptr(p); 174 #endif 175 --p; 176 p->word = (struct blk *)(Rcheat(p->word) & ~BUSY); 177 } 178 179 180 } 181 182 183 #ifdef DEBUG 184 185 chkbptr(ptr) 186 struct blk *ptr; 187 { 188 int exf = 0; 189 register struct blk *p = (struct blk *)brkbegin; 190 register struct blk *q; 191 int us = 0, un = 0; 192 193 for (;;) 194 { 195 q = (struct blk *)(Rcheat(p->word) & ~BUSY); 196 197 if (p+1 == ptr) 198 exf++; 199 200 if (q < (struct blk *)brkbegin || q > bloktop) 201 abort(3); 202 203 if (p == bloktop) 204 break; 205 206 if (busy(p)) 207 us += q - p; 208 else 209 un += q - p; 210 211 if (p >= q) 212 abort(4); 213 214 p = q; 215 } 216 if (exf == 0) 217 abort(1); 218 } 219 220 221 chkmem() 222 { 223 register struct blk *p = (struct blk *)brkbegin; 224 register struct blk *q; 225 int us = 0, un = 0; 226 227 for (;;) { 228 q = (struct blk *)(Rcheat(p->word) & ~BUSY); 229 230 if (q < (struct blk *)brkbegin || q > bloktop) 231 abort(3); 232 233 if (p == bloktop) 234 break; 235 236 if (busy(p)) 237 us += q - p; 238 else 239 un += q - p; 240 241 if (p >= q) 242 abort(4); 243 244 p = q; 245 } 246 247 prs("un/used/avail "); 248 prn(un); 249 blank(); 250 prn(us); 251 blank(); 252 prn((char *)bloktop - brkbegin - (un + us)); 253 newline(); 254 255 } 256 257 #endif 258 259 size_t 260 blklen(q) 261 char *q; 262 { 263 register struct blk *pp = (struct blk *)q; 264 register struct blk *p; 265 266 --pp; 267 p = (struct blk *)(Rcheat(pp->word) & ~BUSY); 268 269 return ((size_t)((long)p - (long)q)); 270 } 271 272 /* 273 * This is a really hasty hack at putting realloc() in the shell, along 274 * with alloc() and free(). I really hate having to do things like this, 275 * hacking in something before I understand _why_ libcollate does any 276 * memory (re)allocation, let alone feel comfortable with this particular 277 * implementation of realloc, assuming it actually gets used by anything. 278 * 279 * I plan to revist this, for now this is just to get sh to compile so 280 * that xcu4 builds may be done and we get xcu4 on our desktops. 281 * 282 * Eric Brunner, 10/21/94 283 * 284 * Implemented a variation on the suggested fix in Trusted Solaris 2.5, 285 * then forward ported the fix into the mainline shell. 286 * 287 * 3/3/99 288 */ 289 #ifdef __STDC__ 290 void * 291 realloc(pp, nbytes) 292 void *pp; 293 size_t nbytes; 294 #else 295 char * 296 realloc(pp, nbytes) 297 char *pp; 298 size_t nbytes; 299 #endif 300 { 301 char *q; 302 size_t blen; 303 304 if (pp == NULL) 305 return (alloc(nbytes)); 306 if ((nbytes == 0) && (pp != NULL)) 307 free(pp); 308 309 blen = blklen(pp); 310 311 if (blen < nbytes) { /* need to grow */ 312 q = alloc(nbytes); 313 memcpy(q, pp, blen); 314 free(pp); 315 return ((char *)q); 316 } else if (blen == nbytes) { /* do nothing */ 317 return (pp); 318 } else { /* free excess */ 319 q = alloc(nbytes); 320 memcpy(q, pp, nbytes); 321 free(pp); 322 return ((char *)q); 323 } 324 325 #ifdef undef 326 /* 327 * all of what follows is the _idea_ of what is going to be done 328 * getting the size of the block is a problem -- what follows 329 * is _not_ "real", since "sizeof" isn't going to tell me any 330 * thing usefull, probably have to travers the list to the next 331 * blk, then subtract ptr addrs ... and be careful not to leave 332 * holes. 333 */ 334 p = (struct blk *)pp; 335 if (sizeof (p) < nbytes) { /* need to grow */ 336 q = alloc(nbytes); 337 memcpy(q, pp, sizeof (p)); 338 free(pp); 339 return ((char *)q); 340 } else if (sizeof (p) == nbytes) { /* do nothing */ 341 return (pp); 342 } else { /* free excess */ 343 q = alloc(nbytes); 344 memcpy(q, pp, nbytes); 345 free(pp); 346 return ((char *)q); 347 } 348 #endif 349 } 350