ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/malloc.c
Revision: 1.6
Committed: Wed Sep 26 19:35:46 1990 UTC (33 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.5: +16 -8 lines
Log Message:
fixed pointer alignment in bfree() and added new checks

File Contents

# Content
1 /* Copyright (c) 1990 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * Fast malloc for memory hogs and VM environments.
9 * Performs a minimum of searching through free lists.
10 * malloc(), realloc() and free() use buckets
11 * containing blocks in powers of two, similar to CIT routines.
12 * bfree() puts memory from any source into malloc free lists.
13 * bmalloc() doesn't keep track of free lists -- it's usually
14 * just a buffered call to sbrk(2). However, bmalloc will
15 * call mscrounge() if sbrk fails.
16 * mscrounge() returns whatever memory it can find to satisfy the
17 * request along with the number of bytes (modified).
18 *
19 * Greg Ward Lawrence Berkeley Laboratory
20 */
21
22 #include <errno.h>
23
24 #define NULL 0
25
26 #ifndef ALIGN
27 #define ALIGN int /* align type */
28 #endif
29 #define BYTES_WORD sizeof(ALIGN)
30
31 #define MAXINCR (1<<18) /* largest sbrk(2) increment */
32
33 #ifdef NOVMEM
34 #define getpagesize() BYTES_WORD
35 #endif
36 /* malloc free lists */
37 typedef union m_head {
38 union m_head *next;
39 int bucket;
40 ALIGN dummy;
41 } M_HEAD;
42
43 #define FIRSTBUCKET 3
44 #define NBUCKETS 30
45
46 static M_HEAD *free_list[NBUCKETS];
47
48
49 char *
50 mscrounge(np) /* search free lists to satisfy request */
51 register unsigned *np;
52 {
53 char *p;
54 register int bucket;
55 register unsigned bsiz;
56
57 for (bucket = FIRSTBUCKET, bsiz = 1<<FIRSTBUCKET;
58 bucket < NBUCKETS; bucket++, bsiz <<= 1)
59 if (free_list[bucket] != NULL && bsiz+sizeof(M_HEAD) >= *np) {
60 *np = bsiz+sizeof(M_HEAD);
61 p = (char *)free_list[bucket];
62 free_list[bucket] = free_list[bucket]->next;
63 return(p);
64 }
65 *np = 0;
66 return(NULL);
67 }
68
69
70 char *
71 bmalloc(n) /* allocate a block of n bytes, sans header */
72 register unsigned n;
73 {
74 extern char *sbrk();
75 static unsigned pagesz = 0;
76 static unsigned amnt;
77 static char *bpos;
78 static unsigned nrem;
79 unsigned thisamnt;
80 register char *p;
81
82 if (pagesz == 0) { /* initialize */
83 pagesz = amnt = getpagesize();
84 nrem = (int)sbrk(0); /* page align break */
85 nrem = pagesz - (nrem&(pagesz-1));
86 bpos = sbrk(nrem); /* word aligned! */
87 if ((int)bpos == -1)
88 return(NULL);
89 }
90
91 n = (n+(BYTES_WORD-1))&~(BYTES_WORD-1); /* word align rqst. */
92
93 if (n > nrem) { /* need more core */
94 if (n > amnt) { /* big chunk */
95 thisamnt = (n+(pagesz-1))&~(pagesz-1);
96 if (thisamnt <= MAXINCR) /* increase amnt */
97 amnt = thisamnt;
98 } else
99 thisamnt = amnt;
100 p = sbrk(thisamnt);
101 if ((int)p == -1) { /* uh-oh, ENOMEM */
102 thisamnt = n; /* search free lists */
103 p = mscrounge(&thisamnt);
104 if (p == NULL) /* we're really out */
105 return(NULL);
106 }
107 if (p != bpos+nrem) { /* not an increment */
108 bfree(bpos, nrem); /* free what we have */
109 bpos = p;
110 nrem = thisamnt;
111 } else /* otherwise tack on */
112 nrem += thisamnt;
113 }
114 p = bpos;
115 bpos += n; /* advance */
116 nrem -= n;
117 return(p);
118 }
119
120
121 bfree(p, n) /* free n bytes of random memory */
122 register char *p;
123 register unsigned n;
124 {
125 register int bucket;
126 register unsigned bsiz;
127 /* align pointer */
128 bsiz = BYTES_WORD - ((unsigned)p&(BYTES_WORD-1));
129 if (bsiz < BYTES_WORD) {
130 p += bsiz;
131 n -= bsiz;
132 }
133 /* fill big buckets first */
134 for (bucket = NBUCKETS-1, bsiz = 1<<(NBUCKETS-1);
135 bucket >= FIRSTBUCKET; bucket--, bsiz >>= 1)
136 if (n >= bsiz+sizeof(M_HEAD)) {
137 ((M_HEAD *)p)->next = free_list[bucket];
138 free_list[bucket] = (M_HEAD *)p;
139 p += bsiz+sizeof(M_HEAD);
140 n -= bsiz+sizeof(M_HEAD);
141 }
142 }
143
144
145 char *
146 malloc(n) /* allocate n bytes of memory */
147 unsigned n;
148 {
149 extern int errno;
150 register M_HEAD *mp;
151 register int bucket;
152 register unsigned bsiz;
153
154 if (n == 0)
155 return(NULL);
156 /* find first bucket that fits */
157 for (bucket = FIRSTBUCKET, bsiz = 1<<FIRSTBUCKET;
158 bucket < NBUCKETS; bucket++, bsiz <<= 1)
159 if (bsiz >= n)
160 break;
161 if (bucket >= NBUCKETS) {
162 errno = EINVAL;
163 return(NULL);
164 }
165 if (free_list[bucket] == NULL) { /* need more core */
166 mp = (M_HEAD *)bmalloc(bsiz+sizeof(M_HEAD));
167 if (mp == NULL)
168 return(NULL);
169 } else { /* got it */
170 mp = free_list[bucket];
171 free_list[bucket] = mp->next;
172 }
173 mp->bucket = bucket; /* tag block */
174 return((char *)(mp+1));
175 }
176
177
178 char *
179 realloc(op, n) /* reallocate memory using malloc() */
180 register char *op;
181 unsigned n;
182 {
183 char *p;
184 register unsigned on;
185 /* get old size */
186 if (op != NULL)
187 on = 1 << ((M_HEAD *)op-1)->bucket;
188 else
189 on = 0;
190 if (n <= on && (n > on>>1 || on == 1<<FIRSTBUCKET))
191 return(op); /* same bucket */
192 p = malloc(n);
193 if (p != NULL)
194 #ifdef BSD
195 bcopy(op, p, n>on ? on : n);
196 #else
197 (void)memcpy(p, op, n>on ? on : n);
198 #endif
199 free(op);
200 return(p);
201 }
202
203
204 free(p) /* free memory allocated by malloc */
205 char *p;
206 {
207 register M_HEAD *mp;
208 register int bucket;
209
210 if (p == NULL)
211 return;
212 mp = (M_HEAD *)p - 1;
213 bucket = mp->bucket;
214 mp->next = free_list[bucket];
215 free_list[bucket] = mp;
216 }
217
218
219 #ifndef NOVMEM
220 #ifndef BSD
221 #include <sys/var.h>
222 int
223 getpagesize() /* use SYSV var structure to get page size */
224 {
225 static int pagesz = 0;
226 struct var v;
227
228 if (pagesz == 0) {
229 uvar(&v);
230 pagesz = 1 << v.v_pageshift;
231 }
232 return(pagesz);
233 }
234 #endif
235 #endif