1*35127Smarc /*
2*35127Smarc
3*35127Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*35127Smarc * All Rights Reserved
5*35127Smarc
6*35127Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35127Smarc * CODE OF AT&T.
8*35127Smarc * The copyright notice above does not
9*35127Smarc * evidence any actual or intended
10*35127Smarc * publication of such source code.
11*35127Smarc
12*35127Smarc */
13*35127Smarc /* @(#)blok.c 1.1 */
14*35127Smarc /*
15*35127Smarc * UNIX shell
16*35127Smarc *
17*35127Smarc * S. R. Bourne
18*35127Smarc * Rewritten by David Korn
19*35127Smarc * AT&T Bell Laboratories
20*35127Smarc *
21*35127Smarc */
22*35127Smarc
23*35127Smarc #include "defs.h"
24*35127Smarc #include "stak.h"
25*35127Smarc #include "brkincr.h"
26*35127Smarc
27*35127Smarc
28*35127Smarc /*
29*35127Smarc * storage allocator
30*35127Smarc * (circular first fit strategy)
31*35127Smarc */
32*35127Smarc
33*35127Smarc #define BUSY 01
34*35127Smarc #define busy(x) (Rcheat((x)->word)&BUSY)
35*35127Smarc
36*35127Smarc void addblok();
37*35127Smarc void free();
38*35127Smarc char *malloc();
39*35127Smarc void setbrk();
40*35127Smarc #ifdef DBUG
41*35127Smarc void chkmem();
42*35127Smarc extern void p_str();
43*35127Smarc extern void p_num();
44*35127Smarc extern void p_flush();
45*35127Smarc #endif /* DBUG */
46*35127Smarc
47*35127Smarc
48*35127Smarc /*
49*35127Smarc * equivalent to malloc(3) except that a data area stack is
50*35127Smarc * maintained on top of the heap
51*35127Smarc */
52*35127Smarc
malloc(nbytes)53*35127Smarc char *malloc(nbytes)
54*35127Smarc unsigned nbytes;
55*35127Smarc {
56*35127Smarc register unsigned rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);
57*35127Smarc while(1)
58*35127Smarc {
59*35127Smarc register BLKPTR p = blokp;
60*35127Smarc register BLKPTR q;
61*35127Smarc register int c=0;
62*35127Smarc do
63*35127Smarc {
64*35127Smarc if(!busy(p))
65*35127Smarc {
66*35127Smarc while(!busy(q = p->word))
67*35127Smarc p->word = q->word;
68*35127Smarc if(ADR(q)-ADR(p) >= rbytes)
69*35127Smarc {
70*35127Smarc blokp = BLK(ADR(p)+rbytes);
71*35127Smarc if(q > blokp)
72*35127Smarc blokp->word = p->word;
73*35127Smarc p->word=BLK(Rcheat(blokp)|BUSY);
74*35127Smarc return(ADR(p+1));
75*35127Smarc }
76*35127Smarc }
77*35127Smarc q = p; p = BLK(Rcheat(p->word)&~BUSY);
78*35127Smarc }
79*35127Smarc while(p>q || (c++)==0);
80*35127Smarc addblok(rbytes);
81*35127Smarc }
82*35127Smarc }
83*35127Smarc
84*35127Smarc /*
85*35127Smarc * add more space to the heap and move the stack to the top of the heap
86*35127Smarc */
87*35127Smarc
addblok(reqd)88*35127Smarc void addblok(reqd)
89*35127Smarc register unsigned int reqd;
90*35127Smarc {
91*35127Smarc if(stakbot == 0)
92*35127Smarc {
93*35127Smarc setbrk(3*BRKINCR);
94*35127Smarc bloktop = BLK(brkbegin);
95*35127Smarc }
96*35127Smarc if(stakbas!=staktop)
97*35127Smarc {
98*35127Smarc register STKPTR rndstak;
99*35127Smarc register BLKPTR blokstak;
100*35127Smarc pushstak(0);
101*35127Smarc rndstak=(STKPTR) round(staktop,BYTESPERWORD);
102*35127Smarc blokstak=BLK(stakbas)-1;
103*35127Smarc blokstak->word=stakbsy; stakbsy=blokstak;
104*35127Smarc bloktop->word=BLK(Rcheat(rndstak)|BUSY);
105*35127Smarc bloktop=BLK(rndstak);
106*35127Smarc }
107*35127Smarc reqd += BRKINCR;
108*35127Smarc reqd &= ~(BRKINCR-1);
109*35127Smarc blokp=bloktop;
110*35127Smarc bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd);
111*35127Smarc reqd = 0;
112*35127Smarc while((char*)bloktop+BRKINCR > brkend+reqd)
113*35127Smarc reqd += BRKINCR;
114*35127Smarc if(reqd)
115*35127Smarc setbrk((int)reqd);
116*35127Smarc bloktop->word=BLK(Rcheat(brkbegin)|BUSY);
117*35127Smarc {
118*35127Smarc register STKPTR stakadr=STK(bloktop+2);
119*35127Smarc register STKPTR sp = stakadr;
120*35127Smarc if(reqd = (staktop-stakbot))
121*35127Smarc {
122*35127Smarc while(reqd-- > 0)
123*35127Smarc *sp++ = *stakbot++;
124*35127Smarc sp--;
125*35127Smarc }
126*35127Smarc staktop = sp;
127*35127Smarc stakbas=stakbot=stakadr;
128*35127Smarc }
129*35127Smarc }
130*35127Smarc
131*35127Smarc /*
132*35127Smarc * mark the block free if address is in the heap
133*35127Smarc */
134*35127Smarc
free(ap)135*35127Smarc void free(ap)
136*35127Smarc register char *ap;
137*35127Smarc {
138*35127Smarc register BLKPTR p;
139*35127Smarc if(ap>brkbegin && ap<(char*)bloktop)
140*35127Smarc {
141*35127Smarc p = (BLKPTR)(ap-sizeof(p->word));
142*35127Smarc p->word = (BLKPTR)(Rcheat(p->word)&~BUSY);
143*35127Smarc }
144*35127Smarc }
145*35127Smarc
146*35127Smarc
setbrk(incr)147*35127Smarc void setbrk(incr)
148*35127Smarc {
149*35127Smarc register char *a=(char *)(sbrk(incr));
150*35127Smarc if((int)a == -1)
151*35127Smarc error(nospace);
152*35127Smarc a = (char*)round(a,BYTESPERWORD);
153*35127Smarc if(brkbegin==0)
154*35127Smarc brkbegin = a;
155*35127Smarc brkend=a+incr-8;
156*35127Smarc #ifndef INT16
157*35127Smarc if(brkend > brkbegin + BRKMAX)
158*35127Smarc {
159*35127Smarc error(nospace);
160*35127Smarc }
161*35127Smarc #endif /* INT16 */
162*35127Smarc }
163*35127Smarc
164*35127Smarc #ifdef DBUG
chkmem()165*35127Smarc void chkmem()
166*35127Smarc {
167*35127Smarc register BLKPTR p = (BLKPTR)brkbegin;
168*35127Smarc register BLKPTR q;
169*35127Smarc register int us=0, un=0;
170*35127Smarc
171*35127Smarc while(1)
172*35127Smarc {
173*35127Smarc q = (BLKPTR) (Rcheat(p->word)&~BUSY);
174*35127Smarc
175*35127Smarc if(q<BLK(brkbegin) || q>bloktop)
176*35127Smarc abort(3);
177*35127Smarc if(p==bloktop)
178*35127Smarc break;
179*35127Smarc if(busy(p))
180*35127Smarc us += q-p;
181*35127Smarc else
182*35127Smarc un += q-p;
183*35127Smarc if(p>=q)
184*35127Smarc {
185*35127Smarc p_flush();
186*35127Smarc abort(4);
187*35127Smarc }
188*35127Smarc p=q;
189*35127Smarc }
190*35127Smarc un *= sizeof(*q);
191*35127Smarc us *= sizeof(*q);
192*35127Smarc p_str("free/used/missing",':');
193*35127Smarc p_num(un,' ');
194*35127Smarc p_num(us,' ');
195*35127Smarc p_num((char*)bloktop - (char*)brkbegin - (un+us),NL);
196*35127Smarc }
197*35127Smarc
198*35127Smarc /*
199*35127Smarc * returns 1 if <ap> is on heap and is free
200*35127Smarc * returns 2 if <ap> is on heap and not beginning of a block
201*35127Smarc * otherwise returns 0
202*35127Smarc */
203*35127Smarc
chkfree(ap)204*35127Smarc int chkfree(ap)
205*35127Smarc register char *ap;
206*35127Smarc {
207*35127Smarc register BLKPTR p;
208*35127Smarc if(ap>brkbegin && ap<(char*)bloktop)
209*35127Smarc {
210*35127Smarc p = (BLKPTR)(ap-sizeof(p->word));
211*35127Smarc if(p->word<BLK(brkbegin) || p->word>bloktop)
212*35127Smarc return(2);
213*35127Smarc return(!busy(p));
214*35127Smarc }
215*35127Smarc return(0);
216*35127Smarc }
217*35127Smarc #endif /* DBUG */
218