From 1c8434e33a6d5d8d3155bbb9a3c2c399634e794e Mon Sep 17 00:00:00 2001 From: George Koehler Date: Tue, 13 Nov 2018 18:05:16 -0500 Subject: [PATCH] Switch led to malloc() and realloc(). Add USEMALLOC and enable it by default. You can switch back to brk() by removing `#define USEMALLOC` in memory.c. 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. My build shows no changes in share/ack/examples (except hilo_bas.*). --- util/led/memory.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) 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;