diff --git a/util/led/memory.c b/util/led/memory.c index 4f8e6d53e..a6dad9608 100644 --- a/util/led/memory.c +++ b/util/led/memory.c @@ -21,6 +21,13 @@ static char rcsid[] = "$Id$"; * (70000 - 65536). */ +/* + * USEMALLOC tells the allocator to use malloc() and realloc(), not brk(). + * This might help systems where brk() doesn't work, or where malloc() can + * allocate outside the brk area. + */ +#define USEMALLOC + #include #include #include @@ -34,8 +41,10 @@ static char rcsid[] = "$Id$"; #include "object.h" #include "sym.h" +#ifndef USEMALLOC static void copy_down(struct memory* mem, ind_t dist); static void copy_up(struct memory* mem, ind_t dist); +#endif static void free_saved_moduls(void); struct memory mems[NMEMS]; @@ -43,6 +52,11 @@ struct memory mems[NMEMS]; bool incore = TRUE; /* TRUE while everything can be kept in core. */ ind_t core_position = (ind_t)0; /* Index of current module. */ +#ifdef USEMALLOC +static size_t modl_initial_size; +static bool frozen = FALSE; /* TRUE after freeze_core(). */ + +#else /* ifndef USEMALLOC */ #define GRANULE 64 /* power of 2 */ static char *BASE; @@ -62,6 +76,7 @@ static int sbreak(ind_t incr) BASE += incr; return 0; } +#endif /* ndef USEMALLOC */ /* * Initialize some pieces of core. We hope that this will be our last @@ -69,6 +84,53 @@ static int sbreak(ind_t incr) */ void init_core(void) { +#ifdef USEMALLOC + struct memory *failed_mem = NULL; + struct memory *mem; + bool string_area; + +#include "mach.h" + modl_initial_size = mems[ALLOMODL].mem_left; + + for (mem = mems; mem < &mems[NMEMS]; mem++) { + string_area = mem == &mems[ALLOLCHR] || mem == &mems[ALLOGCHR]; + /* String areas need at least one byte. */ + if (string_area && mem->mem_left == 0) + mem->mem_left++; + /* Don't malloc() size zero. */ + if (mem->mem_left > 0) { + mem->mem_base = malloc(mem->mem_left); + if (mem->mem_base == NULL) { + failed_mem = mem; + break; + } + } + mem->mem_full = 0; + if (string_area) { + mem->mem_left--; + mem->mem_full++; + } + } + if (failed_mem != NULL) { + incore = FALSE; /* In core strategy failed. */ + /* Undo allocations. */ + for (mem = mems; mem != failed_mem; mem++) + free(mem->mem_base); + /* Allocate only the string areas. */ + for (mem = mems; mem < &mems[NMEMS]; mem++) { + if (mem == &mems[ALLOLCHR] || mem == &mems[ALLOGCHR]) { + mem->mem_base = malloc(1); + if (mem->mem_base == NULL) + fatal("no core at all"); + mem->mem_left = 0; + mem->mem_full = 1; + } else { + mem->mem_base = NULL; + mem->mem_left = mem->mem_full = 0; + } + } + } +#else /* ifndef USEMALLOC */ register char *base; register ind_t total_size; register struct memory *mem; @@ -127,6 +189,7 @@ void init_core(void) } } } +#endif /* ndef USEMALLOC */ } /* @@ -139,6 +202,29 @@ move_up(piece, incr) register int piece; register ind_t incr; { +#ifdef USEMALLOC + size_t oldsize = mems[piece].mem_full + mems[piece].mem_left; + size_t newsize; + char *newbase; + + if (frozen) + return 0; /* Can't realloc() frozen core. */ + + /* We realloc() this piece without moving the other pieces. */ + while (incr > 0) { + newsize = oldsize + incr; + if (newsize > oldsize) { + newbase = realloc(mems[piece].mem_base, newsize); + if (newbase != NULL) { + mems[piece].mem_base = newbase; + mems[piece].mem_left += incr; + return incr; + } + } + incr -= INCRSIZE < incr ? INCRSIZE : incr; + } + return 0; +#else /* ifndef USEMALLOC */ register struct memory *mem; #ifndef NOSTATISTICS extern int statistics; @@ -158,6 +244,7 @@ move_up(piece, incr) mems[piece].mem_left += incr; return incr; +#endif /* ndef USEMALLOC */ } extern int passnumber; @@ -175,6 +262,73 @@ compact(int piece, ind_t incr, int flag) #define FREEZE 1 #define FORCED 2 { +#ifdef USEMALLOC + struct memory *mem; + size_t newsize, oldsize; + char *newbase; + + if (frozen) + return incr == 0; /* Can't realloc() frozen core. */ + /* + * We realloc() to shrink most pieces. + * We can't control how realloc() moves the pieces. + */ + for (mem = mems; mem < &mems[NMEMS]; mem++) { + if (mem == &mems[piece]) + continue; + if (flag == FREEZE && mem == &mems[ALLOMODL]) + continue; + if (mem->mem_full == 0) { + /* Don't try to realloc() to size zero. */ + free(mem->mem_base); + mem->mem_base = NULL; + mem->mem_left = 0; + } else { + newbase = realloc(mem->mem_base, mem->mem_full); + if (newbase != NULL) { + mem->mem_base = newbase; + mem->mem_left = 0; + } + } + } + /* + * After FREEZE, we must be able to grow ALLOMODL without + * moving it. The old allocator allowed ALLOMODL to grow in + * the brk area, but we can't call realloc() later, so we must + * leave some extra space in ALLOMODL now. + */ + if (flag == FREEZE) { + mem = &mems[ALLOMODL]; + oldsize = mem->mem_full + mem->mem_left; + newsize = mem->mem_full + modl_initial_size / 2; + /* Don't shrink ALLOMODL. */ + while (newsize > oldsize) { + newbase = realloc(mem->mem_base, newsize); + if (newbase != NULL) { + mem->mem_base = newbase; + mem->mem_left = newsize - mem->mem_full; + break; + } + newsize -= INCRSIZE < newsize ? INCRSIZE : newsize; + } + frozen = TRUE; /* Prevent later realloc(). */ + } + /* Now grow our piece. */ + if (incr == 0) + return TRUE; + mem = &mems[piece]; + oldsize = mem->mem_full + mem->mem_left; + newsize = oldsize + incr; + if (newsize < mem->mem_full) + return FALSE; /* The size overflowed. */ + newbase = realloc(mem->mem_base, newsize); + if (newbase == NULL) + return FALSE; + mem->mem_base = newbase; + mem->mem_left += incr; + return TRUE; + +#else /* ifndef USEMALLOC */ register ind_t gain, size; register struct memory *mem; int min = piece, max = piece; @@ -300,8 +454,10 @@ compact(int piece, ind_t incr, int flag) assert(mem->mem_base + mem->mem_full + mem->mem_left == (mem+1)->mem_base); } return gain >= incr; +#endif /* ndef USEMALLOC */ } +#ifndef USEMALLOC /* * The bytes of `mem' must be moved `dist' down in the address space. * We copy the bytes from low to high, because the tail of the new area may @@ -342,6 +498,7 @@ static void copy_up(struct memory* mem, ind_t dist) *--new = *--old; mem->mem_base = new; } +#endif /* ndef USEMALLOC */ static int alloctype = NORMAL;