* configure.in: Fix sed invocation for GFORTRAN_FOR_TARGET.
[official-gcc.git] / libbanshee / libcompat / regions.c
blob6426fd68d1ea681bd64f2fc24cac810ae616645a
1 /*
2 * Copyright (c) 1999-2001
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 /* Idea: clear on page alloc rather than individual alloc
31 Turns out not so good (on lcc at least, seems a wash on mudlle):
32 logically should be bad for small regions (less than a few pages)
34 #undef PRECLEAR
35 #undef REGION_PROFILE
36 #include "regions.h"
37 #include <assert.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include "radix-tree.h"
41 #define RPAGESIZE (1 << RPAGELOG)
42 #define PAGE_GROUP_SIZE 32
43 #define K 4
44 #define MAXPAGE (1 << (32 - RPAGELOG))
46 #define PAGENB(x) ((__rcintptr)(x) >> RPAGELOG)
48 #define ALIGN(x, n) (((x) + ((n) - 1)) & ~((n) - 1))
49 #define PALIGN(x, n) ((void *)ALIGN((__rcintptr)(x), n))
50 #ifdef __GNUC__
51 #define RALIGNMENT __alignof(double)
52 #define PTRALIGNMENT __alignof(void *)
53 #define ALIGNMENT_LONG __alignof(unsigned long)
54 #else
55 #define RALIGNMENT 8
56 #define PTRALIGNMENT 4
57 #define ALIGNMENT_LONG 4
58 #endif
60 typedef unsigned long __rcintptr;
62 struct ablock {
63 char *base, *allocfrom;
66 struct allocator {
67 struct ablock page;
68 struct ablock superpage;
69 struct ablock hyperpage;
70 struct page *pages;
71 struct page *bigpages;
74 struct Region {
75 struct allocator normal;
76 struct Region *parent, *sibling, *children;
79 nomem_handler nomem_h;
81 /* dummy region for NULL and malloc memory */
82 struct Region zeroregion;
84 static void clear(void *start, __rcintptr size)
86 long *clear, *clearend;
88 clear = (long *)start;
89 clearend = (long *)((char *)start + size);
90 do *clear++ = 0;
91 while (clear < clearend) ;
94 #ifdef PRECLEAR
95 #define preclear clear
96 #define postclear(s, e)
97 #else
98 #define preclear(s, e)
99 #define postclear clear
100 #endif
102 #include "pages.c"
103 #include "alloc.c"
105 static void nochildren(region r)
107 if (r->children)
108 abort();
111 static void unlink_region(region r)
113 region *scan;
115 scan = &r->parent->children;
116 while (*scan != r)
117 scan = &(*scan)->sibling;
118 *scan = (*scan)->sibling;
121 static void link_region(region r, region parent)
123 r->sibling = parent->children;
124 r->parent = parent;
125 parent->children = r;
128 static int rstart;
130 void initregion(region r)
132 char *first =
133 (char *)r - rstart - offsetof(struct page, previous);
135 /* Start using page with region header as a pointer-containing page */
136 r->normal.page.base = first;
137 r->normal.page.allocfrom = (char *)(r + 1);
139 /* Guarantee failure for all other blocks */
140 r->normal.superpage.allocfrom = (char *)(K * RPAGESIZE + 1);
141 r->normal.hyperpage.allocfrom = (char *)(K * K * RPAGESIZE + 1);
143 /* Remember that r owns this page. */
144 r->normal.pages = (struct page *)first;
145 set_region(r->normal.pages, 1, r);
148 region newregion(void)
150 return newsubregion(&zeroregion);
153 region newsubregion(region parent)
155 char *first;
156 region r;
158 first = (char *)alloc_single_page(NULL);
159 preclear(first + offsetof(struct page, pagecount), RPAGESIZE - offsetof(struct page, pagecount));
161 /* stagger regions across cache lines a bit */
162 rstart += 64;
163 if (rstart > RPAGESIZE / K) rstart = 0;
164 r = (region)(first + rstart + offsetof(struct page, previous));
165 postclear(r, sizeof *r);
166 initregion(r);
168 link_region(r, parent);
170 return r;
173 void *typed_ralloc(region r, size_t size, type_t t)
175 return rstralloc0(r, size);
178 void *typed_rarrayextend(region r, void *old, size_t n, size_t size, type_t t)
180 return rstrextend0(r, old, n * size);
183 void *typed_rarrayalloc(region r, size_t n, size_t size, type_t t)
185 return typed_ralloc(r, n * size, t);
188 char *rstralloc(region r, size_t size)
190 void *mem, *dummy;
192 qalloc(r, &r->normal, &dummy, 0, 1, &mem, size, RALIGNMENT, 0);
194 return mem;
197 char *rstralloc0(region r, size_t size)
199 char *mem;
201 mem = rstralloc(r, size);
202 clear(mem, size);
204 return mem;
207 char *rstrdup(region r, const char *s)
209 char *news = rstralloc(r, strlen(s) + 1);
211 strcpy(news, s);
213 return news;
216 static char *internal_rstrextend(region r, const char *old, size_t newsize,
217 int needsclear)
219 /* For now we don't attempt to extend the old storage area */
220 void *newmem, *hdr;
221 unsigned long *oldhdr, oldsize;
223 qalloc(r, &r->normal, &hdr, sizeof(unsigned long), ALIGNMENT_LONG,
224 &newmem, newsize, RALIGNMENT, 0);
226 /* If we don't do this we can't find the header: */
227 hdr = (char *)newmem - sizeof(unsigned long);
229 *(unsigned long *)hdr = newsize;
231 if (old)
233 oldhdr = (unsigned long *)(old - ALIGNMENT_LONG);
234 oldsize = *oldhdr;
236 if (oldsize > newsize)
237 oldsize = newsize;
238 else if (needsclear)
239 clear((char *) newmem + oldsize, newsize - oldsize);
240 memcpy(newmem, old, oldsize);
242 else if (needsclear)
243 clear(newmem, newsize);
245 return newmem;
248 char *rstrextend(region r, const char *old, size_t newsize)
250 return internal_rstrextend(r, old, newsize, 0);
253 char *rstrextend0(region r, const char *old, size_t newsize)
255 return internal_rstrextend(r, old, newsize, 1);
258 void typed_rarraycopy(void *to, void *from, size_t n, size_t size, type_t type)
260 memcpy(to, from, n * size);
263 static void delregion(region r)
265 nochildren(r);
266 free_all_pages(r, &r->normal);
269 void deleteregion(region r)
271 unlink_region(r);
272 delregion(r);
275 void deleteregion_ptr(region *r)
277 region tmp = *r;
279 *r = NULL;
280 deleteregion(tmp);
283 void deleteregion_array(int n, region *regions)
285 int i;
287 for (i = 0; i < n; i++)
288 unlink_region(regions[i]);
290 for (i = 0; i < n; i++)
292 delregion(regions[i]);
293 regions[i] = NULL;
297 region regionof(void *ptr)
299 return radix_tree_lookup (&__rcregionmap, (unsigned long)ptr >> RPAGELOG);
302 void region_init(void)
304 static int initialized = 0;
305 radix_tree_init ();
306 if ( initialized )
307 return;
308 else
310 rstart = -64; /* Save 64 bytes of memory! (sometimes ;-)) */
311 init_pages();
314 initialized = 1;
317 nomem_handler set_nomem_handler(nomem_handler newhandler)
319 nomem_handler oldh = nomem_h;
321 nomem_h = newhandler;
323 return oldh;
327 int region_main(int argc, char **argv, char **envp);
329 int main(int argc, char **argv, char **envp)
331 region_init();
332 return region_main(argc, argv, envp);
337 /* Debugging support */
339 static FILE *out;
341 static void printref(void *x)
343 /* if (x >= (void *)__rcregionmap && x < (void *)&__rcregionmap[MAXPAGE])
344 return;
346 #ifdef RCPAIRS
347 if (x >= (void *)__rcregions && x < (void *)&__rcregions[MAXREGIONS])
348 return;
350 #endif
352 fprintf(out, "info symbol 0x%p\n", x);
355 void findrefs(region r, void *from, void *to)
357 char *f;
359 if (!out)
360 out = fopen("/dev/tty", "w");
362 for (f = PALIGN(from, PTRALIGNMENT); f < (char *)to; f += PTRALIGNMENT)
363 if (regionof(*(void **)f) == r)
364 printref(f);
366 fflush(out);
369 #ifdef sparc
370 extern void _DYNAMIC, _end;
372 void findgrefs(region r)
374 findrefs(r, &_DYNAMIC, &_end);
376 #endif
378 void findrrefs(region r, region from)
380 struct page *p;
382 for (p = from->normal.pages; p; p = p->next)
383 findrefs(r, (char *)&p->previous, (char *)p + RPAGESIZE);
385 for (p = r->normal.bigpages; p; p = p->next)
386 findrefs(r, (char *)&p->previous, (char *)p + p->pagecount * RPAGESIZE);