From a200a2fb53309c7c05421dc9c0c270b5227f5d68 Mon Sep 17 00:00:00 2001 From: David Given Date: Thu, 11 Aug 2016 00:30:32 +0200 Subject: [PATCH] Replaced the funky and hard-to-compile ACK malloc with a much smaller and simpler one stolen from K&R. libc builds now. --- lang/cem/libcc.ansi/build.lua | 23 +- lang/cem/libcc.ansi/headers/build.lua | 26 ++ lang/cem/libcc.ansi/malloc/malloc.c | 151 +++++++ lang/cem/libcc.ansi/malloc/malloc.h | 25 ++ lang/cem/libcc.ansi/malloc/realloc.c | 41 ++ lang/cem/libcc.ansi/stdlib/malloc/.distr | 13 - lang/cem/libcc.ansi/stdlib/malloc/Makefile | 20 - lang/cem/libcc.ansi/stdlib/malloc/READ_ME | 27 -- lang/cem/libcc.ansi/stdlib/malloc/add_file | 15 - lang/cem/libcc.ansi/stdlib/malloc/check.c | 303 -------------- lang/cem/libcc.ansi/stdlib/malloc/check.h | 21 - lang/cem/libcc.ansi/stdlib/malloc/global.c | 11 - lang/cem/libcc.ansi/stdlib/malloc/impl.h | 84 ---- lang/cem/libcc.ansi/stdlib/malloc/log.c | 129 ------ lang/cem/libcc.ansi/stdlib/malloc/log.h | 26 -- lang/cem/libcc.ansi/stdlib/malloc/mal.c | 385 ------------------ lang/cem/libcc.ansi/stdlib/malloc/param.h | 56 --- lang/cem/libcc.ansi/stdlib/malloc/phys.c | 96 ----- lang/cem/libcc.ansi/stdlib/malloc/phys.h | 76 ---- lang/cem/libcc.ansi/stdlib/malloc/size_type.h | 8 - 20 files changed, 248 insertions(+), 1288 deletions(-) create mode 100644 lang/cem/libcc.ansi/headers/build.lua create mode 100644 lang/cem/libcc.ansi/malloc/malloc.c create mode 100644 lang/cem/libcc.ansi/malloc/malloc.h create mode 100644 lang/cem/libcc.ansi/malloc/realloc.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/.distr delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/Makefile delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/READ_ME delete mode 100755 lang/cem/libcc.ansi/stdlib/malloc/add_file delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/check.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/check.h delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/global.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/impl.h delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/log.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/log.h delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/mal.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/param.h delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/phys.c delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/phys.h delete mode 100644 lang/cem/libcc.ansi/stdlib/malloc/size_type.h diff --git a/lang/cem/libcc.ansi/build.lua b/lang/cem/libcc.ansi/build.lua index ebc948871..60b72b0c5 100644 --- a/lang/cem/libcc.ansi/build.lua +++ b/lang/cem/libcc.ansi/build.lua @@ -1,19 +1,4 @@ -local headers = {} - -local function addheader(dir, list) - for _, f in ipairs(list) do - local b = basename(f) - headers[dir..b] = f - end -end - -addheader("", filenamesof("./headers/*.h")) -addheader("sys/", filenamesof("./headers/sys/*.h")) - -acklibrary { - name = "headers", - hdrs = headers -} +include("plat/build.lua") tabgen { name = "ctype_tab", @@ -49,14 +34,15 @@ for _, plat in ipairs(vars.plats) do "+ctype_files", "+ctype_tab", "./ctype/*.c", - "./assert/*.c", "./errno/*.c", "./locale/*.c", + "./malloc/*.c", "./math/*.c", "./misc/environ.c", -- don't build everything here as it's all obsolete "./setjmp/*.c", "./setjmp/*.e", "./signal/*.c", + "./assert/*.c", "./stdio/*.c", "./stdlib/*.c", "./string/*.c", @@ -65,7 +51,7 @@ for _, plat in ipairs(vars.plats) do }, hdrs = {}, -- must be empty deps = { - "+headers", + "lang/cem/libcc.ansi/headers+headers", "plat/"..plat.."+headers", }, vars = { plat = plat } @@ -83,6 +69,7 @@ for _, plat in ipairs(vars.plats) do installable { name = "pkg_"..plat, map = { + "lang/cem/libcc.ansi/headers+pkg", ["$(PLATIND)/"..plat.."/c-ansi.o"] = "+crt_"..plat, ["$(PLATIND)/"..plat.."/libc.a"] = "+lib_"..plat, } diff --git a/lang/cem/libcc.ansi/headers/build.lua b/lang/cem/libcc.ansi/headers/build.lua new file mode 100644 index 000000000..601d383ec --- /dev/null +++ b/lang/cem/libcc.ansi/headers/build.lua @@ -0,0 +1,26 @@ +include("plat/build.lua") + +local headers = {} +local installmap = {} + +local function addheader(dir, list) + for _, f in ipairs(list) do + local b = basename(f) + headers[dir..b] = f + installmap[concatpath("$(PLATIND)/include/ansi/", dir, b)] = f + end +end + +addheader("", filenamesof("./*.h")) +addheader("sys/", filenamesof("./sys/*.h")) + +acklibrary { + name = "headers", + hdrs = headers +} + +installable { + name = "pkg", + map = installmap +} + diff --git a/lang/cem/libcc.ansi/malloc/malloc.c b/lang/cem/libcc.ansi/malloc/malloc.c new file mode 100644 index 000000000..7eaaacaba --- /dev/null +++ b/lang/cem/libcc.ansi/malloc/malloc.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include "malloc.h" + +block_t __mem_root = {&__mem_root, 0}; +block_t* __mem_freelist = &__mem_root; + +/* Pulls more memory from the system. */ + +static block_t* brkmore(size_t nb) +{ + uintptr_t bytes; + block_t* p; + + if (nb < BRKSIZE) + nb = BRKSIZE; + bytes = nb * sizeof(block_t); + + /* Danger, will robinson! sbrk's parameter is *signed*... but malloc() takes a + * size_t. */ + + if (bytes > INTPTR_MAX) + return NULL; + + p = sbrk(bytes); + if (p == (block_t*)-1) + return NULL; + + /* Add it to the free list by pretending it's a used block and freeing it. */ + + p->size = nb; + free(p + 1); + return __mem_freelist; +} + +void* malloc(size_t size) +{ + block_t* p; + block_t* prev; + size_t nblocks; + + /* Add on space for the header; make sure we allocate a round number + * of blocks; avoid overflow. */ + nblocks = BLOCKCOUNT(size); + if (nblocks < size) + return NULL; + nblocks /= sizeof(block_t); + + prev = __mem_freelist; + p = prev->next; + for (;;) + { + if (p->size == nblocks) + { + /* We found a hole of exactly the right size. Unlink and return it. + * The size field is already set. */ + prev->next = p->next; + __mem_freelist = prev; + return (void*) (p+1); + } + else if (p->size > nblocks) + { + /* We found a hole bigger than we need. We shrink the hole and return + * what's left. */ + p->size -= nblocks; + p += p->size; /* p now points at our new block */ + p->size = nblocks; + __mem_freelist = prev; + return (void*) (p+1); + } + + if (p == __mem_freelist) + { + /* Uh-oh --- we've gone right round the ring and haven't found + * anything. Get more memory from the system and keep going. */ + p = brkmore(nblocks); + if (!p) + return NULL; + } + + prev = p; + p = p->next; + } +} + +void free(void *ptr) +{ + block_t* h = BLOCKOF(ptr); + block_t* p; + + if (!ptr) + return; + + /* __mem_freelist points into an ordered ring of free blocks. First, + * we run around the ring until we find the last block before this one. + */ + + p = __mem_freelist; + for (;;) + { + /* Is h between p and the block after p? If so, h needs to be inserted + * after p, so stop here. */ + if ((p < h) && (h < p->next)) + break; + + /* Is p the last block before the end of the address space? */ + if (p >= p->next) + { + /* Is h after p? (That is, will it become the new last block?) */ + if (p < h) + break; + + /* Is h going to become the new *first* block? */ + if (h < p->next) + break; + } + + p = p->next; + } + + /* If we can, merge the next block onto the end of h. */ + + if ((h + h->size) == p->next) + { + h->size += p->next->size; + h->next = p->next->next; + } + else + { + /* Otherwise, insert h before p->next. */ + h->next = p->next; + } + + /* Now try to merge h onto the end of p. */ + + if ((p + p->size) == h) + { + p->size += h->size; + p->next = h->next; + } + else + { + /* Okay, we couldn't do the merge. Fix up the linked list. */ + p->next = h; + } + + /* ...and update the ring pointer. */ + __mem_freelist = p; +} + diff --git a/lang/cem/libcc.ansi/malloc/malloc.h b/lang/cem/libcc.ansi/malloc/malloc.h new file mode 100644 index 000000000..d70e92ae0 --- /dev/null +++ b/lang/cem/libcc.ansi/malloc/malloc.h @@ -0,0 +1,25 @@ +/* This is an ANSI C version of the classic K&R memory allocator, with + * some improvements stolen from the Fuzix libc. + */ + +#ifndef MALLOC_H +#define MALLOC_H + +typedef struct block_s { + struct block_s* next; + size_t size; /* in sizeof(block_t) units */ +} block_t; + +extern block_t __mem_root; +extern block_t* __mem_first_free; + +#define BLOCKOF(p) (((block_t*)(p)) - 1) + +/* Smallest amount to allocate from brk */ +#define BRKSIZE (512 / sizeof(block_t)) + +#define BLOCKCOUNT(bytes) \ + (bytes + sizeof(block_t) + sizeof(block_t) - 1) + +#endif + diff --git a/lang/cem/libcc.ansi/malloc/realloc.c b/lang/cem/libcc.ansi/malloc/realloc.c new file mode 100644 index 000000000..7e6dfbb70 --- /dev/null +++ b/lang/cem/libcc.ansi/malloc/realloc.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include "malloc.h" + +void* realloc(void *ptr, size_t size) +{ + block_t* h; + size_t nblocks; + void* newptr; + + if (size == 0) + { + free(ptr); + return NULL; + } + + if (!ptr) + return malloc(size); + + h = BLOCKOF(ptr); + + nblocks = BLOCKCOUNT(size); + /* Overflow check. */ + if (nblocks < size) + return NULL; + + /* Shrinking the block? Don't bother doing anything (it's never worth it). */ + if (nblocks <= h->size) + return ptr; + + /* Allocate and copy. */ + + newptr = malloc(size); + if (!newptr) + return NULL; + memcpy(newptr, ptr, h->size * sizeof(block_t)); + free(ptr); + return newptr; +} diff --git a/lang/cem/libcc.ansi/stdlib/malloc/.distr b/lang/cem/libcc.ansi/stdlib/malloc/.distr deleted file mode 100644 index e23a0ee82..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/.distr +++ /dev/null @@ -1,13 +0,0 @@ -READ_ME -add_file -check.c -check.h -global.c -impl.h -log.c -log.h -mal.c -param.h -phys.c -phys.h -size_type.h diff --git a/lang/cem/libcc.ansi/stdlib/malloc/Makefile b/lang/cem/libcc.ansi/stdlib/malloc/Makefile deleted file mode 100644 index 11cf36765..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -DIR = . -MALLOC_C = $(DIR)/malloc.c -MALLOC_O = $(DIR)/malloc.o - -MALLOCSRC = READ_ME size_type.h param.h impl.h check.h log.h phys.h \ - mal.c log.c phys.c check.c - -$(MALLOC_C): $(MALLOCSRC) Makefile add_file - rm -f $(MALLOC_C) - for i in $(MALLOCSRC) ; do add_file $$i >> $(MALLOC_C) ; done - rm -f $(MALLOC_O) - -pr: - @pr Makefile add_file $(MALLOCSRC) - -opr: - make pr | opr - -clean: - rm -f *.o malloc.c diff --git a/lang/cem/libcc.ansi/stdlib/malloc/READ_ME b/lang/cem/libcc.ansi/stdlib/malloc/READ_ME deleted file mode 100644 index 2f0bd6f84..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/READ_ME +++ /dev/null @@ -1,27 +0,0 @@ -/* - PROGRAM - malloc(), free(), realloc() - AUTHOR - Dick Grune, Free University, Amsterdam - Modified by Ceriel Jacobs, Free University, Amsterdam, - to make it faster - VERSION - $Id$ - DESCRIPTION - This is an independent rewrite of the malloc/free package; it is - fast and efficient. Free blocks are kept in doubly linked lists, - list N holding blocks with sizes between 2**N and 2**(N+1)-1. - Consequently neither malloc nor free have to do any searching: - the cost of a call of malloc() (or free()) is constant, however - many blocks you have got. - - If you switch on the NON_STANDARD macro (see param.h) every block - costs 2 pointers overhead (otherwise it's 4). -*/ -/* - There is an organisational problem here: during devellopment - I want the package divided into modules, which implies external - names for the communication. The only external names I want in - the finished product are malloc, realloc and free. This requires - some hanky-panky. -*/ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/add_file b/lang/cem/libcc.ansi/stdlib/malloc/add_file deleted file mode 100755 index 58585bf05..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/add_file +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -echo "" -echo "/**********************************************************/" -echo "/* This was file $1 */" -echo "/**********************************************************/" -echo "" - -cat $1 | -sed ' - /#include[ ].*"/d - s/^public/private/ - s/^publicdata/static/ -' -echo '' diff --git a/lang/cem/libcc.ansi/stdlib/malloc/check.c b/lang/cem/libcc.ansi/stdlib/malloc/check.c deleted file mode 100644 index a0bfab331..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/check.c +++ /dev/null @@ -1,303 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#include - -#ifdef CHECK /* otherwise this whole file is skipped */ - -/* ??? check these later */ -private acquire_malout(void), check_ml_last(const char *s); -private dump_all_mallinks(void), dump_free_list(int i); -private dump_mallink(const char *s, mallink *ml), print_loop(mallink *ml); -private working_on(mallink *ml); -private size_type checksum(mallink *ml); -static FILE *malout; - -private mallink *free_list_entry(int i); - -#define for_free_list(i,p) \ - for (p = free_list_entry(i); p; p = log_next_of(p)) - -#define for_all_mallinks(ml) /* backwards! */ \ - for (ml = ml_last; ml; \ - ml = first_mallink(ml) ? MAL_NULL : phys_prev_of(ml)) - -/* Maldump */ - -static int pr_cnt = 0; - -maldump(int n) { - /* Dump pertinent info in pseudo-readable format; - abort afterwards if n != 0. - */ - static int dumping = 0; - int i; - - if (dumping) - return; - dumping++; - acquire_malout(); - fprintf(malout, - ">>>>>>>>>>>>>>>> DUMP OF ALL MALLINKS <<<<<<<<<<<<<<<<"); - fprintf(malout, " ml_last = %p\n", ml_last); - if (++pr_cnt == 100) pr_cnt = 0; - dump_all_mallinks(); - fprintf(malout, - ">>>>>>>>>>>>>>>> DUMP OF FREE_LISTS <<<<<<<<<<<<<<<<\n"); - if (++pr_cnt == 100) pr_cnt = 0; - for (i = 0; i < MAX_FLIST; i++) - dump_free_list(i); - fprintf(malout, - ">>>>>>>>>>>>>>>> END OF DUMP <<<<<<<<<<<<<<<<\n"); - fclose(malout); - dumping--; - if (n) - abort(); -} - -private -acquire_malout(void) { - static char buf[BUFSIZ]; - - if (!malout) { - malout = freopen("mal.out", "w", stderr); - setbuf(malout, buf); - } -} - -private -dump_all_mallinks(void) { - mallink *ml; - - for_all_mallinks (ml) { - if (print_loop(ml)) - return; - dump_mallink((char *)0, ml); - } -} - -private -dump_free_list(int i) { - mallink *ml = free_list_entry(i); - - if (!ml) - return; - fprintf(malout, "%2d: ", i); - for_free_list(i, ml) { - if (print_loop(ml)) - return; - fprintf(malout, "%p ", ml); - } - fprintf(malout, "<\n"); -} - -private int -print_loop(mallink *ml) { - if (print_of(ml) == pr_cnt) { - fprintf(malout, "... PRINT LOOP\n"); - return 1; - } - set_print(ml, pr_cnt); - return 0; -} - -private -dump_mallink(const char *s, mallink *ml) { - acquire_malout(); - if (s) - fprintf(malout, "%s: ", s); - fprintf(malout, "@: %p;", ml); - if (ml && checksum_of(ml) != checksum(ml)) - fprintf(malout, ">>>> CORRUPTED <<<<"); - if (!ml) { - fprintf(malout, "\n"); - return; - } - if (free_of(ml)) { - fprintf(malout, " l_p: %p;", _log_prev_of(ml)); - fprintf(malout, " l_n: %p;", _log_next_of(ml)); - } - fprintf(malout, " p_s: %p;", prev_size_of(ml)); - fprintf(malout, " t_s: %p;", _this_size_of(ml)); - fprintf(malout, " sz: %lu;", (unsigned long) size_of(ml)); - fprintf(malout, " fr: %d;", free_of(ml)); - fprintf(malout, "\n"); -} - -/* Check_mallinks() checks the total data structure as accessible - through free_list[] and ml_last. All check_sums should be OK, - except those held in the small array off_colour. This is a - trick to allow to continue checking even when a few mallinks - are temporarily out of order. - Check_mallinks() tests for a lot of internal consistency. -*/ - -/* Some arbitrary constants */ -#define IN_ML_LAST 93 -#define IN_FREE_LIST 57 /* and in ml_last */ -#define CLEAR 21 - -#define VRIJ 1 -#define BEZET 2 - -private -check_mallinks(const char *s) { - mallink *ml; - size_type size; - int i; - char stat; - - check_ml_last(s); - stat = BEZET; - for_all_mallinks(ml) { - if (checksum_of(ml) != checksum(ml)) - Error("mallink info at %p corrupted", s, ml); - if (working_on(ml)) { - stat = BEZET; - continue; - } - if ( !last_mallink(ml) && - phys_prev_of(phys_next_of(ml)) != ml - ) - Error("upward chain bad at %p", s, ml); - if ( !first_mallink(ml) && - phys_next_of(phys_prev_of(ml)) != ml - ) - Error("downward chain bad at %p", s, ml); - if (free_of(ml)) { - if (stat == VRIJ) - Error("free mallink at %p follows free mallink", - s, ml); - stat = VRIJ; - } - else - stat = BEZET; - set_mark(ml, IN_ML_LAST); - } - - for (i = 0, size = MIN_SIZE; i < MAX_FLIST; i++, size *= 2) { - for_free_list(i, ml) { - if (working_on(ml)) - continue; - if (!free_of(ml)) - Error("occupied mallink %p occurs in free_list", s, ml); - switch (mark_of(ml)) { - case IN_ML_LAST: - set_mark(ml, IN_FREE_LIST); - break; - case IN_FREE_LIST: - Error("mallink %p occurs in 2 free_lists", - s, ml); - default: - Error("unknown mallink %p in free_list", - s, ml); - } - if (size_of(ml) < size) - Error("size of mallink %p too small", s, ml); - if (size_of(ml) >= 2*size) - Error("size of mallink %p too large", s, ml); - } - } - for_all_mallinks (ml) { - if (working_on(ml)) - continue; - if (free_of(ml) && mark_of(ml) != IN_FREE_LIST) - Error("free mallink %p is in no free_list", s, ml); - set_mark(ml, CLEAR); - } -} - -private -check_ml_last(const char *s) { - if (ml_last && _this_size_of(ml_last) == 0) - Error("size of ml_last == 0, at %p", s, ml_last); -} - -private size_type -checksum(mallink *ml) { - size_type sum = 0; - - if (free_of(ml)) { - sum += (size_type)_log_prev_of(ml); - sum += (size_type)_log_next_of(ml); - } - sum += (size_type)prev_size_of(ml); - sum += (size_type)_this_size_of(ml); - return sum; -} - -private -calc_checksum(mallink *ml) { - set_checksum(ml, checksum(ml)); -} - -#define N_COLOUR 10 -static mallink *off_colour[N_COLOUR]; - -private -started_working_on(mallink *ml) { - int i; - - for (i = 0; i < N_COLOUR; i++) - if (off_colour[i] == MAL_NULL) { - off_colour[i] = ml; - return; - } - Error("out of off_colour array at %p", "started_working_on", ml); -} - -private -stopped_working_on(mallink *ml) { - int i; - - for (i = 0; i < N_COLOUR; i++) - if (off_colour[i] == ml) { - off_colour[i] = MAL_NULL; - return; - } - Error("stopped working on mallink %p", "stopped_working_on", ml); -} - -private int -working_on(mallink *ml) { - int i; - - for (i = 0; i < N_COLOUR; i++) - if (off_colour[i] == ml) - return 1; - return 0; -} - -private -check_work_empty(const char *s) { - int i; - int cnt = 0; - - for (i = 0; i < N_COLOUR; i++) - if (off_colour[i] != MAL_NULL) - cnt++; - if (cnt != 0) - Error("off_colour not empty", s, MAL_NULL); -} - -private int -Error(const char *fmt, const char *s, mallink *ml) { - static int already_called = 0; - - if (already_called++) return 0; - setbuf(stdout, (char *) 0); - printf("%s: ", s); - printf(fmt, (long)ml); - printf("\n"); - acquire_malout(); - fprintf(malout, "%s: ", s); - fprintf(malout, fmt, (long)ml); - fprintf(malout, "\n"); - fflush(stdout); - maldump(1); - return 0; /* to satisfy lint */ -} - -#endif /* CHECK */ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/check.h b/lang/cem/libcc.ansi/stdlib/malloc/check.h deleted file mode 100644 index bc6aafc4f..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/check.h +++ /dev/null @@ -1,21 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#ifdef CHECK - -public check_mallinks(const char *s), calc_checksum(mallink *ml); -public check_work_empty(const char *s); -public started_working_on(mallink *ml), stopped_working_on(mallink *ml); - -#else /* ifndef CHECK */ - -#define maldump(n) abort() -#define check_mallinks(s) 0 -#define calc_checksum(ml) 0 -#define started_working_on(ml) 0 -#define stopped_working_on(ml) 0 -#define check_work_empty(s) 0 - -#endif /* CHECK */ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/global.c b/lang/cem/libcc.ansi/stdlib/malloc/global.c deleted file mode 100644 index 49cb459c0..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/global.c +++ /dev/null @@ -1,11 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#include "param.h" -#include "impl.h" - -/* The only global data item: -*/ -mallink *ml_last; /* link to the world */ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/impl.h b/lang/cem/libcc.ansi/stdlib/malloc/impl.h deleted file mode 100644 index bd454037c..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/impl.h +++ /dev/null @@ -1,84 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* This file essentially describes how the mallink info block - is implemented. -*/ - -#define MIN_SIZE (1<>= 1; - mlp++; - } - while (n >= MIN_SIZE); - - ml1 = *--mlp; - set_log_prev(ml, MAL_NULL); - set_log_next(ml, ml1); - calc_checksum(ml); - if (ml1) { - /* link backwards - */ - set_log_prev(ml1, ml); - calc_checksum(ml1); - } - *mlp = ml; -} - -public -unlink_free_chunk(register mallink *ml) -{ - /* Unlinks a free chunk from (the middle of) the - logical chain. - */ - register mallink *next = log_next_of(ml); - register mallink *prev = log_prev_of(ml); - - if (!prev) { - /* it is the first in the chain */ - register mallink **mlp = &free_list[-1]; - register size_type n = size_of(ml); - - assert(n < (1L << LOG_MAX_SIZE)); - do { - n >>= 1; - mlp++; - } - while (n >= MIN_SIZE); - *mlp = next; - } - else { - set_log_next(prev, next); - calc_checksum(prev); - } - if (next) { - set_log_prev(next, prev); - calc_checksum(next); - } -} - -public mallink * -search_free_list(int class, size_t n) -{ - /* Searches the free_list[class] for a chunk of at least size n; - since it is searching a slightly undersized list, - such a block may not be there. - */ - register mallink *ml; - - for (ml = free_list[class]; ml; ml = log_next_of(ml)) - if (size_of(ml) >= n) - return ml; - return MAL_NULL; /* nothing found */ -} - -public mallink * -first_present(int class) -{ - /* Find the index i in free_list[] such that: - i >= class && free_list[i] != MAL_NULL. - Return MAL_NULL if no such i exists; - Otherwise, return the first block of this list, after - unlinking it. - */ - register mallink **mlp, *ml; - - for (mlp = &free_list[class]; mlp < &free_list[MAX_FLIST]; mlp++) { - if ((ml = *mlp) != MAL_NULL) { - - *mlp = log_next_of(ml); /* may be MAL_NULL */ - if (*mlp) { - /* unhook backward link - */ - set_log_prev(*mlp, MAL_NULL); - calc_checksum(*mlp); - } - return ml; - } - } - return MAL_NULL; -} - -#ifdef CHECK -public mallink * -free_list_entry(int i) { - /* To allow maldump.c access to log.c's private data. - */ - return free_list[i]; -} -#endif /* CHECK */ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/log.h b/lang/cem/libcc.ansi/stdlib/malloc/log.h deleted file mode 100644 index f2ba3c947..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/log.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* Algorithms to manipulate the doubly-linked lists of free - chunks. -*/ - -public link_free_chunk(mallink *ml), unlink_free_chunk(mallink *ml); -public mallink *first_present(int class); -public mallink *search_free_list(int class, size_t n); - -#ifdef STORE -#define in_store(ml) ((size_type)_phys_prev_of(ml) & STORE_BIT) -#define set_store(ml, e) \ - (_phys_prev_of(ml) = (mallink *) \ - ((e) ? (size_type) _phys_prev_of(ml) | STORE_BIT : \ - (size_type) _phys_prev_of(ml) & ~STORE_BIT)) -#endif -#define set_log_prev(ml,e) (_log_prev_of(ml) = (e)) -#define log_prev_of(ml) (mallink *) (_log_prev_of(ml)) - -#define set_log_next(ml,e) (_log_next_of(ml) = (e)) -#define log_next_of(ml) (mallink *) (_log_next_of(ml)) - diff --git a/lang/cem/libcc.ansi/stdlib/malloc/mal.c b/lang/cem/libcc.ansi/stdlib/malloc/mal.c deleted file mode 100644 index d523c9ad1..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/mal.c +++ /dev/null @@ -1,385 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#include -#include -#include "param.h" -#include "impl.h" -#include "check.h" -#include "log.h" -#include "phys.h" - -/* Malloc space is traversed by N doubly-linked lists of chunks, each - containing a couple of house-keeping data addressed as a - 'mallink' and a piece of useful space, called the block. - The N lists are accessed through their starting pointers in - free_list[]. Free_list[n] points to a list of chunks between - 2**(n+LOG_MIN_SIZE) and 2**(n+LOG_MIN_SIZE+1)-1, which means - that the smallest chunk is 2**LOG_MIN_SIZE (== MIN_SIZE). -*/ - -#ifdef SYSTEM -#include -#define SBRK sys_break -extern void *SBRK(int incr); -#else -#include -#define SBRK sbrk -#define ILL_BREAK (void *)(-1) /* funny failure value */ -#endif -#ifdef STORE -#define MAX_STORE 32 -private do_free(mallink *ml), sell_out(void); -privatedata mallink *store[MAX_STORE]; -#endif /* STORE */ - -void * -malloc(register size_t n) -{check_mallinks("malloc entry");{ - register mallink *ml; - register int min_class; - - if (n == 0) { - return NULL; - } - if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n); -#ifdef STORE - if (n <= MAX_STORE*MIN_SIZE) { - /* look in the store first */ - register mallink **stp = &store[(n >> LOG_MIN_SIZE) - 1]; - - if (ml = *stp) { - *stp = log_next_of(ml); - set_store(ml, 0); - check_mallinks("malloc fast exit"); - assert(! in_store(ml)); - return block_of_mallink(ml); - } - } -#endif /* STORE */ - - check_work_empty("malloc, entry"); - - /* Acquire a chunk of at least size n if at all possible; - Try everything. - */ - { - /* Inline substitution of "smallest". - */ - register size_t n1 = n; - - assert(n1 < (1L << LOG_MAX_SIZE)); - min_class = 0; - - do { - n1 >>= 1; - min_class++; - } while (n1 >= MIN_SIZE); - } - - if (min_class >= MAX_FLIST) - return NULL; /* we don't deal in blocks that big */ - ml = first_present(min_class); - if (ml == MAL_NULL) { - /* Try and extend */ - register void *p; -#define GRABSIZE 4096 /* Power of 2 */ - register size_t req = - ((MIN_SIZE<= 0) p = SBRK((int)req); - } - if (p == ILL_BREAK) { - /* Now this is bad. The system will not give us - more memory. We can only liquidate our store - and hope it helps. - */ -#ifdef STORE - sell_out(); - ml = first_present(min_class); - if (ml == MAL_NULL) { -#endif /* STORE */ - /* In this emergency we try to locate a suitable - chunk in the free_list just below the safe - one; some of these chunks may fit the job. - */ - ml = search_free_list(min_class - 1, n); - if (!ml) /* really out of space */ - return NULL; - started_working_on(ml); - unlink_free_chunk(ml); - check_mallinks("suitable_chunk, forced"); -#ifdef STORE - } - else started_working_on(ml); -#endif /* STORE */ - } - else { - assert((size_type)p == align((size_type)p)); - ml = create_chunk(p, req); - } - check_mallinks("suitable_chunk, extended"); - } - else started_working_on(ml); - - /* we have a chunk */ - set_free(ml, 0); - calc_checksum(ml); - check_mallinks("suitable_chunk, removed"); - n += mallink_size(); - if (n + MIN_SIZE <= size_of(ml)) { - truncate(ml, n); - } - stopped_working_on(ml); - check_mallinks("malloc exit"); - check_work_empty("malloc exit"); -#ifdef STORE - assert(! in_store(ml)); -#endif - return block_of_mallink(ml); -}} - -void -free(void *addr) -{check_mallinks("free entry");{ - register mallink *ml; - - if (addr == NULL) { - check_mallinks("free(0) very fast exit"); - return; - } - - ml = mallink_of_block(addr); -#ifdef STORE - - if (free_of(ml) || in_store(ml)) - return; /* user frees free block */ - if (size_of(ml) <= MAX_STORE*MIN_SIZE) { - /* return to store */ - mallink **stp = &store[(size_of(ml) >> LOG_MIN_SIZE) - 1]; - - set_log_next(ml, *stp); - *stp = ml; - set_store(ml, 1); - calc_checksum(ml); - check_mallinks("free fast exit"); - } - else { - do_free(ml); - check_mallinks("free exit"); - } -}} - -private -do_free(register mallink *ml) -{{ -#endif - -#ifndef STORE - if (free_of(ml)) return; -#endif /* STORE */ - started_working_on(ml); - set_free(ml, 1); - calc_checksum(ml); - if (! last_mallink(ml)) { - register mallink *next = phys_next_of(ml); - - if (free_of(next)) coalesce_forw(ml, next); - } - - if (! first_mallink(ml)) { - register mallink *prev = phys_prev_of(ml); - - if (free_of(prev)) { - coalesce_backw(ml, prev); - ml = prev; - } - } - link_free_chunk(ml); - stopped_working_on(ml); - check_work_empty("free"); - - /* Compile-time checks on param.h */ - switch (0) { - case MIN_SIZE < OFF_SET * sizeof(mallink): break; - case 1: break; - /* If this statement does not compile due to duplicate case - entry, the minimum size block cannot hold the links for - the free blocks. Either raise LOG_MIN_SIZE or switch - off NON_STANDARD. - */ - } - switch(0) { - case sizeof(void *) != sizeof(size_type): break; - case 1: break; - /* If this statement does not compile due to duplicate - case entry, size_type is not defined correctly. - Redefine and compile again. - */ - } -}} - -void * -realloc(void *addr, register size_t n) -{check_mallinks("realloc entry");{ - register mallink *ml, *ph_next; - register size_type size; - - if (addr == NULL) { - /* Behave like most Unix realloc's when handed a - null-pointer - */ - return malloc(n); - } - if (n == 0) { - free(addr); - return NULL; - } - ml = mallink_of_block(addr); - if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n); -#ifdef STORE - if (in_store(ml)) { - register mallink *stp = store[(size_of(ml) >> LOG_MIN_SIZE) - 1]; - mallink *stp1 = NULL; - while (ml != stp) { - stp1 = stp; - stp = log_next_of(stp); - } - stp = log_next_of(stp); - if (! stp1) store[(size_of(ml) >> LOG_MIN_SIZE) - 1] = stp; - else set_log_next(stp1, stp); - set_store(ml, 0); - calc_checksum(ml); - } -#endif - if (free_of(ml)) { - unlink_free_chunk(ml); - set_free(ml, 0); /* user reallocs free block */ - } - started_working_on(ml); - size = size_of(ml); - if ( /* we can simplify the problem by adding the next chunk: */ - n > size && - !last_mallink(ml) && - (ph_next = phys_next_of(ml), free_of(ph_next)) && - n <= size + mallink_size() + size_of(ph_next) - ) { - /* add in the physically next chunk */ - unlink_free_chunk(ph_next); - combine_chunks(ml, ph_next); - size = size_of(ml); - check_mallinks("realloc, combining"); - } - if (n > size) { /* this didn't help */ - void *new; - register char *l1, *l2 = addr; - - stopped_working_on(ml); - if (!(new = l1 = malloc(n))) return NULL; /* no way */ - while (size--) *l1++ = *l2++; - free(addr); - check_work_empty("mv_realloc"); -#ifdef STORE - assert(! in_store(mallink_of_block(new))); -#endif - return new; - } - /* it helped, but maybe too well */ - n += mallink_size(); - if (n + MIN_SIZE <= size_of(ml)) { - truncate(ml, n); - } - stopped_working_on(ml); - check_mallinks("realloc exit"); - check_work_empty("realloc"); -#ifdef STORE - assert(! in_store(ml)); -#endif - return addr; -}} - -void * -calloc(size_t nmemb, size_t size) -{check_mallinks("calloc entry");{ - long *l1, *l2; - size_t n; - - if (size == 0) return NULL; - if (nmemb == 0) return NULL; - - /* Check for overflow on the multiplication. The peephole-optimizer - * will eliminate all but one of the possibilities. - */ - if (sizeof(size_t) == sizeof(int)) { - if (UINT_MAX / size < nmemb) return NULL; - } else if (sizeof(size_t) == sizeof(long)) { - if (ULONG_MAX / size < nmemb) return NULL; - } else return NULL; /* can't happen, can it ? */ - - n = size * nmemb; - if (n < MIN_SIZE) n = align(MIN_SIZE); else n = align(n); - if (n >= (1L << LOG_MAX_SIZE)) return NULL; - l1 = (long *) malloc(n); - l2 = l1 + (n / sizeof(long)); /* n is at least long aligned */ - while ( l2 != l1 ) *--l2 = 0; - check_mallinks("calloc exit"); - check_work_empty("calloc exit"); - return (void *)l1; -}} -/* Auxiliary routines */ - -#ifdef STORE -private -sell_out(void) { - /* Frees all block in store. - */ - register mallink **stp; - - for (stp = &store[0]; stp < &store[MAX_STORE]; stp++) { - register mallink *ml = *stp; - - while (ml) { - *stp = log_next_of(ml); - set_store(ml, 0); - do_free(ml); - ml = *stp; - } - } - -} -#endif /* STORE */ - -#ifdef ASSERT -public -m_assert(const char *fn, int ln) -{ - char ch; - - while (*fn) - write(2, fn++, 1); - write(2, ": malloc assert failed in line ", 31); - ch = (ln / 100) + '0'; write(2, &ch, 1); ln %= 100; - ch = (ln / 10) + '0'; write(2, &ch, 1); ln %= 10; - ch = (ln / 1) + '0'; write(2, &ch, 1); - write(2, "\n", 1); - maldump(1); -} -#endif /* ASSERT */ diff --git a/lang/cem/libcc.ansi/stdlib/malloc/param.h b/lang/cem/libcc.ansi/stdlib/malloc/param.h deleted file mode 100644 index b47c0d430..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/param.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#include "size_type.h" - -# define NON_STANDARD /* If defined, the contents of a block - will NOT be left undisturbed after it - is freed, as opposed to what it says - in the manual (malloc(2)). - Setting this option reduces the memory - overhead considerably. I personally - consider the specified behaviour an - artefact of the original - implementation. - */ - -# undef ASSERT /* If defined, some inexpensive tests - will be made to ensure the - correctness of some sensitive data. - It often turns an uncontrolled crash - into a controlled one. - */ - -# undef CHECK /* If defined, extensive and expensive - tests will be done, inculding a - checksum on the mallinks (chunk - information blocks). The resulting - information will be printed on a file - called mal.out . - Additionally a function - maldump(n) int n; - will be defined, which will dump - pertinent info in pseudo-readable - form; it aborts afterwards if n != 0. - */ - -# undef EXTERN /* If defined, all static names will - become extern, which is a help in - using adb(1) or prof(1) - */ - -# define STORE /* If defined, separate free lists will - be kept of chunks with small sizes, - to speed things up a little. - */ - -# undef SYSTEM /* If defined, the system module is used. - Otherwise, "sbrk" is called directly. - */ - -#define ALIGNMENT 8 - /* alignment common to all types */ -#define LOG_MIN_SIZE 3 -#define LOG_MAX_SIZE 24 diff --git a/lang/cem/libcc.ansi/stdlib/malloc/phys.c b/lang/cem/libcc.ansi/stdlib/malloc/phys.c deleted file mode 100644 index 3d14fa35c..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/phys.c +++ /dev/null @@ -1,96 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -#include -#include "param.h" -#include "impl.h" -#include "check.h" -#include "phys.h" - -/* Physical manipulations. - The blocks concerned are not in any logical chain. -*/ - -public mallink * -create_chunk(void *p, size_t n) -{ - /* The newly acquired piece of memory at p, of length n, - is turned into a free chunk, properly chained in the - physical chain. - The address of the chunk is returned. - */ - register mallink *ml; - /* All of malloc memory is followed by a virtual chunk, the - mallink of which starts mallink_size() bytes past the last - byte in memory. - Its use is prevented by testing for ml == ml_last first. - */ - register mallink *last = ml_last; - - assert(!last || p == (char *)phys_next_of(last) - mallink_size()); - ml = (mallink *)((char *)p + mallink_size()); /* bump ml */ - new_mallink(ml); - started_working_on(ml); - set_free(ml, 1); - set_phys_prev(ml, last); - ml_last = ml; - - set_phys_next(ml, (mallink *)((char *)ml + n)); - calc_checksum(ml); - assert(size_of(ml) + mallink_size() == n); - if (last && free_of(last)) { - coalesce_backw(ml, last); - ml = last; - } - check_mallinks("create_chunk, phys. linked"); - return ml; -} - -public -truncate(register mallink *ml, size_t size) -{ - /* The chunk ml is truncated. - The chunk at ml is split in two. - The remaining part is then freed. - */ - register mallink *new = (mallink *)((char *)ml + size); - register mallink *ph_next = phys_next_of(ml); - - new_mallink(new); - set_free(new, 1); - set_phys_prev(new, ml); - set_phys_next(new, ph_next); - calc_checksum(new); - if (! last_mallink(ml)) { - set_phys_prev(ph_next, new); - calc_checksum(ph_next); - if (free_of(ph_next)) coalesce_forw(new, ph_next); - } - else ml_last = new; - set_phys_next(ml, new); - calc_checksum(ml); - - started_working_on(new); - link_free_chunk(new); - stopped_working_on(new); - check_mallinks("truncate"); -} - -public -combine_chunks(register mallink *ml1, register mallink *ml2) -{ - /* The chunks ml1 and ml2 are combined. - */ - register mallink *ml3 = phys_next_of(ml2); - - set_phys_next(ml1, ml3); - calc_checksum(ml1); - if (!last_mallink(ml2)) { - set_phys_prev(ml3, ml1); - calc_checksum(ml3); - } - if (ml_last == ml2) - ml_last = ml1; -} diff --git a/lang/cem/libcc.ansi/stdlib/malloc/phys.h b/lang/cem/libcc.ansi/stdlib/malloc/phys.h deleted file mode 100644 index 67fb9838d..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/phys.h +++ /dev/null @@ -1,76 +0,0 @@ -/* $Id$ */ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* Algorithms to manipulate the doubly-linked list of physical - chunks. -*/ -publicdata mallink *ml_last; - -#define FREE_BIT 01 -#ifdef STORE -#define STORE_BIT 02 -#define BITS (FREE_BIT|STORE_BIT) -#else -#define BITS (FREE_BIT) -#endif - -#define __bits(ml) ((int)((size_type)_phys_prev_of(ml) & BITS)) -#define __free_of(ml) ((int)((size_type)_phys_prev_of(ml) & FREE_BIT)) -#define __phys_prev_of(ml) ((mallink *)((size_type)_phys_prev_of(ml) & ~BITS)) -#define prev_size_of(ml) ((char *)(ml) - \ - (char *)__phys_prev_of(ml) - \ - mallink_size() \ - ) -#define set_phys_prev(ml,e) \ - (_phys_prev_of(ml) = (mallink *) ((char *)e + __bits(ml))) - -#ifdef CHECK -public Error(const char *fmt, const char *s, mallink *ml); -#define phys_prev_of(ml) (mallink *) \ - (first_mallink(ml) ? \ - (char *)Error("phys_prev_of first_mallink %p", "somewhere", ml) : \ - (char *)__phys_prev_of(ml) \ - ) -#else /* ndef CHECK */ -#define phys_prev_of(ml) __phys_prev_of(ml) -#endif /* CHECK */ - -#define first_mallink(ml) (int) (__phys_prev_of(ml) == 0) -#define last_mallink(ml) (int) ((ml) == ml_last) - -/* There is an ambiguity in the semantics of phys_next_of: sometimes - one wants it to return MAL_NULL if there is no next chunk, at - other times one wants the address of the virtual chunk at the - end of memory. The present version returns the address of the - (virtual) chunk and relies on the user to test last_mallink(ml) - first. -*/ -#define size_of(ml) (_this_size_of(ml) - mallink_size()) -#define set_phys_next(ml,e) \ - (_this_size_of(ml) = (size_type)((char *)(e) - (char *)(ml))) -#define phys_next_of(ml) (mallink *) ((char *)(ml) + _this_size_of(ml)) - -#define set_free(ml,e) \ - (_phys_prev_of(ml) = (mallink *) \ - ((e) ? (size_type) _phys_prev_of(ml) | FREE_BIT : \ - (size_type) _phys_prev_of(ml) & ~FREE_BIT)) -#define free_of(ml) (__free_of(ml)) - -#define coalesce_forw(ml,nxt) ( unlink_free_chunk(nxt), \ - combine_chunks((ml), (nxt))) - -#define coalesce_backw(ml,prv) ( unlink_free_chunk(prv), \ - stopped_working_on(ml), \ - combine_chunks((prv), (ml)), \ - started_working_on(prv)) - -#ifdef CHECK -#define set_print(ml,e) (_print_of(ml) = (e)) -#define print_of(ml) (_print_of(ml)) -#endif /* CHECK */ - -public truncate(mallink *ml, size_t size); -public combine_chunks(register mallink *ml1, register mallink *ml2); -public mallink *create_chunk(void *p, size_t n); diff --git a/lang/cem/libcc.ansi/stdlib/malloc/size_type.h b/lang/cem/libcc.ansi/stdlib/malloc/size_type.h deleted file mode 100644 index b39609ea1..000000000 --- a/lang/cem/libcc.ansi/stdlib/malloc/size_type.h +++ /dev/null @@ -1,8 +0,0 @@ -#if _EM_WSIZE == _EM_PSIZE -typedef unsigned int size_type; -#elif _EM_LSIZE == _EM_PSIZE -typedef unsigned long size_type; -#else -#error funny pointer size -#endif -#include