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