Reason for cygwin GCC 2.97 non-bootstrap found
Zack Weinberg
zackw@Stanford.EDU
Mon Nov 20 15:42:00 GMT 2000
On Mon, Nov 20, 2000 at 05:45:26PM -0500, Kelley Cook wrote:
> After much binary searching this weekend, I discovered the reason why
> Cygwin hasn't been able to bootstrap since late August.
...
> * ggc-page.c (alloc_page): If HAVE_MMAP_ANYWHERE and we're
> asked for one page, allocate GGC_QUIRE_SIZE of them and put
> the extras on the free list.
I am not familiar with Cygwin internals either. However, the
underlying Windows primitives - MapViewOfFile, UnmapViewOfFile - do
not appear to support allocating a large chunk of memory and then
freeing bits and pieces of it, which is what the above winds up
doing. (I am basing this on a rapid skim of the Windows API docs
available, with effort, from msdn.microsoft.com. I may be wrong.)
That change was a marginal performance hack and I don't think it'd do
any harm to scrap it. However, I am currently testing a patch which
moves the memory allocation mess into libiberty. (It's a modified
version of the patch by Alexandre Oliva and Laurnyas Bivenis - less
complex, hopefully just as effective.) I'd be curious to know how it
works on cygwin. Patch is appended.
It'd probably be a good idea to add additional autoconf and #ifdef
logic so that xvalloc.c uses VirtualAlloc() instead of Cygwin's mmap
on Win32 hosts.
WARNING: This patch temporarily removes the ability to allocate
objects larger than one page with ggc_alloc. I haven't yet had any
problems, but a ridiculously huge switch statement might trip over the
limitation.
NOTE: There are a bunch of technically unrelated cleanups to the
libiberty configure.in in here.
zw
gcc:
* Makefile.in: Take out GGC, GGC_LIB; unconditionally use
ggc-page.o in OBJS.
(configure): Depend also on aclocal.m4.
* aclocal.m4 (AC_FUNC_MMAP_ANYWHERE): Remove.
(AC_FUNC_MMAP_FILE): Don't AC_REQUIRE AC_FUNC_MMAP_ANYWHERE.
* configure.in: Don't use AC_FUNC_MMAP_ANYWHERE. Remove GGC
selection logic.
* configure, config.in: Regenerate.
* ggc-page.c: Remove all code which uses mmap or valloc
directly. Remove code handling allocations of >1 page. Use
xvalloc and xvfree, provided by libiberty.
libiberty:
* acconfig.h: Delete.
* aclocal.m4 (libiberty_AC_PROG_CC): Move here from configure.in.
(libiberty_FUNC_MMAP_ALLOCATION): New.
(AC_DEFINE_NOAUTOHEADER): Temporary hack to avoid autoheader bug.
* configure.in: Call AC_C_CONST, AC_C_INLINE,
libiberty_FUNC_MMAP_AUTOHEADER, and AC_CHECK_FUNCS for
memalign, valloc, and posix_valloc.
Use 3-arg form of AC_DEFINE in dummy declarations block, so
acconfig.h is unnecessary. Use AC_DEFINE_NOAUTOHEADER where
necessary to avoid duplicate entries in config.in.
* libiberty.h (xmalloc_failed, xvalloc, xvfree, xvalloc_init):
New functions.
* Makefile.in (CFILES): Add xvalloc.c.
(REQUIRED_OFILES): Add xvalloc.o.
(xvalloc.o): New rule.
* xvalloc.c: New file.
* xmalloc.c: Split out failure reporting to xmalloc_failed,
and export it.
===================================================================
Index: gcc/Makefile.in
--- gcc/Makefile.in 2000/11/19 00:30:05 1.545
+++ gcc/Makefile.in 2000/11/20 23:27:41
@@ -358,12 +358,6 @@ CLIB=
# system library.
OBSTACK=obstack.o
-# The GC method to be used on this system.
-GGC=@GGC@.o
-
-# If a supplementary library is being used for the GC.
-GGC_LIB=
-
# Configure will set these if you need vfprintf and possibly _doprnt support.
VFPRINTF=@vfprintf@
DOPRINT=@doprint@
@@ -732,10 +726,10 @@ OBJS = diagnostic.o version.o tree.o pri
regclass.o regmove.o local-alloc.o global.o reload.o reload1.o caller-save.o \
insn-peep.o reorg.o haifa-sched.o final.o recog.o reg-stack.o regrename.o \
insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o lcm.o \
- profile.o insn-attrtab.o $(out_object_file) $(EXTRA_OBJS) convert.o \
- mbchar.o splay-tree.o graph.o sbitmap.o resource.o hash.o predict.o \
- lists.o ggc-common.o $(GGC) stringpool.o simplify-rtx.o ssa.o bb-reorder.o \
- sibcall.o conflict.o timevar.o ifcvt.o dominance.o dependence.o dce.o
+ profile.o insn-attrtab.o convert.o mbchar.o graph.o sbitmap.o resource.o \
+ hash.o predict.o lists.o ggc-common.o ggc-page.o stringpool.o simplify-rtx.o \
+ ssa.o bb-reorder.o sibcall.o conflict.o timevar.o ifcvt.o dominance.o dce.o \
+ dependence.o $(out_object_file) $(EXTRA_OBJS)
BACKEND = toplev.o libbackend.a
@@ -862,7 +856,7 @@ Makefile: $(srcdir)/Makefile.in config.s
LANGUAGES="$(CONFIG_LANGUAGES)" $(SHELL) config.run
rm -f config.run
-$(srcdir)/configure: $(srcdir)/configure.in
+$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4
(cd $(srcdir) && autoconf)
gccbug: $(srcdir)/gccbug.in
===================================================================
Index: gcc/aclocal.m4
--- gcc/aclocal.m4 2000/10/09 08:36:36 1.37
+++ gcc/aclocal.m4 2000/11/20 23:27:42
@@ -734,104 +734,9 @@ fi
AC_SUBST($1)dnl
])
-# Check whether mmap can map an arbitrary page from /dev/zero or with
-# MAP_ANONYMOUS, without MAP_FIXED.
-AC_DEFUN([AC_FUNC_MMAP_ANYWHERE],
-[AC_CHECK_HEADERS(unistd.h)
-AC_CHECK_FUNCS(getpagesize)
-AC_CACHE_CHECK(for working mmap which provides zeroed pages anywhere,
- ac_cv_func_mmap_anywhere,
-[AC_TRY_RUN([
-/* Test by Richard Henderson and Alexandre Oliva.
- Check whether mmap MAP_ANONYMOUS or mmap from /dev/zero works. */
-#include <sys/types.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
-# define MAP_ANONYMOUS MAP_ANON
-#endif
-
-/* This mess was copied from the GNU getpagesize.h. */
-#ifndef HAVE_GETPAGESIZE
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-/* Assume that all systems that can run configure have sys/param.h. */
-# ifndef HAVE_SYS_PARAM_H
-# define HAVE_SYS_PARAM_H 1
-# endif
-
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# ifdef EXEC_PAGESIZE
-# define getpagesize() EXEC_PAGESIZE
-# else /* no EXEC_PAGESIZE */
-# ifdef NBPG
-# define getpagesize() NBPG * CLSIZE
-# ifndef CLSIZE
-# define CLSIZE 1
-# endif /* no CLSIZE */
-# else /* no NBPG */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
-
-int main()
-{
- char *x;
- int fd, pg;
-
-#ifndef MAP_ANONYMOUS
- fd = open("/dev/zero", O_RDWR);
- if (fd < 0)
- exit(1);
-#endif
-
- pg = getpagesize();
-#ifdef MAP_ANONYMOUS
- x = (char*)mmap(0, pg, PROT_READ|PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-#else
- x = (char*)mmap(0, pg, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
-#endif
- if (x == (char *) -1)
- exit(2);
-
- *(int *)x += 1;
-
- if (munmap(x, pg) < 0)
- exit(3);
-
- exit(0);
-}], ac_cv_func_mmap_anywhere=yes, ac_cv_func_mmap_anywhere=no,
-ac_cv_func_mmap_anywhere=no)])
-if test $ac_cv_func_mmap_anywhere = yes; then
- AC_DEFINE(HAVE_MMAP_ANYWHERE, 1,
- [Define if mmap can get us zeroed pages without MAP_FIXED.])
-fi
-])
-
# Check whether mmap can map a plain file, without MAP_FIXED.
-AC_DEFUN([AC_FUNC_MMAP_FILE],
-[AC_REQUIRE([AC_FUNC_MMAP_ANYWHERE])dnl
-AC_CACHE_CHECK(for working mmap of a file, ac_cv_func_mmap_file,
+AC_DEFUN(AC_FUNC_MMAP_FILE,
+[AC_CACHE_CHECK(for working mmap of a file, ac_cv_func_mmap_file,
[# Create a file one thousand bytes long.
for i in 1 2 3 4 5 6 7 8 9 0
do for j in 1 2 3 4 5 6 7 8 9 0
===================================================================
Index: gcc/configure.in
--- gcc/configure.in 2000/11/19 05:00:10 1.455
+++ gcc/configure.in 2000/11/20 23:27:44
@@ -581,7 +581,6 @@ case "${host}" in
;;
esac
AC_FUNC_VFORK
-AC_FUNC_MMAP_ANYWHERE
AC_FUNC_MMAP_FILE
# We will need to find libiberty.h and ansidecl.h
@@ -1566,27 +1565,6 @@ if test $thread_file != single; then
gthread_flags=-DHAVE_GTHR_DEFAULT
fi
AC_SUBST(gthread_flags)
-
-# Find out what GC implementation we want, or may, use.
-AC_ARG_WITH(gc,
-[ --with-gc={simple,page} Choose the garbage collection mechanism to use
- with the compiler.],
-[case "$withval" in
- simple | page)
- GGC=ggc-$withval
- ;;
- *)
- AC_MSG_ERROR([$withval is an invalid option to --with-gc])
- ;;
-esac],
-[if test $ac_cv_func_mmap_anywhere = yes \
- || test $ac_cv_func_valloc = yes; then
- GGC=ggc-page
-else
- GGC=ggc-simple
-fi])
-AC_SUBST(GGC)
-echo "Using $GGC for garbage collection."
# Use the system's zlib library.
zlibdir=-L../zlib
===================================================================
Index: gcc/ggc-page.c
--- gcc/ggc-page.c 2000/11/17 06:05:15 1.31
+++ gcc/ggc-page.c 2000/11/20 23:27:44
@@ -28,19 +28,8 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "ggc.h"
#include "timevar.h"
+#include "libiberty.h"
-#ifdef HAVE_MMAP_ANYWHERE
-#include <sys/mman.h>
-#endif
-
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-
-#if !defined (MAP_ANONYMOUS) && defined (MAP_ANON)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
/* Stategy:
This garbage-collecting allocator allocates objects on one of a set
@@ -142,10 +131,6 @@ typedef struct page_entry
this is the last page-entry. */
struct page_entry *next;
- /* The number of bytes allocated. (This will always be a multiple
- of the host system page size.) */
- size_t bytes;
-
/* The address at which the memory is allocated. */
char *page;
@@ -198,7 +183,8 @@ static struct globals
/* The Nth element in this array is a page with objects of size 2^N.
If there are any pages with free objects, they will be at the
head of the list. NULL if there are no page-entries for this
- object size. */
+ object size. Note that only the entries through G.lg_pagesize are
+ actually used. */
page_entry *pages[HOST_BITS_PER_PTR];
/* The Nth element in this array is the last page with objects of
@@ -225,11 +211,6 @@ static struct globals
/* The current depth in the context stack. */
unsigned short context_depth;
- /* A file descriptor open to /dev/zero for reading. */
-#if defined (HAVE_MMAP_ANYWHERE) && !defined(MAP_ANONYMOUS)
- int dev_zero_fd;
-#endif
-
/* A cache of free system pages. */
page_entry *free_pages;
@@ -243,9 +224,8 @@ static struct globals
(((Dividend) + (Divisor) - 1) / (Divisor))
/* The number of objects per allocation page, for objects of size
- 2^ORDER. */
-#define OBJECTS_PER_PAGE(Order) \
- ((Order) >= G.lg_pagesize ? 1 : G.pagesize / ((size_t)1 << (Order)))
+ 2^ORDER. Note that ORDER may not go above log2(G.pagesize). */
+#define OBJECTS_PER_PAGE(Order) (G.pagesize / ((size_t)1 << (Order)))
/* The size in bytes required to maintain a bitmap for the objects
on a page-entry. */
@@ -270,7 +250,6 @@ static struct globals
static int ggc_allocated_p PARAMS ((const void *));
static page_entry *lookup_page_table_entry PARAMS ((const void *));
static void set_page_table_entry PARAMS ((void *, page_entry *));
-static char *alloc_anon PARAMS ((char *, size_t));
static struct page_entry * alloc_page PARAMS ((unsigned));
static void free_page PARAMS ((struct page_entry *));
static void release_pages PARAMS ((void));
@@ -401,46 +380,6 @@ debug_print_page_list (order)
fflush (stdout);
}
-/* Allocate SIZE bytes of anonymous memory, preferably near PREF,
- (if non-null). */
-
-static inline char *
-alloc_anon (pref, size)
- char *pref ATTRIBUTE_UNUSED;
- size_t size;
-{
- char *page;
-
-#ifdef HAVE_MMAP_ANYWHERE
-#ifdef MAP_ANONYMOUS
- page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-#else
- page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, G.dev_zero_fd, 0);
-#endif
- if (page == (char *) MAP_FAILED)
- {
- fputs ("Virtual memory exhausted!\n", stderr);
- exit(1);
- }
-#else
-#ifdef HAVE_VALLOC
- page = (char *) valloc (size);
- if (!page)
- {
- fputs ("Virtual memory exhausted!\n", stderr);
- exit(1);
- }
-#endif /* HAVE_VALLOC */
-#endif /* HAVE_MMAP_ANYWHERE */
-
- /* Remember that we allocated this memory. */
- G.bytes_mapped += size;
-
- return page;
-}
-
/* Allocate a new page for allocating objects of size 2^ORDER,
and return an entry for it. The entry is not added to the
appropriate page_table list. */
@@ -449,30 +388,30 @@ static inline struct page_entry *
alloc_page (order)
unsigned order;
{
- struct page_entry *entry, *p, **pp;
+ struct page_entry *entry, *p;
char *page;
size_t num_objects;
size_t bitmap_size;
size_t page_entry_size;
- size_t entry_size;
num_objects = OBJECTS_PER_PAGE (order);
bitmap_size = BITMAP_SIZE (num_objects + 1);
page_entry_size = sizeof (page_entry) - sizeof (long) + bitmap_size;
- entry_size = num_objects * (1 << order);
+#ifdef ENABLE_CHECKING
+ if (num_objects * (1 << order) != G.pagesize)
+ abort ();
+#endif
+
entry = NULL;
page = NULL;
- /* Check the list of free pages for one we can use. */
- for (pp = &G.free_pages, p = *pp; p ; pp = &p->next, p = *pp)
- if (p->bytes == entry_size)
- break;
+ p = G.free_pages;
if (p != NULL)
{
/* Recycle the allocated memory from this page ... */
- *pp = p->next;
+ G.free_pages = p->next;
page = p->page;
/* ... and, if possible, the page entry itself. */
if (p->order == order)
@@ -483,36 +422,17 @@ alloc_page (order)
else
free (p);
}
-#ifdef HAVE_MMAP_ANYWHERE
- else if (entry_size == G.pagesize)
+ else
{
- /* We want just one page. Allocate a bunch of them and put the
- extras on the freelist. (Can only do this optimization with
- mmap for backing store.) */
- struct page_entry *e, *f = G.free_pages;
- int i;
-
- page = alloc_anon (NULL, entry_size * GGC_QUIRE_SIZE);
- /* This loop counts down so that the chain will be in ascending
- memory order. */
- for (i = GGC_QUIRE_SIZE - 1; i >= 1; i--)
- {
- e = (struct page_entry *) xcalloc (1, sizeof (struct page_entry));
- e->bytes = entry_size;
- e->page = page + i*entry_size;
- e->next = f;
- f = e;
- }
- G.free_pages = f;
+ page = xvalloc (G.pagesize);
+ /* Remember that we allocated this memory. */
+ G.bytes_mapped += G.pagesize;
}
-#endif
- else
- page = alloc_anon (NULL, entry_size);
+
if (entry == NULL)
entry = (struct page_entry *) xcalloc (1, page_entry_size);
- entry->bytes = entry_size;
entry->page = page;
entry->context_depth = G.context_depth;
entry->order = order;
@@ -527,9 +447,8 @@ alloc_page (order)
set_page_table_entry (page, entry);
if (GGC_DEBUG_LEVEL >= 2)
- fprintf (G.debug_file,
- "Allocating page at %p, object size=%d, data %p-%p\n",
- (PTR) entry, 1 << order, page, page + entry_size - 1);
+ fprintf (G.debug_file, "Allocating page at %p, object size=%d\n",
+ (PTR) entry, 1 << order);
return entry;
}
@@ -542,8 +461,7 @@ free_page (entry)
{
if (GGC_DEBUG_LEVEL >= 2)
fprintf (G.debug_file,
- "Deallocating page at %p, data %p-%p\n", (PTR) entry,
- entry->page, entry->page + entry->bytes - 1);
+ "Deallocating page at %p\n", (PTR) entry);
set_page_table_entry (entry->page, NULL);
@@ -558,44 +476,13 @@ release_pages ()
{
page_entry *p, *next;
-#ifdef HAVE_MMAP_ANYWHERE
- char *start;
- size_t len;
-
- /* Gather up adjacent pages so they are unmapped together. */
- p = G.free_pages;
-
- while (p)
- {
- start = p->page;
- next = p->next;
- len = p->bytes;
- free (p);
- p = next;
-
- while (p && p->page == start + len)
- {
- next = p->next;
- len += p->bytes;
- free (p);
- p = next;
- }
-
- munmap (start, len);
- G.bytes_mapped -= len;
- }
-#else
-#ifdef HAVE_VALLOC
-
for (p = G.free_pages; p; p = next)
{
next = p->next;
- free (p->page);
- G.bytes_mapped -= p->bytes;
+ xvfree (p->page, G.pagesize);
+ G.bytes_mapped -= G.pagesize;
free (p);
}
-#endif /* HAVE_VALLOC */
-#endif /* HAVE_MMAP_ANYWHERE */
G.free_pages = NULL;
}
@@ -635,6 +522,9 @@ ggc_alloc (size)
struct page_entry *entry;
void *result;
+ if (size > G.pagesize)
+ fatal ("cannot ggc_alloc %d byte chunk, larger than one page", size);
+
if (size <= 256)
order = size_lookup[size];
else
@@ -803,12 +693,7 @@ init_ggc ()
{
G.pagesize = getpagesize();
G.lg_pagesize = exact_log2 (G.pagesize);
-
-#if defined (HAVE_MMAP_ANYWHERE) && !defined(MAP_ANONYMOUS)
- G.dev_zero_fd = open ("/dev/zero", O_RDONLY);
- if (G.dev_zero_fd == -1)
- abort ();
-#endif
+ G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
#if 0
G.debug_file = fopen ("ggc-mmap.debug", "w");
@@ -816,27 +701,7 @@ init_ggc ()
G.debug_file = stdout;
#endif
- G.allocated_last_gc = GGC_MIN_LAST_ALLOCATED;
-
-#ifdef HAVE_MMAP_ANYWHERE
- /* StunOS has an amazing off-by-one error for the first mmap allocation
- after fiddling with RLIMIT_STACK. The result, as hard as it is to
- believe, is an unaligned page allocation, which would cause us to
- hork badly if we tried to use it. */
- {
- char *p = alloc_anon (NULL, G.pagesize);
- if ((size_t)p & (G.pagesize - 1))
- {
- /* How losing. Discard this one and try another. If we still
- can't get something useful, give up. */
-
- p = alloc_anon (NULL, G.pagesize);
- if ((size_t)p & (G.pagesize - 1))
- abort ();
- }
- munmap (p, G.pagesize);
- }
-#endif
+ xvalloc_init ();
}
/* Increment the `GC context'. Objects allocated in an outer context
@@ -903,7 +768,7 @@ ggc_pop_context ()
/* Any remaining pages in the popped context are lowered to the new
current context; i.e. objects allocated in the popped context and
left over are imported into the previous context. */
- for (order = 2; order < HOST_BITS_PER_PTR; order++)
+ for (order = 2; order <= G.lg_pagesize; order++)
{
page_entry *p;
@@ -931,7 +796,7 @@ clear_marks ()
{
unsigned order;
- for (order = 2; order < HOST_BITS_PER_PTR; order++)
+ for (order = 2; order <= G.lg_pagesize; order++)
{
size_t num_objects = OBJECTS_PER_PAGE (order);
size_t bitmap_size = BITMAP_SIZE (num_objects + 1);
@@ -975,7 +840,7 @@ sweep_pages ()
{
unsigned order;
- for (order = 2; order < HOST_BITS_PER_PTR; order++)
+ for (order = 2; order <= G.lg_pagesize; order++)
{
/* The last page-entry to consider, regardless of entries
placed at the end of the list. */
@@ -1082,7 +947,7 @@ poison_pages ()
{
unsigned order;
- for (order = 2; order < HOST_BITS_PER_PTR; order++)
+ for (order = 2; order <= G.lg_pagesize; order++)
{
size_t num_objects = OBJECTS_PER_PAGE (order);
size_t size = (size_t) 1 << order;
@@ -1188,7 +1053,7 @@ ggc_print_statistics ()
allocation. */
fprintf (stderr, "\n%-5s %10s %10s %10s\n",
"Log", "Allocated", "Used", "Overhead");
- for (i = 0; i < HOST_BITS_PER_PTR; ++i)
+ for (i = 0; i <= G.lg_pagesize; ++i)
{
page_entry *p;
size_t allocated;
@@ -1206,7 +1071,7 @@ ggc_print_statistics ()
out how much memory the page table is using. */
for (p = G.pages[i]; p; p = p->next)
{
- allocated += p->bytes;
+ allocated += G.pagesize;
in_use +=
(OBJECTS_PER_PAGE (i) - p->num_free_objects) * (1 << i);
===================================================================
Index: include/libiberty.h
--- include/libiberty.h 2000/08/24 20:28:15 1.13
+++ include/libiberty.h 2000/11/20 23:27:45
@@ -126,20 +126,25 @@ extern int xatexit PARAMS ((void (*fn) (
extern void xexit PARAMS ((int status)) ATTRIBUTE_NORETURN;
+#ifdef ANSI_PROTOTYPES
+/* Get a definition for size_t. */
+#include <stddef.h>
+/* Get a definition for va_list. */
+#include <stdarg.h>
+#endif
+
/* Set the program name used by xmalloc. */
extern void xmalloc_set_program_name PARAMS ((const char *));
+/* Report memory allocation failure. */
+
+extern void xmalloc_failed PARAMS ((size_t)) ATTRIBUTE_NORETURN;
+
/* Allocate memory without fail. If malloc fails, this will print a
message to stderr (using the name set by xmalloc_set_program_name,
if any) and then call xexit. */
-#ifdef ANSI_PROTOTYPES
-/* Get a definition for size_t. */
-#include <stddef.h>
-/* Get a definition for va_list. */
-#include <stdarg.h>
-#endif
extern PTR xmalloc PARAMS ((size_t)) ATTRIBUTE_MALLOC;
/* Reallocate memory without fail. This works like xmalloc. Note,
@@ -160,6 +165,19 @@ extern char *xstrdup PARAMS ((const char
/* Copy an existing memory buffer to a new memory buffer without fail. */
extern PTR xmemdup PARAMS ((const PTR, size_t, size_t)) ATTRIBUTE_MALLOC;
+
+/* Allocate a page-aligned memory block without fail. This may use mmap,
+ so you must use xvfree to free memory allocated by xvalloc. */
+
+extern char *xvalloc PARAMS ((size_t)) ATTRIBUTE_MALLOC;
+
+/* Release memory allocated by xvalloc. */
+
+extern void xvfree PARAMS ((char *, size_t));
+
+/* Initialize xvalloc internal structures. Must be called before
+ xvalloc is used. */
+extern void xvalloc_init PARAMS ((void));
/* hex character manipulation routines */
===================================================================
Index: libiberty/Makefile.in
--- libiberty/Makefile.in 2000/08/29 04:35:59 1.54
+++ libiberty/Makefile.in 2000/11/20 23:27:45
@@ -135,7 +135,7 @@ CFILES = asprintf.c alloca.c argv.c atex
strchr.c strdup.c strerror.c strncmp.c strrchr.c strsignal.c strstr.c \
strtod.c strtol.c strtoul.c tmpnam.c vasprintf.c vfork.c vfprintf.c \
vprintf.c vsprintf.c waitpid.c xatexit.c xexit.c xmalloc.c \
- xmemdup.c xstrdup.c xstrerror.c
+ xmemdup.c xstrdup.c xstrerror.c xvalloc.c
# These are always included in the library.
REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o cp-demangle.o \
@@ -143,7 +143,7 @@ REQUIRED_OFILES = argv.o choose-temp.o c
getruntime.o hashtab.o hex.o floatformat.o md5.o objalloc.o obstack.o \
partition.o pexecute.o sort.o spaces.o splay-tree.o strerror.o \
strsignal.o xatexit.o xexit.o xmalloc.o xmemdup.o xstrdup.o \
- xstrerror.o
+ xstrerror.o xvalloc.o
$(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) $(ALLOCA)
rm -f $(TARGETLIB)
@@ -297,5 +297,6 @@ xmalloc.o: config.h $(INCDIR)/libiberty.
xmemdup.o: config.h $(INCDIR)/libiberty.h
xstrdup.o: config.h $(INCDIR)/libiberty.h
xstrerror.o: config.h $(INCDIR)/libiberty.h
+xvalloc.o: config.h $(INCDIR)/libiberty.h
waitpid.o: config.h
hashtab.o: config.h $(INCDIR)/libiberty.h $(INCDIR)/hashtab.h $(INCDIR)/ansidecl.h
===================================================================
Index: libiberty/acconfig.h
--- libiberty/acconfig.h 1999/09/04 15:08:49 1.2
+++ libiberty/acconfig.h 2000/11/20 23:27:45
@@ -1,11 +0,0 @@
-/* Define if you have the sys_errlist variable. */
-#undef HAVE_SYS_ERRLIST
-
-/* Define if you have the sys_nerr variable. */
-#undef HAVE_SYS_NERR
-
-/* Define if you have the sys_siglist variable. */
-#undef HAVE_SYS_SIGLIST
-
-/* Define if you have the strerror function. */
-#undef HAVE_STRERROR
===================================================================
Index: libiberty/aclocal.m4
--- libiberty/aclocal.m4 2000/07/23 16:05:03 1.2
+++ libiberty/aclocal.m4 2000/11/20 23:27:45
@@ -83,3 +83,174 @@ then AC_DEFINE(NEED_DECLARATION_ERRNO, 1
[Define if errno must be declared even when <errno.h> is included.])
fi
])
+
+dnl FIXME: We temporarily define our own version of AC_PROG_CC. This is
+dnl copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
+dnl are probably using a cross compiler, which will not be able to fully
+dnl link an executable. This should really be fixed in autoconf
+dnl itself.
+AC_DEFUN(libiberty_AC_PROG_CC,
+[AC_BEFORE([$0], [AC_PROG_CPP])dnl
+AC_PROVIDE([AC_PROG_CC])
+AC_CHECK_PROG(CC, gcc, gcc)
+if test -z "$CC"; then
+ AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
+ test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
+fi
+
+AC_PROG_CC_GNU
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ ac_libiberty_warn_cflags='-W -Wall -Wtraditional -pedantic'
+dnl Check whether -g works, even if CFLAGS is set, in case the package
+dnl plays around with CFLAGS (such as to build both debugging and
+dnl normal versions of a library), tasteless as that idea is.
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=
+ AC_PROG_CC_G
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ elif test $ac_cv_prog_cc_g = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-O2"
+ fi
+else
+ GCC=
+ ac_libiberty_warn_cflags=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+AC_SUBST(ac_libiberty_warn_cflags)
+])
+
+dnl Check whether we can use mmap to allocate memory, with no
+dnl specification of the address to allocate at.
+dnl Defines HAVE_MMAP_ANON and HAVE_MMAP_DEV_ZERO, depending on which
+dnl technique you have to use.
+AC_DEFUN([libiberty_FUNC_MMAP_ALLOCATION],
+[AC_CHECK_HEADERS(unistd.h)
+AC_CHECK_FUNCS(getpagesize)
+cat >ct-mmap.inc <<'__END_OF_FILE__'
+/* Test by Richard Henderson and Alexandre Oliva.
+ Check whether mmap from /dev/zero works. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+/* This mess was copied from the GNU getpagesize.h. */
+#ifndef HAVE_GETPAGESIZE
+# ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# endif
+
+/* Assume that all systems that can run configure have sys/param.h. */
+# ifndef HAVE_SYS_PARAM_H
+# define HAVE_SYS_PARAM_H 1
+# endif
+
+# ifdef _SC_PAGESIZE
+# define getpagesize() sysconf(_SC_PAGESIZE)
+# else /* no _SC_PAGESIZE */
+# ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else /* no EXEC_PAGESIZE */
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif /* no CLSIZE */
+# else /* no NBPG */
+# ifdef NBPC
+# define getpagesize() NBPC
+# else /* no NBPC */
+# ifdef PAGESIZE
+# define getpagesize() PAGESIZE
+# endif /* PAGESIZE */
+# endif /* no NBPC */
+# endif /* no NBPG */
+# endif /* no EXEC_PAGESIZE */
+# else /* no HAVE_SYS_PARAM_H */
+# define getpagesize() 8192 /* punt totally */
+# endif /* no HAVE_SYS_PARAM_H */
+# endif /* no _SC_PAGESIZE */
+
+#endif /* no HAVE_GETPAGESIZE */
+
+#ifdef USE_DEV_ZERO
+# undef MAP_ANONYMOUS
+# define MAP_ANONYMOUS 0
+#else
+# if !defined MAP_ANONYMOUS && defined MAP_ANON
+# define MAP_ANONYMOUS MAP_ANON
+# endif
+#endif
+
+int main()
+{
+ char *x;
+ int pg;
+
+#ifdef USE_DEV_ZERO
+ int fd;
+
+ fd = open("/dev/zero", O_RDWR);
+ if (fd < 0)
+ exit(1);
+#else
+# define fd -1
+#endif
+
+ pg = getpagesize();
+ x = (char*)mmap(0, pg, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, fd, 0);
+ if (x == (char *) -1)
+ exit(2);
+
+ *(int *)x += 1;
+
+ if (munmap(x, pg) < 0)
+ exit(3);
+
+ exit(0);
+}
+__END_OF_FILE__
+
+AC_CACHE_CHECK(for working mmap with MAP_ANON, ac_cv_func_mmap_anon,
+[AC_TRY_RUN(
+[#include "ct-mmap.inc"],
+ ac_cv_func_mmap_anon=yes,
+ ac_cv_func_mmap_anon=no,
+ ac_cv_func_mmap_anon=no)
+])
+if test $ac_cv_func_mmap_anon = yes; then
+ AC_DEFINE(HAVE_MMAP_ANON, 1,
+ [Define if mmap can get us zeroed pages with MAP_ANON(YMOUS).])
+fi
+
+AC_CACHE_CHECK(for working mmap from /dev/zero, ac_cv_func_mmap_dev_zero,
+[AC_TRY_RUN(
+[#define USE_DEV_ZERO
+#include "ct-mmap.inc"],
+ ac_cv_func_mmap_dev_zero=yes,
+ ac_cv_func_mmap_dev_zero=no,
+ ac_cv_func_mmap_dev_zero=no)
+])
+if test $ac_cv_func_mmap_dev_zero = yes; then
+ AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
+ [Define if mmap can get us zeroed pages from /dev/zero.])
+fi
+rm -f ct-mmap.inc
+])
+
+dnl This hack works around a bug in autoheader. Take out after we
+dnl start insisting on autoconf >2.50.
+dnl Use of 'define' not 'AC_DEFUN' is deliberate.
+define(AC_DEFINE_NOAUTOHEADER,
+[cat >> confdefs.h <<\EOF
+[#define] $1 ifelse($#, 2, [$2], $#, 3, [$2], 1)
+EOF
+])
===================================================================
Index: libiberty/configure.in
--- libiberty/configure.in 2000/09/05 18:43:26 1.29
+++ libiberty/configure.in 2000/11/20 23:27:46
@@ -36,51 +36,11 @@ dnl to call AC_CHECK_PROG.
AC_CHECK_TOOL(AR, ar)
AC_CHECK_TOOL(RANLIB, ranlib, :)
-# FIXME: We temporarily define our own version of AC_PROG_CC. This is
-# copied from autoconf 2.12, but does not call AC_PROG_CC_WORKS. We
-# are probably using a cross compiler, which will not be able to fully
-# link an executable. This should really be fixed in autoconf
-# itself.
-
-AC_DEFUN(LIB_AC_PROG_CC,
-[AC_BEFORE([$0], [AC_PROG_CPP])dnl
-AC_PROVIDE([AC_PROG_CC])
-AC_CHECK_PROG(CC, gcc, gcc)
-if test -z "$CC"; then
- AC_CHECK_PROG(CC, cc, cc, , , /usr/ucb/cc)
- test -z "$CC" && AC_MSG_ERROR([no acceptable cc found in \$PATH])
-fi
-
-AC_PROG_CC_GNU
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
- ac_libiberty_warn_cflags='-W -Wall -Wtraditional -pedantic'
-dnl Check whether -g works, even if CFLAGS is set, in case the package
-dnl plays around with CFLAGS (such as to build both debugging and
-dnl normal versions of a library), tasteless as that idea is.
- ac_test_CFLAGS="${CFLAGS+set}"
- ac_save_CFLAGS="$CFLAGS"
- CFLAGS=
- AC_PROG_CC_G
- if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
- elif test $ac_cv_prog_cc_g = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-O2"
- fi
-else
- GCC=
- ac_libiberty_warn_cflags=
- test "${CFLAGS+set}" = set || CFLAGS="-g"
-fi
-])
-AC_SUBST(ac_libiberty_warn_cflags)
+libiberty_AC_PROG_CC
-LIB_AC_PROG_CC
-
AC_ISC_POSIX
+AC_C_CONST
+AC_C_INLINE
dnl When we start using libtool:
dnl Default to a non shared library. This may be overridden by the
@@ -172,11 +132,11 @@ if test "x" = "y"; then
AC_CHECK_FUNCS(memset putenv random rename rindex sigsetmask strcasecmp)
AC_CHECK_FUNCS(setenv strchr strdup strncasecmp strrchr strstr strtod strtol)
AC_CHECK_FUNCS(strtoul tmpnam vasprintf vfprintf vprintf vsprintf waitpid)
- AC_DEFINE(HAVE_SYS_ERRLIST)
- AC_DEFINE(HAVE_SYS_NERR)
- AC_DEFINE(HAVE_SYS_SIGLIST)
AC_CHECK_FUNCS(getrusage on_exit psignal strerror strsignal sysconf times)
AC_CHECK_FUNCS(sbrk gettimeofday)
+ AC_DEFINE(HAVE_SYS_ERRLIST, 1, [Define if you have the sys_errlist variable.])
+ AC_DEFINE(HAVE_SYS_NERR, 1, [Define if you have the sys_nerr variable.])
+ AC_DEFINE(HAVE_SYS_SIGLIST, 1, [Define if you have the sys_siglist variable.])
fi
# For each of these functions, if the host does not provide the
@@ -215,7 +175,7 @@ if test -n "${with_target_subdir}"; then
# dont have to check them here.
# Of the functions in $checkfuncs, newlib only has strerror.
- AC_DEFINE(HAVE_STRERROR)
+ AC_DEFINE_NOAUTOHEADER(HAVE_STRERROR)
setobjs=yes
@@ -256,7 +216,7 @@ if test -z "${setobjs}"; then
# don't have to check them here.
# Of the functions in $checkfuncs, VxWorks only has strerror.
- AC_DEFINE(HAVE_STRERROR)
+ AC_DEFINE_NOAUTOHEADER(HAVE_STRERROR)
setobjs=yes
;;
@@ -294,9 +254,8 @@ if test -z "${setobjs}"; then
*-*-mingw32*)
# Under mingw32, sys_nerr and sys_errlist exist, but they are
# macros, so the test below won't find them.
- vars="`echo $vars | sed -e 's/sys_nerr//' -e 's/sys_errlist//'`"
- AC_DEFINE(HAVE_SYS_NERR)
- AC_DEFINE(HAVE_SYS_ERRLIST)
+ libiberty_cv_var_sys_nerr=yes
+ libiberty_cv_var_sys_errlist=yes
;;
*-*-uwin*)
@@ -307,8 +266,8 @@ if test -z "${setobjs}"; then
# Under uwin 2.0+, sys_nerr and sys_errlist exist, but they are
# macros (actually, these are imported from a DLL, but the end effect
# is the same), so the test below won't find them.
- AC_DEFINE(HAVE_SYS_NERR)
- AC_DEFINE(HAVE_SYS_ERRLIST)
+ libiberty_cv_var_sys_nerr=yes
+ libiberty_cv_var_sys_errlist=yes
;;
esac
@@ -361,6 +320,10 @@ EOF
fi
libiberty_AC_FUNC_STRNCMP
+
+# These are used by xvalloc.c
+libiberty_FUNC_MMAP_ALLOCATION
+AC_CHECK_FUNCS(memalign valloc posix_valloc)
# Install a library built with a cross compiler in $(tooldir) rather
# than $(libdir).
===================================================================
Index: libiberty/xmalloc.c
--- libiberty/xmalloc.c 2000/05/18 22:48:34 1.9
+++ libiberty/xmalloc.c 2000/11/20 23:27:46
@@ -24,6 +24,10 @@ Boston, MA 02111-1307, USA. */
#include "libiberty.h"
#include <stdio.h>
+#include <errno.h>
+#ifdef NEED_DECLARATION_ERRNO
+extern int errno;
+#endif
#ifdef __STDC__
#include <stddef.h>
@@ -64,6 +68,36 @@ xmalloc_set_program_name (s)
#endif /* HAVE_SBRK */
}
+void
+xmalloc_failed (size)
+ size_t size;
+{
+ int save_errno = errno;
+
+#ifdef HAVE_SBRK
+ extern char **environ;
+ size_t allocated;
+
+ if (first_break != NULL)
+ allocated = (char *) sbrk (0) - first_break;
+ else
+ allocated = (char *) sbrk (0) - (char *) &environ;
+ fprintf (stderr,
+ "\n%s%sCannot allocate %lu bytes after allocating %lu bytes\n",
+ name, *name ? ": " : "",
+ (unsigned long) size, (unsigned long) allocated);
+#else /* HAVE_SBRK */
+ fprintf (stderr,
+ "\n%s%sCannot allocate %lu bytes\n",
+ name, *name ? ": " : "",
+ (unsigned long) size);
+#endif /* HAVE_SBRK */
+ fprintf (stderr, "%s%s(%s)\n",
+ name, *name ? ": " : "", xstrerror (save_errno));
+
+ xexit (1);
+}
+
PTR
xmalloc (size)
size_t size;
@@ -73,29 +107,10 @@ xmalloc (size)
if (size == 0)
size = 1;
newmem = malloc (size);
- if (!newmem)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- size_t allocated;
+ if (newmem)
+ return (newmem);
- if (first_break != NULL)
- allocated = (char *) sbrk (0) - first_break;
- else
- allocated = (char *) sbrk (0) - (char *) &environ;
- fprintf (stderr,
- "\n%s%sCannot allocate %lu bytes after allocating %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) size, (unsigned long) allocated);
-#else /* HAVE_SBRK */
- fprintf (stderr,
- "\n%s%sCannot allocate %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) size);
-#endif /* HAVE_SBRK */
- xexit (1);
- }
- return (newmem);
+ xmalloc_failed (size); /* doesn't return */
}
PTR
@@ -108,29 +123,10 @@ xcalloc (nelem, elsize)
nelem = elsize = 1;
newmem = calloc (nelem, elsize);
- if (!newmem)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- size_t allocated;
+ if (newmem)
+ return (newmem);
- if (first_break != NULL)
- allocated = (char *) sbrk (0) - first_break;
- else
- allocated = (char *) sbrk (0) - (char *) &environ;
- fprintf (stderr,
- "\n%s%sCannot allocate %lu bytes after allocating %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) (nelem * elsize), (unsigned long) allocated);
-#else /* HAVE_SBRK */
- fprintf (stderr,
- "\n%s%sCannot allocate %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) (nelem * elsize));
-#endif /* HAVE_SBRK */
- xexit (1);
- }
- return (newmem);
+ xmalloc_failed (nelem * elsize); /* doesn't return */
}
PTR
@@ -146,27 +142,8 @@ xrealloc (oldmem, size)
newmem = malloc (size);
else
newmem = realloc (oldmem, size);
- if (!newmem)
- {
-#ifdef HAVE_SBRK
- extern char **environ;
- size_t allocated;
+ if (newmem)
+ return (newmem);
- if (first_break != NULL)
- allocated = (char *) sbrk (0) - first_break;
- else
- allocated = (char *) sbrk (0) - (char *) &environ;
- fprintf (stderr,
- "\n%s%sCannot reallocate %lu bytes after allocating %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) size, (unsigned long) allocated);
-#else /* HAVE_SBRK */
- fprintf (stderr,
- "\n%s%sCannot reallocate %lu bytes\n",
- name, *name ? ": " : "",
- (unsigned long) size);
-#endif /* HAVE_SBRK */
- xexit (1);
- }
- return (newmem);
+ xmalloc_failed (size); /* doesn't return */
}
===================================================================
Index: libiberty/xvalloc.c
--- libiberty/xvalloc.c Tue May 5 13:32:27 1998
+++ libiberty/xvalloc.c Mon Nov 20 15:27:46 2000
@@ -0,0 +1,293 @@
+/* page-aligned memory allocation routines.
+ Copyright (C) 1999, 2000 Free Software Foundation
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If not, write
+to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This code allocates page-aligned memory by hook or by crook.
+ If mmap(2) can give us anonymous memory, we use that. If the
+ system provides valloc(3) or memalign(3), we can use them instead.
+ As a last resort, we use plain malloc, with trickery to extract a
+ page-aligned region from the actual allocation. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libiberty.h>
+
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#if HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#if HAVE_SYS_MMAN_H
+# include <sys/mman.h>
+#endif
+
+/* The system's page size. */
+static size_t pagesize;
+
+/* Test the misalignment of an address. */
+#define MISALIGNMENT(Address) \
+ (((size_t)(Address)) & (pagesize - 1))
+
+/* Configuration. */
+
+/* Shut up pedantic warnings about 'inline'. */
+#if defined __GNUC__ && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 7)
+# undef inline
+# define inline __inline__
+#endif
+
+/* For testing */
+#if FORCE_USE_MALLOC
+# undef HAVE_MMAP_ANON
+# undef HAVE_MMAP_DEV_ZERO
+# undef HAVE_VALLOC
+# undef HAVE_POSIX_VALLOC
+# undef HAVE_MEMALIGN
+#endif
+
+#define use_mmap 0
+#define use_valloc 0
+#define use_posix_valloc 0
+#define use_malloc 0
+#define need_dev_zero 0
+
+/* mmap with MAP_ANON(YMOUS) is preferred, because it doesn't require us
+ to hold a file descriptor on /dev/zero. */
+#ifdef HAVE_MMAP_ANON
+# undef use_mmap
+# define use_mmap 1
+#else
+# ifdef HAVE_MMAP_DEV_ZERO
+# undef need_dev_zero
+# define need_dev_zero 1
+# undef use_mmap
+# define use_mmap 1
+# else
+/* memalign is preferred to valloc, because valloc may call getpagesize()
+ (which may involve an expensive system call) on every use. */
+# ifdef HAVE_MEMALIGN
+# undef use_valloc
+# define use_valloc 1
+# undef valloc
+# define valloc(size) memalign(pagesize, size)
+# else
+# ifdef HAVE_VALLOC
+# undef use_valloc
+# define use_valloc 1
+# else
+# ifdef HAVE_POSIX_VALLOC
+# undef use_posix_valloc
+# define use_posix_valloc 1
+# else
+# undef use_malloc
+# define use_malloc 1
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#if need_dev_zero
+static int dev_zero_fd = -1;
+#else
+#define dev_zero_fd -1
+#endif
+
+#if use_malloc
+static size_t roundup;
+static size_t offset;
+#else
+# define roundup 0
+# define offset 0
+#endif
+
+#ifndef MAP_FAILED
+# define MAP_FAILED -1
+#endif
+#ifndef MAP_ANON
+# ifdef MAP_ANONYMOUS
+# define MAP_ANON MAP_ANONYMOUS
+# else
+# define MAP_ANON 0
+# endif
+#endif
+
+/* Sanity check */
+extern int only_one_of_the_use_macros_may_be_nonzero
+[(use_mmap + use_valloc + use_posix_valloc + use_malloc > 1) ? -1 : 1];
+
+static inline char *xv_get_core PARAMS ((size_t));
+static inline void xv_put_core PARAMS ((char *, size_t));
+
+/* Internal allocation/deallocation primitives. They give you
+ exactly as many bytes as you asked for, with no particular
+ guarantee about how it's aligned; and they expect you to hand
+ back the block just as it was returned by them. */
+static inline char *
+xv_get_core (size)
+ size_t size;
+{
+#if use_mmap
+ char *res = (char *) mmap (0, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, dev_zero_fd, 0);
+ if (res != (char *) MAP_FAILED)
+ return res;
+
+ return 0;
+#endif
+#if use_valloc
+ return (char *) valloc (size);
+#endif
+#if use_posix_valloc
+ /* POSIX.1d - had to be different... */
+ char *res;
+ int err = posix_valloc (&res, size);
+ if (err == 0)
+ return res;
+
+ errno = err;
+ return 0;
+#endif
+#if use_malloc
+ return (char *) malloc (size);
+#endif
+}
+
+static inline void
+xv_put_core (ptr, size)
+ char *ptr;
+ size_t size ATTRIBUTE_UNUSED;
+{
+#if use_mmap
+ munmap (ptr, size);
+#else
+ /* We assume all other allocation methods permit you to pass the
+ pointer they return to free directly. This is believed not to be
+ true everywhere, but we were unable to find a platform where it
+ wasn't. */
+ free (ptr);
+#endif
+}
+
+/* Adjust an allocation request before and after passing it to the
+ underlying allocator, so all higher level code sees an aligned
+ block of memory. Also traps allocation failures. */
+char *
+xvalloc (size)
+ size_t size;
+{
+ char *res;
+
+ size += roundup;
+
+ res = xv_get_core (size);
+ if (res == 0)
+ xmalloc_failed (size); /* doesn't return */
+
+ return res + offset;
+}
+
+void
+xvfree (ptr, size)
+ char *ptr;
+ size_t size;
+{
+ xv_put_core (ptr - offset, size + roundup);
+}
+
+/* Initialize internal data structures. */
+void
+xvalloc_init ()
+{
+ pagesize = getpagesize ();
+
+#if need_dev_zero
+ dev_zero_fd = open("/dev/zero", O_RDWR);
+ if (dev_zero_fd == -1)
+ abort ();
+#endif
+
+#if use_mmap
+ /* StunOS has an amazing off-by-one error for the first mmap allocation
+ after fiddling with RLIMIT_STACK. The result, as hard as it is to
+ believe, is an unaligned page allocation, which would cause us to
+ hork badly if we tried to use it. */
+ {
+ char *p = xvalloc (pagesize);
+
+ if (MISALIGNMENT (p))
+ {
+ /* How losing. Discard this one and try another. If we still
+ can't get something useful, give up. */
+
+ p = xvalloc (pagesize);
+ if (MISALIGNMENT (p))
+ abort ();
+ }
+ xvfree (p, pagesize);
+ }
+#endif
+
+#if use_malloc
+ /* We must determine how to get page-aligned memory out of this
+ system's malloc implementation. */
+ {
+ char *p = xvalloc (pagesize);
+ size_t i;
+
+ if (MISALIGNMENT (p) == 0)
+ {
+ /* This malloc page-aligns page-sized memory. We assume it does
+ so for all larger allocations as well. */
+ xvfree (p, pagesize);
+ return;
+ }
+
+ /* Determine the smallest allocation such that there is a complete
+ aligned page within it. This must happen when we allocate two
+ full pages, but not necessarily before. */
+ for (i = pagesize + sizeof(int); i <= pagesize*2; i += sizeof(int))
+ {
+ p = xvalloc (i);
+ if (p + pagesize + (pagesize - MISALIGNMENT (p)) <= p + i)
+ {
+ size_t r = i - pagesize;
+ size_t o = pagesize - MISALIGNMENT (p);
+
+ xvfree (p, i);
+ roundup = r;
+ offset = o;
+ return;
+ }
+ xvfree (p, i);
+ }
+ abort ();
+ }
+#endif
+}
More information about the Gcc-patches
mailing list