Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Date: Mon, 20 Nov 2000 15:42:23 -0800 From: "Zack Weinberg" To: Kelley Cook Cc: Cygwin mailing list , GCC Bugs , GCC Patches Subject: Re: Reason for cygwin GCC 2.97 non-bootstrap found Message-ID: <20001120154222.O17712@wolery.stanford.edu> References: <200011202245 DOT eAKMjjN27680 AT plmlir3 DOT mail DOT eds DOT com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i In-Reply-To: <200011202245.eAKMjjN27680@plmlir3.mail.eds.com>; from Kelley.Cook@home.com on Mon, Nov 20, 2000 at 05:45:26PM -0500 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 AT DOT 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 -#include -#include - -#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 -# 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 -# 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 -#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 +/* Get a definition for va_list. */ +#include +#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 -/* Get a definition for va_list. */ -#include -#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 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 +#include +#include + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef HAVE_UNISTD_H +# include +# 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 +# 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 +#include +#ifdef NEED_DECLARATION_ERRNO +extern int errno; +#endif #ifdef __STDC__ #include @@ -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 +#endif + +#include + +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +# include +#endif + +#if HAVE_FCNTL_H +# include +#endif + +#if HAVE_SYS_MMAN_H +# include +#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 +} -- Want to unsubscribe from this list? Send a message to cygwin-unsubscribe AT sourceware DOT cygnus DOT com