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

# User Rev Content
1 greg 1.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 greg 1.4 * 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 greg 1.3 * 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 greg 1.1 *
19     * Greg Ward Lawrence Berkeley Laboratory
20     */
21    
22 greg 1.6 #include <errno.h>
23    
24 greg 1.1 #define NULL 0
25    
26     #ifndef ALIGN
27     #define ALIGN int /* align type */
28     #endif
29     #define BYTES_WORD sizeof(ALIGN)
30    
31 greg 1.3 #define MAXINCR (1<<18) /* largest sbrk(2) increment */
32    
33 greg 1.1 #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 greg 1.4 mscrounge(np) /* search free lists to satisfy request */
51 greg 1.3 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 greg 1.1 bmalloc(n) /* allocate a block of n bytes, sans header */
72     register unsigned n;
73     {
74     extern char *sbrk();
75 greg 1.3 static unsigned pagesz = 0;
76     static unsigned amnt;
77 greg 1.1 static char *bpos;
78 greg 1.3 static unsigned nrem;
79     unsigned thisamnt;
80 greg 1.1 register char *p;
81    
82     if (pagesz == 0) { /* initialize */
83 greg 1.2 pagesz = amnt = getpagesize();
84 greg 1.1 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 greg 1.3 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 greg 1.4 if ((int)p == -1) { /* uh-oh, ENOMEM */
102 greg 1.3 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 greg 1.4 bfree(bpos, nrem); /* free what we have */
109 greg 1.1 bpos = p;
110 greg 1.3 nrem = thisamnt;
111 greg 1.4 } else /* otherwise tack on */
112 greg 1.3 nrem += thisamnt;
113 greg 1.1 }
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 greg 1.2 register char *p;
123     register unsigned n;
124 greg 1.1 {
125     register int bucket;
126     register unsigned bsiz;
127 greg 1.4 /* align pointer */
128 greg 1.6 bsiz = BYTES_WORD - ((unsigned)p&(BYTES_WORD-1));
129 greg 1.4 if (bsiz < BYTES_WORD) {
130     p += bsiz;
131     n -= bsiz;
132 greg 1.1 }
133 greg 1.4 /* 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 greg 1.1 }
143    
144    
145     char *
146     malloc(n) /* allocate n bytes of memory */
147     unsigned n;
148     {
149 greg 1.6 extern int errno;
150 greg 1.1 register M_HEAD *mp;
151     register int bucket;
152     register unsigned bsiz;
153    
154 greg 1.2 if (n == 0)
155     return(NULL);
156     /* find first bucket that fits */
157 greg 1.6 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 greg 1.4 if (free_list[bucket] == NULL) { /* need more core */
166 greg 1.1 mp = (M_HEAD *)bmalloc(bsiz+sizeof(M_HEAD));
167     if (mp == NULL)
168     return(NULL);
169 greg 1.4 } else { /* got it */
170 greg 1.1 mp = free_list[bucket];
171     free_list[bucket] = mp->next;
172     }
173 greg 1.4 mp->bucket = bucket; /* tag block */
174 greg 1.1 return((char *)(mp+1));
175     }
176    
177    
178     char *
179     realloc(op, n) /* reallocate memory using malloc() */
180 greg 1.6 register char *op;
181 greg 1.1 unsigned n;
182     {
183 greg 1.6 char *p;
184 greg 1.1 register unsigned on;
185 greg 1.6 /* get old size */
186 greg 1.5 if (op != NULL)
187     on = 1 << ((M_HEAD *)op-1)->bucket;
188     else
189     on = 0;
190 greg 1.6 if (n <= on && (n > on>>1 || on == 1<<FIRSTBUCKET))
191 greg 1.5 return(op); /* same bucket */
192     p = malloc(n);
193     if (p != NULL)
194 greg 1.1 #ifdef BSD
195 greg 1.2 bcopy(op, p, n>on ? on : n);
196 greg 1.1 #else
197 greg 1.2 (void)memcpy(p, op, n>on ? on : n);
198 greg 1.1 #endif
199 greg 1.5 free(op);
200 greg 1.1 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 greg 1.2 if (p == NULL)
211     return;
212 greg 1.1 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