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.*).
This commit is contained in:
George Koehler 2018-11-13 18:05:16 -05:00
parent 4fdfa3177e
commit 1c8434e33a

View file

@ -21,6 +21,13 @@ static char rcsid[] = "$Id$";
* (70000 - 65536). * (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 <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -34,8 +41,10 @@ static char rcsid[] = "$Id$";
#include "object.h" #include "object.h"
#include "sym.h" #include "sym.h"
#ifndef USEMALLOC
static void copy_down(struct memory* mem, ind_t dist); static void copy_down(struct memory* mem, ind_t dist);
static void copy_up(struct memory* mem, ind_t dist); static void copy_up(struct memory* mem, ind_t dist);
#endif
static void free_saved_moduls(void); static void free_saved_moduls(void);
struct memory mems[NMEMS]; struct memory mems[NMEMS];
@ -43,6 +52,11 @@ struct memory mems[NMEMS];
bool incore = TRUE; /* TRUE while everything can be kept in core. */ bool incore = TRUE; /* TRUE while everything can be kept in core. */
ind_t core_position = (ind_t)0; /* Index of current module. */ 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 */ #define GRANULE 64 /* power of 2 */
static char *BASE; static char *BASE;
@ -62,6 +76,7 @@ static int sbreak(ind_t incr)
BASE += incr; BASE += incr;
return 0; return 0;
} }
#endif /* ndef USEMALLOC */
/* /*
* Initialize some pieces of core. We hope that this will be our last * 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) 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 char *base;
register ind_t total_size; register ind_t total_size;
register struct memory *mem; 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 int piece;
register ind_t incr; 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; register struct memory *mem;
#ifndef NOSTATISTICS #ifndef NOSTATISTICS
extern int statistics; extern int statistics;
@ -158,6 +244,7 @@ move_up(piece, incr)
mems[piece].mem_left += incr; mems[piece].mem_left += incr;
return incr; return incr;
#endif /* ndef USEMALLOC */
} }
extern int passnumber; extern int passnumber;
@ -175,6 +262,73 @@ compact(int piece, ind_t incr, int flag)
#define FREEZE 1 #define FREEZE 1
#define FORCED 2 #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 ind_t gain, size;
register struct memory *mem; register struct memory *mem;
int min = piece, max = piece; 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); assert(mem->mem_base + mem->mem_full + mem->mem_left == (mem+1)->mem_base);
} }
return gain >= incr; return gain >= incr;
#endif /* ndef USEMALLOC */
} }
#ifndef USEMALLOC
/* /*
* The bytes of `mem' must be moved `dist' down in the address space. * 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 * 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; *--new = *--old;
mem->mem_base = new; mem->mem_base = new;
} }
#endif /* ndef USEMALLOC */
static int alloctype = NORMAL; static int alloctype = NORMAL;