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 * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
32 *
33 * Sccsid @(#)blok.c 1.7 (gritter) 6/16/05
34 */
35
36 /* from OpenSolaris "blok.c 1.19 05/06/08 SMI" */
37 /*
38 * UNIX shell
39 */
40
41 #include "defs.h"
42
43
44 /*
45 * storage allocator
46 * (circular first fit strategy)
47 */
48
49 #define BUSY 01
50 #define busy(x) (Rcheat((x)->word) & BUSY)
51
52 unsigned brkincr = BRKINCR;
53 struct blk *blokp; /* current search pointer */
54 struct blk *bloktop; /* top of arena (last blok) */
55
56 unsigned char *brkbegin;
57
58 void *
alloc(nbytes)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 void
addblok(unsigned reqd)99 addblok(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
free(ap)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 int
chkbptr(struct blk * ptr)186 chkbptr(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 int
chkmem(void)222 chkmem(void)
223 {
224 register struct blk *p = (struct blk *)brkbegin;
225 register 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
blklen(char * q)261 blklen(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