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