ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/malloc.c
Revision: 1.5
Committed: Wed Sep 26 13:46:52 1990 UTC (33 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +9 -6 lines
Log Message:
got back old version of realloc() from 1.3

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 #define NULL 0
23
24 #ifndef ALIGN
25 #define ALIGN int /* align type */
26 #endif
27 #define BYTES_WORD sizeof(ALIGN)
28
29 #define MAXINCR (1<<18) /* largest sbrk(2) increment */
30
31 #ifdef NOVMEM
32 #define getpagesize() BYTES_WORD
33 #endif
34 /* malloc free lists */
35 typedef union m_head {
36 union m_head *next;
37 int bucket;
38 ALIGN dummy;
39 } M_HEAD;
40
41 #define FIRSTBUCKET 3
42 #define NBUCKETS 30
43
44 static M_HEAD *free_list[NBUCKETS];
45
46
47 char *
48 mscrounge(np) /* search free lists to satisfy request */
49 register unsigned *np;
50 {
51 char *p;
52 register int bucket;
53 register unsigned bsiz;
54
55 for (bucket = FIRSTBUCKET, bsiz = 1<<FIRSTBUCKET;
56 bucket < NBUCKETS; bucket++, bsiz <<= 1)
57 if (free_list[bucket] != NULL && bsiz+sizeof(M_HEAD) >= *np) {
58 *np = bsiz+sizeof(M_HEAD);
59 p = (char *)free_list[bucket];
60 free_list[bucket] = free_list[bucket]->next;
61 return(p);
62 }
63 *np = 0;
64 return(NULL);
65 }
66
67
68 char *
69 bmalloc(n) /* allocate a block of n bytes, sans header */
70 register unsigned n;
71 {
72 extern char *sbrk();
73 static unsigned pagesz = 0;
74 static unsigned amnt;
75 static char *bpos;
76 static unsigned nrem;
77 unsigned thisamnt;
78 register char *p;
79
80 if (pagesz == 0) { /* initialize */
81 pagesz = amnt = getpagesize();
82 nrem = (int)sbrk(0); /* page align break */
83 nrem = pagesz - (nrem&(pagesz-1));
84 bpos = sbrk(nrem); /* word aligned! */
85 if ((int)bpos == -1)
86 return(NULL);
87 }
88
89 n = (n+(BYTES_WORD-1))&~(BYTES_WORD-1); /* word align rqst. */
90
91 if (n > nrem) { /* need more core */
92 if (n > amnt) { /* big chunk */
93 thisamnt = (n+(pagesz-1))&~(pagesz-1);
94 if (thisamnt <= MAXINCR) /* increase amnt */
95 amnt = thisamnt;
96 } else
97 thisamnt = amnt;
98 p = sbrk(thisamnt);
99 if ((int)p == -1) { /* uh-oh, ENOMEM */
100 thisamnt = n; /* search free lists */
101 p = mscrounge(&thisamnt);
102 if (p == NULL) /* we're really out */
103 return(NULL);
104 }
105 if (p != bpos+nrem) { /* not an increment */
106 bfree(bpos, nrem); /* free what we have */
107 bpos = p;
108 nrem = thisamnt;
109 } else /* otherwise tack on */
110 nrem += thisamnt;
111 }
112 p = bpos;
113 bpos += n; /* advance */
114 nrem -= n;
115 return(p);
116 }
117
118
119 bfree(p, n) /* free n bytes of random memory */
120 register char *p;
121 register unsigned n;
122 {
123 register int bucket;
124 register unsigned bsiz;
125 /* align pointer */
126 bsiz = BYTES_WORD - ((unsigned)p&~(BYTES_WORD-1));
127 if (bsiz < BYTES_WORD) {
128 p += bsiz;
129 n -= bsiz;
130 }
131 /* fill big buckets first */
132 for (bucket = NBUCKETS-1, bsiz = 1<<(NBUCKETS-1);
133 bucket >= FIRSTBUCKET; bucket--, bsiz >>= 1)
134 if (n >= bsiz+sizeof(M_HEAD)) {
135 ((M_HEAD *)p)->next = free_list[bucket];
136 free_list[bucket] = (M_HEAD *)p;
137 p += bsiz+sizeof(M_HEAD);
138 n -= bsiz+sizeof(M_HEAD);
139 }
140 }
141
142
143 char *
144 malloc(n) /* allocate n bytes of memory */
145 unsigned n;
146 {
147 register M_HEAD *mp;
148 register int bucket;
149 register unsigned bsiz;
150
151 if (n == 0)
152 return(NULL);
153 /* find first bucket that fits */
154 bucket = FIRSTBUCKET;
155 for (bsiz = 1<<FIRSTBUCKET; bsiz < n; bsiz <<= 1)
156 bucket++;
157 if (free_list[bucket] == NULL) { /* need more core */
158 mp = (M_HEAD *)bmalloc(bsiz+sizeof(M_HEAD));
159 if (mp == NULL)
160 return(NULL);
161 } else { /* got it */
162 mp = free_list[bucket];
163 free_list[bucket] = mp->next;
164 }
165 mp->bucket = bucket; /* tag block */
166 return((char *)(mp+1));
167 }
168
169
170 char *
171 realloc(op, n) /* reallocate memory using malloc() */
172 char *op;
173 unsigned n;
174 {
175 register char *p;
176 register unsigned on;
177
178 if (op != NULL)
179 on = 1 << ((M_HEAD *)op-1)->bucket;
180 else
181 on = 0;
182 if (n <= on && n > on>>1)
183 return(op); /* same bucket */
184 p = malloc(n);
185 if (p != NULL)
186 #ifdef BSD
187 bcopy(op, p, n>on ? on : n);
188 #else
189 (void)memcpy(p, op, n>on ? on : n);
190 #endif
191 free(op);
192 return(p);
193 }
194
195
196 free(p) /* free memory allocated by malloc */
197 char *p;
198 {
199 register M_HEAD *mp;
200 register int bucket;
201
202 if (p == NULL)
203 return;
204 mp = (M_HEAD *)p - 1;
205 bucket = mp->bucket;
206 mp->next = free_list[bucket];
207 free_list[bucket] = mp;
208 }
209
210
211 #ifndef NOVMEM
212 #ifndef BSD
213 #include <sys/var.h>
214 int
215 getpagesize() /* use SYSV var structure to get page size */
216 {
217 static int pagesz = 0;
218 struct var v;
219
220 if (pagesz == 0) {
221 uvar(&v);
222 pagesz = 1 << v.v_pageshift;
223 }
224 return(pagesz);
225 }
226 #endif
227 #endif