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
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.
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]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
26 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.3 */
28 #define ASSERT(p) if(!(p))botch("p");else
32 printf("assertion botched: %s\n",s
);
39 /* C storage allocator
40 * circular first-fit strategy
41 * works with noncontiguous, but monotonically linked, arena
42 * each block is preceded by a ptr to the (pointer of)
43 * the next following block
44 * blocks are exact number of words long
45 * aligned to the data type requirements of ALIGN
46 * pointers to blocks must have BUSY bit 0
47 * bit in ptr is 1 for busy, 0 for idle
48 * gaps in arena are merely noted as busy blocks
49 * last block of arena is empty and
50 * has a pointer to first
51 * idle blocks are coalesced during space search
53 * a different implementation may need to redefine
54 * ALIGN, NALIGN, BLOCK, BUSY, INT
55 * where INT is integer type to which a pointer can be cast
60 #define WORD sizeof(union store)
64 #define testbusy(p) ((INT)(p)&BUSY)
65 #define setbusy(p) (union store *)((INT)(p)|BUSY)
66 #define clearbusy(p) (union store *)((INT)(p)&~BUSY)
71 int calloc
; /*calloc clears an array of integers*/
74 static union store alloca
; /* initial arena */
75 static union store
*allocb
= &alloca
; /*arena base*/
76 static union store
*allocp
= &alloca
; /*search ptr*/
77 static union store
*allocx
; /*for benefit of realloc*/
84 register union store
*p
, *q
;
87 register union store
*r
= 0;
89 nw
= (nbytes
+WORD
+WORD
-1)/WORD
+ 1; /*need one more than asked for*/
90 ASSERT(allock(allocp
));
91 for(; ; ) { /* done at most twice */
93 if(alloca
.ptr
!=0) /*C can't initialize union*/
95 if(!testbusy(p
->ptr
)) {
96 while(!testbusy((q
=p
->ptr
)->ptr
)) {
101 if(q
>=p
+nw
&& p
+nw
>=p
)
106 p
= clearbusy(p
->ptr
);
116 p
= (union store
*)sbrk(0);
117 if (r
&& !testbusy(r
->ptr
) && r
->ptr
+ 1 == p
)
119 temp
= ((temp
+BLOCK
/WORD
)/(BLOCK
/WORD
))*(BLOCK
/WORD
);
123 q
= (union store
*)sbrk(temp
*WORD
);
126 temp
-= (temp
-nw
+1)/2;
130 ialloc((char *)q
, (unsigned)temp
*WORD
);
135 allocx
= allocp
->ptr
;
136 allocp
->ptr
= p
->ptr
;
138 p
->ptr
= setbusy(allocp
);
139 return((char *)(p
+1));
142 /* freeing strategy tuned for LIFO allocation
147 register union store
*p
= (union store
*)ap
;
150 ASSERT(allock(allocp
));
151 ASSERT(testbusy(p
->ptr
));
152 p
->ptr
= clearbusy(p
->ptr
);
153 ASSERT(p
->ptr
> allocp
);
156 /* ialloc(q, nbytes) inserts a block that did not come
157 * from malloc into the arena
159 * q points to new block
160 * r points to last of new block
161 * p points to last cell of arena before new block
162 * s points to first cell of arena after new block
168 register union store
*p
, *q
, *s
;
171 q
= (union store
*)qq
;
172 r
= q
+ (nbytes
/WORD
) - 1;
174 if(alloca
.ptr
==0) /*C can't initialize union*/
175 alloca
.ptr
= &alloca
;
176 for(p
=allocb
; ; p
=s
) {
177 s
= clearbusy(p
->ptr
);
188 p
->ptr
= q
==p
+1? q
: setbusy(q
);
189 r
->ptr
= s
==r
+1? s
: setbusy(s
);
195 /* realloc(p, nbytes) reallocates a block obtained from malloc()
196 * and freed since last call of malloc()
197 * to have new size nbytes, and old content
198 * returns new location, or 0 on failure
206 register union store
*q
;
207 register union store
*p
= (union store
*)pp
;
209 register unsigned nw
;
213 if(testbusy(p
[-1].ptr
))
216 q
= (union store
*)malloc(nbytes
);
219 ASSERT(q
<p
||q
>p
[-1].ptr
);
222 nw
= (nbytes
+WORD
-1)/WORD
;
227 ASSERT(clearbusy(q
[-1].ptr
)-q
==nw
);
229 (q
+(q
+nw
-p
))->ptr
= allocx
;
239 register union store
*p
, *r
;
245 for( ; (r
=clearbusy(p
->ptr
)) > p
; p
=r
) {
249 return(r
==allocb
&(x
==1|p
==q
));