diff --git a/util/led/memory.c b/util/led/memory.c index 9710ce942..c1e6c4a01 100644 --- a/util/led/memory.c +++ b/util/led/memory.c @@ -8,32 +8,16 @@ static char rcsid[] = "$Id$"; /* * Memory manager. Memory is divided into NMEMS pieces. There is a struct - * for each piece telling where it is, how many bytes are used, and how may - * are left. If a request for core doesn't fit in the left bytes, an sbrk() - * is done and pieces after the one that requested the growth are moved up. - * - * Unfortunately, we cannot use sbrk to request more memory, because its - * result cannot be trusted. More specifically, it does not work properly - * on 2.9 BSD, and probably does not work properly on 2.8 BSD and V7 either. - * The problem is that "sbrk" adds the increment to the current "break" - * WITHOUT testing the carry bit. So, if your break is at 40000, and - * you "sbrk(30000)", it will succeed, but your break will be at 4464 - * (70000 - 65536). + * for each piece telling where it is, how many bytes are used, and how many + * are left. Each piece is its own malloc() block; if a request for core + * doesn't fit in the left bytes, the piece is grown with realloc(). */ -/* - * 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 #include #include -#include #include #include "const.h" #include "debug.h" @@ -44,10 +28,6 @@ static char rcsid[] = "$Id$"; #include "write.h" #include "scan.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]; @@ -55,38 +35,15 @@ 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; -static ind_t refused; - -static int sbreak(ind_t incr) -{ - incr = (incr + (GRANULE - 1)) & ~(GRANULE - 1); - - if ((refused && refused < incr) || BASE + incr < BASE || brk(BASE + incr) == -1) - { - if (!refused || refused > incr) - refused = incr; - return -1; - } - BASE += incr; - return 0; -} -#endif /* ndef USEMALLOC */ - /* * Initialize some pieces of core. We hope that this will be our last * real allocation, meaning we've made the right choices. */ void init_core(void) { -#ifdef USEMALLOC struct memory* failed_mem = NULL; struct memory* mem; bool string_area; @@ -141,85 +98,14 @@ void init_core(void) } } } -#else /* ifndef USEMALLOC */ - char* base; - ind_t total_size; - struct memory* mem; - -#include "mach.h" -#define ALIGN 8 /* minimum alignment for pieces */ -#define AT_LEAST (ind_t)2 * ALIGN /* See comment about string areas. */ - - total_size = (ind_t)0; /* Will accumulate the sizes. */ - BASE = base = sbrk(0); /* First free. */ - if ((int)base % ALIGN) - { - base = sbrk(ALIGN - (int)base % ALIGN); - BASE = base = sbrk(0); - } - /* - * String areas are special-cased. The first byte is unused as a way to - * distinguish a name without string from a name which has the first - * string in the string area. - */ - for (mem = mems; mem < &mems[NMEMS]; mem++) - { - mem->mem_base = base; - mem->mem_full = (ind_t)0; - if (mem == &mems[ALLOLCHR] || mem == &mems[ALLOGCHR]) - { - if (mem->mem_left == 0) - { - mem->mem_left = ALIGN; - total_size += ALIGN; - base += ALIGN; - } - base += mem->mem_left; - total_size += mem->mem_left; - mem->mem_left--; - mem->mem_full++; - } - else - { - base += mem->mem_left; /* Each piece will start after prev. */ - total_size += mem->mem_left; - } - } - - if (sbreak(total_size) == -1) - { - incore = false; /* In core strategy failed. */ - if (sbreak(AT_LEAST) == -1) - fatal("no core at all"); - - base = BASE; - for (mem = mems; mem < &mems[NMEMS]; mem++) - { - mem->mem_base = base; - if (mem == &mems[ALLOLCHR] || mem == &mems[ALLOGCHR]) - { - base += ALIGN; - mem->mem_left = ALIGN - 1; - mem->mem_full = 1; - } - else - { - mem->mem_full = (ind_t)0; - mem->mem_left = 0; - } - } - } -#endif /* ndef USEMALLOC */ } /* - * Allocate an extra block of `incr' bytes and move all pieces with index - * higher than `piece' up with the size of the block. - * Move up as much as possible, if "incr" fails. + * Grow `piece' by `incr' bytes with realloc(); the other pieces stay where + * they are. Grow by as much as possible, if "incr" fails. */ static ind_t move_up(int piece, ind_t incr) { -#ifdef USEMALLOC size_t oldsize = mems[piece].mem_full + mems[piece].mem_left; size_t newsize; char* newbase; @@ -244,43 +130,18 @@ static ind_t move_up(int piece, ind_t incr) incr -= INCRSIZE < incr ? INCRSIZE : incr; } return 0; -#else /* ifndef USEMALLOC */ - struct memory* mem; -#ifndef NOSTATISTICS - extern int statistics; -#endif - - debug("move_up(%d, %d)\n", piece, (int)incr, 0, 0); - while (incr > 0 && sbreak(incr) == -1) - incr -= INCRSIZE < incr ? INCRSIZE : incr; - - if (incr == 0) - return (ind_t)0; -#ifndef NOSTATISTICS - if (statistics) - fprintf(stderr, "moving up %lx\n", (long)incr); -#endif - for (mem = &mems[NMEMS - 1]; mem > &mems[piece]; mem--) - copy_up(mem, incr); - - mems[piece].mem_left += incr; - return incr; -#endif /* ndef USEMALLOC */ } /* * This routine is called if `piece' needs `incr' bytes and the system won't - * give them. We first steal the free bytes of all lower pieces and move them - * and `piece' down. If that doesn't give us enough bytes, we steal the free - * bytes of all higher pieces and move them up. We return whether we have - * enough bytes, the first or the second time. + * give them. We shrink all other pieces to what they use, then try to grow + * `piece' again, and return whether we have enough bytes. */ static bool compact(int piece, ind_t incr, int flag) #define NORMAL 0 #define FREEZE 1 #define FORCED 2 { -#ifdef USEMALLOC struct memory* mem; size_t newsize, oldsize; char* newbase; @@ -354,210 +215,8 @@ static bool compact(int piece, ind_t incr, int flag) mem->mem_left += incr; return true; -#else /* ifndef USEMALLOC */ - ind_t gain, size; - struct memory* mem; - int min = piece, max = piece; -#define SHIFT_COUNT \ - 2 /* let pieces only contribute if their free \ -memory is more than 1/2**SHIFT_COUNT * 100 % \ -of its occupied memory \ -*/ - - debug("compact(%d, %d, %d)\n", piece, (int)incr, flag, 0); - for (mem = &mems[0]; mem < &mems[NMEMS - 1]; mem++) - { - assert(mem->mem_base + mem->mem_full + mem->mem_left == (mem + 1)->mem_base); - } - - mem = &mems[piece]; - if (flag == NORMAL) - { - /* try and gain a bit more than needed */ - gain = (mem->mem_full + incr) >> SHIFT_COUNT; - if (incr < gain) - incr = gain; - } - - /* - * First, check that moving will result in enough space - */ - if (flag != FREEZE) - { - gain = mem->mem_left; - for (mem = &mems[piece - 1]; mem >= &mems[0]; mem--) - { - /* - * Don't give it all away! - * If this does not give us enough, bad luck - */ - if (flag == FORCED) - size = 0; - else - { - size = mem->mem_full >> SHIFT_COUNT; - if (size == 0) - size = mem->mem_left >> 1; - } - if (mem->mem_left >= size) - gain += (mem->mem_left - size) & ~(ALIGN - 1); - if (gain >= incr) - { - min = mem - &mems[0]; - break; - } - } - if (min == piece) - for (mem = &mems[piece + 1]; mem <= &mems[NMEMS - 1]; mem++) - { - /* - * Don't give it all away! - * If this does not give us enough, bad luck - */ - if (flag == FORCED) - size = 0; - else - { - size = mem->mem_full >> SHIFT_COUNT; - if (size == 0) - size = mem->mem_left >> 1; - } - if (mem->mem_left >= size) - gain += (mem->mem_left - size) & ~(ALIGN - 1); - if (gain >= incr) - { - max = mem - &mems[0]; - break; - } - } - if (min == piece) - { - min = 0; - if (max == piece) - max = 0; - } - if (gain < incr) - return 0; - } - else - { - min = 0; - max = NMEMS - 1; - } - - gain = 0; - for (mem = &mems[min]; mem != &mems[piece]; mem++) - { - /* Here memory is inserted before a piece. */ - assert(passnumber == FIRST || gain == (ind_t)0); - if (gain) - copy_down(mem, gain); - if (flag == FREEZE || gain < incr) - { - if (flag != NORMAL) - size = 0; - else - { - size = mem->mem_full >> SHIFT_COUNT; - if (size == 0) - size = mem->mem_left >> 1; - } - if (mem->mem_left >= size) - { - size = (mem->mem_left - size) & ~(ALIGN - 1); - gain += size; - mem->mem_left -= size; - } - } - } - /* - * Now mems[piece]: - */ - if (gain) - copy_down(mem, gain); - gain += mem->mem_left; - mem->mem_left = 0; - - if (gain < incr) - { - ind_t up = (ind_t)0; - - for (mem = &mems[max]; mem > &mems[piece]; mem--) - { - /* Here memory is appended after a piece. */ - if (flag == FREEZE || gain + up < incr) - { - if (flag != NORMAL) - size = 0; - else - { - size = mem->mem_full >> SHIFT_COUNT; - if (size == 0) - size = mem->mem_left >> 1; - } - if (mem->mem_left >= size) - { - size = (mem->mem_left - size) & ~(ALIGN - 1); - up += size; - mem->mem_left -= size; - } - } - if (up) - copy_up(mem, up); - } - gain += up; - } - mems[piece].mem_left += gain; - assert(flag == FREEZE || gain >= incr); - for (mem = &mems[0]; mem < &mems[NMEMS - 1]; mem++) - { - 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 - * overlap with the old area, but we do not want to overwrite them before they - * are copied. - */ -static void copy_down(struct memory* mem, ind_t dist) -{ - char* old; - char* new; - ind_t size; - - size = mem->mem_full; - old = mem->mem_base; - new = old - dist; - mem->mem_base = new; - while (size--) - *new ++ = *old++; } -/* - * The bytes of `mem' must be moved `dist' up in the address space. - * We copy the bytes from high to low, because the tail of the new area may - * overlap with the old area, but we do not want to overwrite them before they - * are copied. - */ -static void copy_up(struct memory* mem, ind_t dist) -{ - char* old; - char* new; - ind_t size; - - size = mem->mem_full; - old = mem->mem_base + size; - new = old + dist; - while (size--) - *--new = *--old; - mem->mem_base = new; -} -#endif /* ndef USEMALLOC */ static int alloctype = NORMAL; diff --git a/util/led/memory.h b/util/led/memory.h index fa5476bee..6c05d6c22 100644 --- a/util/led/memory.h +++ b/util/led/memory.h @@ -44,7 +44,12 @@ struct outname; #define address(piece, offset) (mems[(piece)].mem_base + (offset)) #define modulptr(offset) (mems[ALLOMODL].mem_base + core_position + (offset)) -#define int_align(sz) (((sz) + (sizeof(int) - 1)) & ~(sizeof(int) - 1)) +/* + * Round a size or offset in a piece up so that whatever follows it is + * aligned for any type: modules in ALLOMODL hold structs with pointers and + * longs (struct outname, struct ar_hdr, ind_t), 8 bytes on a 64-bit host. + */ +#define int_align(sz) (((sz) + (_Alignof(max_align_t) - 1)) & ~(_Alignof(max_align_t) - 1)) extern bool incore; extern ind_t core_position; diff --git a/util/led/save.c b/util/led/save.c index 4bcc03ae3..8f1b72275 100644 --- a/util/led/save.c +++ b/util/led/save.c @@ -37,7 +37,7 @@ void savemagic(void) if ((p = core_alloc(ALLOMODL, (long)sizeof(int))) != (char*)0) { *(unsigned short*)p = AALMAG; - core_position += sizeof(int); + core_position += int_align(sizeof(int)); } } diff --git a/util/led/scan.c b/util/led/scan.c index ffd7a392e..02fe90090 100644 --- a/util/led/scan.c +++ b/util/led/scan.c @@ -29,7 +29,7 @@ static char rcsid[] = "$Id$"; #define READ 0 -#define IND_EMIT(x) (IND_CHAR(x) + (ind_t)align((x).oh_nchar)) +#define IND_EMIT(x) int_align(IND_CHAR(x) + (x).oh_nchar) #define IND_RELO(x) (IND_EMIT(x) + (x).oh_nsect * sizeof(ind_t)) #ifdef SYMDBUG #define IND_DBUG(x) (IND_RELO(x) + sizeof(ind_t)) @@ -43,7 +43,6 @@ int passnumber; /* Current pass */ long objectsize; #endif /* SYMDBUG */ -static size_t align(size_t size); static char* modulbase; static size_t modulsize(struct outhead* head); static void can_modul(void); @@ -113,8 +112,8 @@ int getfile(char* filename) } else if (incore) { - modulbase += sizeof(int); - core_position += sizeof(int); + modulbase += int_align(sizeof(int)); + core_position += int_align(sizeof(int)); } return ARCHIVE; default: @@ -223,16 +222,12 @@ static bool direct_alloc(struct outhead* head) unsigned short nsect = head->oh_nsect; size_t size, rest; -#ifdef SYMDBUG - rest = nsect * sizeof(ind_t) + sizeof(ind_t) + sizeof(ind_t); -#else /* SYMDBUG */ - rest = nsect * sizeof(ind_t) + sizeof(ind_t); -#endif /* SYMDBUG */ /* - * We already allocated space for the header, we now need - * the section, name an string table. + * We already allocated space for the header (IND_SECT bytes, alloc() + * rounds), we now need the section, name and string table. */ - size = modulsize(head) - sizeof(struct outhead) - rest; + size = IND_EMIT(*head) - IND_SECT(*head); + rest = modulsize(head) - IND_EMIT(*head); if (hard_alloc(ALLOMODL, size) == BADOFF) fatal("no space for module"); rd_sect(sects = ((struct outsect*)modulptr(sectindex)), nsect); @@ -444,11 +439,7 @@ static void read_modul(void) nameindex = IND_NAME(*head); nchar = head->oh_nchar; charindex = IND_CHAR(*head); -#ifdef SYMDBUG - size = modulsize(head) - (nsect * sizeof(ind_t) + 2 * sizeof(ind_t)); -#else /* SYMDBUG */ - size = modulsize(head) - (nsect * sizeof(ind_t) + sizeof(ind_t)); -#endif /* SYMDBUG */ + size = IND_EMIT(*head) - IND_SECT(*head); if (hard_alloc(ALLOMODL, size) == BADOFF) fatal("no space for module"); @@ -470,15 +461,6 @@ static void read_modul(void) rd_string(chars, nchar); } -/* - * Align `size' to a multiple of the size of a double. - * This is assumed to be a power of 2. - */ -static size_t align(size_t size) -{ - return (size + (sizeof(double) - 1)) & ~(sizeof(double) - 1); -} - /* * Compute how many DIRECT bytes must be allocated for a module of which the * header is pointed to by `head': @@ -494,16 +476,11 @@ static size_t align(size_t size) */ static size_t modulsize(struct outhead* head) { - return sizeof(struct outhead) + /* 0 */ - head->oh_nsect * sizeof(struct outsect) + /* 1 */ - head->oh_nname * sizeof(struct outname) + /* 2 */ - align(head->oh_nchar) + /* 3 */ - head->oh_nsect * sizeof(ind_t) + /* 4 */ + /* Each part starts aligned (IND_SECT, IND_NAME, IND_EMIT). */ #ifdef SYMDBUG - sizeof(ind_t) + /* 5 */ - sizeof(ind_t); /* 6 */ + return int_align(IND_DBUG(*head) + sizeof(ind_t)); #else /* SYMDBUG */ - sizeof(ind_t); /* 5 */ + return int_align(IND_RELO(*head) + sizeof(ind_t)); #endif /* SYMDBUG */ } diff --git a/util/led/scan.h b/util/led/scan.h index acb87c594..d3f75e5f3 100644 --- a/util/led/scan.h +++ b/util/led/scan.h @@ -14,8 +14,8 @@ */ #define IND_HEAD ((ind_t)0) -#define IND_SECT(x) (IND_HEAD + sizeof(struct outhead)) -#define IND_NAME(x) (IND_SECT(x) + (x).oh_nsect * sizeof(struct outsect)) +#define IND_SECT(x) int_align(IND_HEAD + sizeof(struct outhead)) +#define IND_NAME(x) int_align(IND_SECT(x) + (x).oh_nsect * sizeof(struct outsect)) #define IND_CHAR(x) (IND_NAME(x) + (x).oh_nname * sizeof(struct outname)) #ifdef SYMDBUG #define OFF_DBUG(x) (OFF_CHAR(x) + (x).oh_nchar)