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