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

# 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     #define NULL 0
23    
24     #ifndef ALIGN
25     #define ALIGN int /* align type */
26     #endif
27     #define BYTES_WORD sizeof(ALIGN)
28    
29 greg 1.3 #define MAXINCR (1<<18) /* largest sbrk(2) increment */
30    
31 greg 1.1 #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 greg 1.4 mscrounge(np) /* search free lists to satisfy request */
49 greg 1.3 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 greg 1.1 bmalloc(n) /* allocate a block of n bytes, sans header */
70     register unsigned n;
71     {
72     extern char *sbrk();
73 greg 1.3 static unsigned pagesz = 0;
74     static unsigned amnt;
75 greg 1.1 static char *bpos;
76 greg 1.3 static unsigned nrem;
77     unsigned thisamnt;
78 greg 1.1 register char *p;
79    
80     if (pagesz == 0) { /* initialize */
81 greg 1.2 pagesz = amnt = getpagesize();
82 greg 1.1 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 greg 1.3 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 greg 1.4 if ((int)p == -1) { /* uh-oh, ENOMEM */
100 greg 1.3 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 greg 1.4 bfree(bpos, nrem); /* free what we have */
107 greg 1.1 bpos = p;
108 greg 1.3 nrem = thisamnt;
109 greg 1.4 } else /* otherwise tack on */
110 greg 1.3 nrem += thisamnt;
111 greg 1.1 }
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 greg 1.2 register char *p;
121     register unsigned n;
122 greg 1.1 {
123     register int bucket;
124     register unsigned bsiz;
125 greg 1.4 /* align pointer */
126     bsiz = BYTES_WORD - ((unsigned)p&~(BYTES_WORD-1));
127     if (bsiz < BYTES_WORD) {
128     p += bsiz;
129     n -= bsiz;
130 greg 1.1 }
131 greg 1.4 /* 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 greg 1.1 }
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 greg 1.2 if (n == 0)
152     return(NULL);
153     /* find first bucket that fits */
154 greg 1.1 bucket = FIRSTBUCKET;
155     for (bsiz = 1<<FIRSTBUCKET; bsiz < n; bsiz <<= 1)
156     bucket++;
157 greg 1.4 if (free_list[bucket] == NULL) { /* need more core */
158 greg 1.1 mp = (M_HEAD *)bmalloc(bsiz+sizeof(M_HEAD));
159     if (mp == NULL)
160     return(NULL);
161 greg 1.4 } else { /* got it */
162 greg 1.1 mp = free_list[bucket];
163     free_list[bucket] = mp->next;
164     }
165 greg 1.4 mp->bucket = bucket; /* tag block */
166 greg 1.1 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 greg 1.5 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 greg 1.1 #ifdef BSD
187 greg 1.2 bcopy(op, p, n>on ? on : n);
188 greg 1.1 #else
189 greg 1.2 (void)memcpy(p, op, n>on ? on : n);
190 greg 1.1 #endif
191 greg 1.5 free(op);
192 greg 1.1 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 greg 1.2 if (p == NULL)
203     return;
204 greg 1.1 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