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.
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.
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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
39 * (circular first fit strategy)
43 #define busy(x) (Rcheat((x)->word) & BUSY)
45 unsigned brkincr
= BRKINCR
;
46 struct blk
*blokp
; /* current search pointer */
47 struct blk
*bloktop
; /* top of arena (last blok) */
49 unsigned char *brkbegin
;
50 extern unsigned char *setbrk();
54 * If DEBUG is defined, the following testing will be performed:
55 * - chkbptr() checks the linkage of blocks by following links.
56 * Note that this makes shell really slow.
57 * - fill_pat() fills the memory block with pattern like umem does.
58 * The pattern used to fill the memory area is defined below.
60 #define PAT_MAGIC 0xfeedface
61 #define PAT_INIT 0xbaddcafe
62 #define PAT_FREE 0xdeadbeef
64 static void fill_pat(struct blk
*, uint32_t);
65 static void chkbptr(struct blk
*);
71 size_t rbytes
= round(nbytes
+ ALIGNSIZ
, ALIGNSIZ
);
74 addblok((unsigned int)0);
79 struct blk
*p
= blokp
;
85 while (!busy(q
= p
->word
))
87 if ((char *)q
- (char *)p
>= rbytes
) {
88 blokp
= (struct blk
*)
91 blokp
->word
= p
->word
;
92 p
->word
= (struct blk
*)
93 (Rcheat(blokp
) | BUSY
);
95 fill_pat(p
, PAT_INIT
);
97 return ((char *)(p
+ 1));
101 p
= (struct blk
*)(Rcheat(p
->word
) & ~BUSY
);
102 } while (p
> q
|| (c
++) == 0);
108 addblok(unsigned int reqd
)
111 brkbegin
= setbrk(3 * BRKINCR
);
113 * setbrk() returns 8 byte aligned address
114 * but we could need larger align in future
116 brkbegin
= (unsigned char *)round(brkbegin
, ALIGNSIZ
);
117 bloktop
= (struct blk
*)brkbegin
;
120 if (stakbas
!= staktop
) {
121 unsigned char *rndstak
;
122 struct blk
*blokstak
;
124 if (staktop
>= brkend
)
127 rndstak
= (unsigned char *)round(staktop
, ALIGNSIZ
);
128 blokstak
= (struct blk
*)(stakbas
) - 1;
129 blokstak
->word
= stakbsy
;
131 bloktop
->word
= (struct blk
*)(Rcheat(rndstak
) | BUSY
);
132 bloktop
= (struct blk
*)(rndstak
);
135 reqd
&= ~(brkincr
- 1);
138 * brkend points to the first invalid address.
139 * make sure bloktop is valid.
141 if ((unsigned char *)&bloktop
->word
>= brkend
) {
142 if (setbrk((unsigned)((unsigned char *)
143 (&bloktop
->word
) - brkend
+ sizeof (struct blk
))) ==
147 bloktop
= bloktop
->word
= (struct blk
*)(Rcheat(bloktop
) + reqd
);
148 if ((unsigned char *)&bloktop
->word
>= brkend
) {
149 if (setbrk((unsigned)((unsigned char *)
150 (&bloktop
->word
) - brkend
+ sizeof (struct blk
))) ==
154 bloktop
->word
= (struct blk
*)(brkbegin
+ 1);
156 unsigned char *stakadr
= (unsigned char *)
158 unsigned char *sp
= stakadr
;
159 if (reqd
= (staktop
-stakbot
)) {
160 if (stakadr
+ reqd
>= brkend
)
161 growstak(stakadr
+ reqd
);
167 if (staktop
>= brkend
)
169 stakbas
= stakbot
= stakadr
;
179 if ((p
= (struct blk
*)ap
) && p
< bloktop
&& p
> (struct blk
*)brkbegin
)
185 p
->word
= (struct blk
*)(Rcheat(p
->word
) & ~BUSY
);
187 fill_pat(p
, PAT_FREE
);
198 fill_pat(struct blk
*ptr
, uint32_t pat
)
202 *(uint32_t *)ptr
->pad
= PAT_MAGIC
;
203 eui
= (uint32_t *)(Rcheat(ptr
->word
) & ~BUSY
);
204 for (ui
= (uint32_t *)(ptr
+ 1); ui
< eui
; ui
++)
209 chkbptr(struct blk
*ptr
)
212 struct blk
*p
= (struct blk
*)brkbegin
;
217 q
= (struct blk
*)(Rcheat(p
->word
) & ~BUSY
);
222 if (q
< (struct blk
*)brkbegin
|| q
> bloktop
)
245 struct blk
*p
= (struct blk
*)brkbegin
;
250 q
= (struct blk
*)(Rcheat(p
->word
) & ~BUSY
);
252 if (q
< (struct blk
*)brkbegin
|| q
> bloktop
)
269 prs("un/used/avail ");
274 prn((uintptr_t)bloktop
- (uintptr_t)brkbegin
- (un
+ us
));
285 struct blk
*pp
= (struct blk
*)q
;
289 p
= (struct blk
*)(Rcheat(pp
->word
) & ~BUSY
);
291 return ((size_t)((long)p
- (long)q
));
295 * This is a really hasty hack at putting realloc() in the shell, along
296 * with alloc() and free(). I really hate having to do things like this,
297 * hacking in something before I understand _why_ libcollate does any
298 * memory (re)allocation, let alone feel comfortable with this particular
299 * implementation of realloc, assuming it actually gets used by anything.
301 * I plan to revist this, for now this is just to get sh to compile so
302 * that xcu4 builds may be done and we get xcu4 on our desktops.
304 * Eric Brunner, 10/21/94
306 * Implemented a variation on the suggested fix in Trusted Solaris 2.5,
307 * then forward ported the fix into the mainline shell.
327 return (alloc(nbytes
));
328 if ((nbytes
== 0) && (pp
!= NULL
))
333 if (blen
< nbytes
) { /* need to grow */
338 } else if (blen
== nbytes
) { /* do nothing */
340 } else { /* free excess */
342 memcpy(q
, pp
, nbytes
);
349 * all of what follows is the _idea_ of what is going to be done
350 * getting the size of the block is a problem -- what follows
351 * is _not_ "real", since "sizeof" isn't going to tell me any
352 * thing usefull, probably have to travers the list to the next
353 * blk, then subtract ptr addrs ... and be careful not to leave
356 p
= (struct blk
*)pp
;
357 if (sizeof (p
) < nbytes
) { /* need to grow */
359 memcpy(q
, pp
, sizeof (p
));
362 } else if (sizeof (p
) == nbytes
) { /* do nothing */
364 } else { /* free excess */
366 memcpy(q
, pp
, nbytes
);