libc/libminc malloc reorganization
. rename minix malloc sources to minix-* so Makefile references aren't ambiguous . throw out malloc source file copies in libminc . make libminc use phkmalloc instead of minix malloc (slightly faster)
This commit is contained in:
parent
c087a60ed2
commit
d3d8c30c2e
8 changed files with 19 additions and 277 deletions
|
@ -44,9 +44,9 @@ SRCS+= erand48_ieee754.c
|
||||||
SRCS+= jemalloc.c
|
SRCS+= jemalloc.c
|
||||||
.elif (${USE_MINIXMALLOC} != "no")
|
.elif (${USE_MINIXMALLOC} != "no")
|
||||||
SRCS+= \
|
SRCS+= \
|
||||||
minix/malloc.c \
|
minix/minix-malloc.c \
|
||||||
minix/calloc.c \
|
minix/minix-calloc.c \
|
||||||
minix/malloc-debug.c
|
minix/minix-malloc-debug.c
|
||||||
.else
|
.else
|
||||||
SRCS+= malloc.c
|
SRCS+= malloc.c
|
||||||
.endif
|
.endif
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
#ifdef __minix
|
#ifdef __minix
|
||||||
#define mmap minix_mmap
|
#define mmap minix_mmap
|
||||||
#define munmap minix_munmap
|
#define munmap minix_munmap
|
||||||
|
#ifdef _LIBSYS
|
||||||
|
#include <minix/sysutil.h>
|
||||||
|
#define MALLOC_NO_SYSCALLS
|
||||||
|
#define wrtwarning(w) printf("libminc malloc warning: %s\n", w)
|
||||||
|
#define wrterror(w) panic("libminc malloc error: %s\n", w)
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -309,6 +315,7 @@ static void *imalloc(size_t size);
|
||||||
static void ifree(void *ptr);
|
static void ifree(void *ptr);
|
||||||
static void *irealloc(void *ptr, size_t size);
|
static void *irealloc(void *ptr, size_t size);
|
||||||
|
|
||||||
|
#ifndef MALLOC_NO_SYSCALLS
|
||||||
static void
|
static void
|
||||||
wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
|
wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
|
||||||
{
|
{
|
||||||
|
@ -341,6 +348,7 @@ wrtwarning(const char *p)
|
||||||
if (malloc_abort || issetugid() || getuid() == 0 || getgid() == 0)
|
if (malloc_abort || issetugid() || getuid() == 0 || getgid() == 0)
|
||||||
wrterror(p);
|
wrterror(p);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a number of pages from the OS
|
* Allocate a number of pages from the OS
|
||||||
|
@ -452,16 +460,20 @@ extend_pgdir(size_t idx)
|
||||||
static void
|
static void
|
||||||
malloc_init(void)
|
malloc_init(void)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
#ifndef MALLOC_NO_SYSCALLS
|
||||||
const char *p;
|
const char *p;
|
||||||
char b[64];
|
char b[64];
|
||||||
size_t i;
|
size_t i;
|
||||||
ssize_t j;
|
ssize_t j;
|
||||||
int save_errno = errno;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute page-size related variables.
|
* Compute page-size related variables.
|
||||||
*/
|
*/
|
||||||
malloc_pagesize = (size_t)sysconf(_SC_PAGESIZE);
|
malloc_pagesize = (size_t)sysconf(_SC_PAGESIZE);
|
||||||
|
#else
|
||||||
|
malloc_pagesize = PAGE_SIZE;
|
||||||
|
#endif
|
||||||
malloc_pagemask = malloc_pagesize - 1;
|
malloc_pagemask = malloc_pagesize - 1;
|
||||||
for (malloc_pageshift = 0;
|
for (malloc_pageshift = 0;
|
||||||
(1UL << malloc_pageshift) != malloc_pagesize;
|
(1UL << malloc_pageshift) != malloc_pagesize;
|
||||||
|
@ -474,6 +486,7 @@ malloc_init(void)
|
||||||
malloc_junk = 1;
|
malloc_junk = 1;
|
||||||
#endif /* MALLOC_EXTRA_SANITY */
|
#endif /* MALLOC_EXTRA_SANITY */
|
||||||
|
|
||||||
|
#ifndef MALLOC_NO_SYSCALLS
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
j = readlink("/etc/malloc.conf", b, sizeof b - 1);
|
j = readlink("/etc/malloc.conf", b, sizeof b - 1);
|
||||||
|
@ -519,6 +532,7 @@ malloc_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
UTRACE(0, 0, 0);
|
UTRACE(0, 0, 0);
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,6 @@ SRCS+= memset.c
|
||||||
#
|
#
|
||||||
# Customized versions of libc functions.
|
# Customized versions of libc functions.
|
||||||
#
|
#
|
||||||
SRCS+= calloc.c malloc.c
|
|
||||||
SRCS+= fputs.c _stdfile.c
|
SRCS+= fputs.c _stdfile.c
|
||||||
CPPFLAGS.fputs.c+= -I${LIBCSRCDIR}/include
|
CPPFLAGS.fputs.c+= -I${LIBCSRCDIR}/include
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ SRCS+= ${i}
|
||||||
.endfor
|
.endfor
|
||||||
# Import from stdlib
|
# Import from stdlib
|
||||||
.for i in abort.c atexit.c atoi.c exit.c getenv.c \
|
.for i in abort.c atexit.c atoi.c exit.c getenv.c \
|
||||||
getopt.c ldiv.c
|
getopt.c ldiv.c malloc.c
|
||||||
.PATH.c: ${LIBCSRCDIR}/stdlib
|
.PATH.c: ${LIBCSRCDIR}/stdlib
|
||||||
SRCS+= ${i}
|
SRCS+= ${i}
|
||||||
CPPFLAGS.${i}+= -I${LIBCSRCDIR}/stdlib -I${LIBCSRCDIR}/include
|
CPPFLAGS.${i}+= -I${LIBCSRCDIR}/stdlib -I${LIBCSRCDIR}/include
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/* $Header$ */
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/* replace undef by define */
|
|
||||||
#define ALIGN_EIGHT_BYTES /* Use 8-byte alignment. */
|
|
||||||
|
|
||||||
#ifdef ALIGN_EIGHT_BYTES
|
|
||||||
#define ALIGN_SIZE 8
|
|
||||||
#else
|
|
||||||
#define ALIGN_SIZE sizeof(size_t)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ALIGN(x) (((x) + (ALIGN_SIZE - 1)) & ~(ALIGN_SIZE - 1))
|
|
||||||
|
|
||||||
void *
|
|
||||||
calloc(size_t nelem, size_t elsize)
|
|
||||||
{
|
|
||||||
register char *p;
|
|
||||||
register size_t *q;
|
|
||||||
size_t size = ALIGN(nelem * elsize);
|
|
||||||
|
|
||||||
p = malloc(size);
|
|
||||||
if (p == NULL) return NULL;
|
|
||||||
q = (size_t *) (p + size);
|
|
||||||
while ((char *) q > p) *--q = 0;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,243 +0,0 @@
|
||||||
/* $Header$ */
|
|
||||||
|
|
||||||
/* replace undef by define */
|
|
||||||
#define ALIGN_EIGHT_BYTES /* Use 8-byte alignment. */
|
|
||||||
#define DEBUG /* check assertions */
|
|
||||||
#undef SLOWDEBUG /* some extra test loops (requires DEBUG) */
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
|
||||||
#define NDEBUG
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
#define CHECK_DBG(statement)
|
|
||||||
|
|
||||||
#define ptrint int
|
|
||||||
|
|
||||||
#define BRKSIZE 4096
|
|
||||||
#ifdef ALIGN_EIGHT_BYTES
|
|
||||||
#define PTRSIZE 8
|
|
||||||
#else
|
|
||||||
#define PTRSIZE ((int) sizeof(void *))
|
|
||||||
#endif
|
|
||||||
#define Align(x,a) (((x) + (a - 1)) & ~(a - 1))
|
|
||||||
#define NextSlot(p) (* (void **) ((p) - PTRSIZE))
|
|
||||||
#define NextFree(p) (* (void **) (p))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* A short explanation of the data structure and algorithms.
|
|
||||||
* An area returned by malloc() is called a slot. Each slot
|
|
||||||
* contains the number of bytes requested, but preceeded by
|
|
||||||
* an extra pointer to the next the slot in memory.
|
|
||||||
* '_bottom' and '_top' point to the first/last slot.
|
|
||||||
* More memory is asked for using brk() and appended to top.
|
|
||||||
* The list of free slots is maintained to keep malloc() fast.
|
|
||||||
* '_empty' points the the first free slot. Free slots are
|
|
||||||
* linked together by a pointer at the start of the
|
|
||||||
* user visable part, so just after the next-slot pointer.
|
|
||||||
* Free slots are merged together by free().
|
|
||||||
*
|
|
||||||
* Since modern processors prefer 8-byte alignment, we now pretend
|
|
||||||
* our pointers are 8 bytes wide.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern void *_sbrk(int);
|
|
||||||
extern int _brk(void *);
|
|
||||||
static void *_bottom, *_top, *_empty;
|
|
||||||
|
|
||||||
static int grow(size_t len)
|
|
||||||
{
|
|
||||||
register char *p;
|
|
||||||
|
|
||||||
assert(NextSlot((char *)_top) == 0);
|
|
||||||
if ((char *) _top + len < (char *) _top
|
|
||||||
|| (p = (char *)Align((ptrint)_top + len, BRKSIZE)) < (char *) _top ) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
if (_brk(p) != 0)
|
|
||||||
return(0);
|
|
||||||
NextSlot((char *)_top) = p;
|
|
||||||
NextSlot(p) = 0;
|
|
||||||
free(_top);
|
|
||||||
_top = p;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
malloc(const size_t size)
|
|
||||||
{
|
|
||||||
register char *prev, *p, *next, *new;
|
|
||||||
unsigned ntries;
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
CHECK_DBG(return _dbg_malloc(size));
|
|
||||||
|
|
||||||
for (ntries = 0; ntries < 2; ntries++) {
|
|
||||||
unsigned len = Align(size, PTRSIZE) + PTRSIZE;
|
|
||||||
if (len < 2 * PTRSIZE) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (_bottom == 0) {
|
|
||||||
if ((p = _sbrk(2 * PTRSIZE)) == (char *) -1)
|
|
||||||
return NULL;
|
|
||||||
p = (char *) Align((ptrint)p, PTRSIZE);
|
|
||||||
p += PTRSIZE;
|
|
||||||
_top = _bottom = p;
|
|
||||||
NextSlot(p) = 0;
|
|
||||||
}
|
|
||||||
#ifdef SLOWDEBUG
|
|
||||||
for (p = _bottom; (next = NextSlot(p)) != 0; p = next)
|
|
||||||
assert(next > p);
|
|
||||||
assert(p == _top);
|
|
||||||
#endif
|
|
||||||
for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
|
|
||||||
next = NextSlot(p);
|
|
||||||
new = p + len; /* easily overflows!! */
|
|
||||||
if (new > next || new <= p)
|
|
||||||
continue; /* too small */
|
|
||||||
if (new + PTRSIZE < next) { /* too big, so split */
|
|
||||||
/* + PTRSIZE avoids tiny slots on free list */
|
|
||||||
NextSlot(new) = next;
|
|
||||||
NextSlot(p) = new;
|
|
||||||
NextFree(new) = NextFree(p);
|
|
||||||
NextFree(p) = new;
|
|
||||||
}
|
|
||||||
if (prev)
|
|
||||||
NextFree(prev) = NextFree(p);
|
|
||||||
else
|
|
||||||
_empty = NextFree(p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
if (grow(len) == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(ntries != 2);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
realloc(void *oldp, size_t size)
|
|
||||||
{
|
|
||||||
register char *prev, *p, *next, *new;
|
|
||||||
char *old = oldp;
|
|
||||||
register size_t len, n;
|
|
||||||
|
|
||||||
if (old == 0)
|
|
||||||
return malloc(size);
|
|
||||||
if (size == 0) {
|
|
||||||
free(old);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_DBG(return _dbg_realloc(oldp, size));
|
|
||||||
|
|
||||||
len = Align(size, PTRSIZE) + PTRSIZE;
|
|
||||||
next = NextSlot(old);
|
|
||||||
n = (int)(next - old); /* old length */
|
|
||||||
/*
|
|
||||||
* extend old if there is any free space just behind it
|
|
||||||
*/
|
|
||||||
for (prev = 0, p = _empty; p != 0; prev = p, p = NextFree(p)) {
|
|
||||||
if (p > next)
|
|
||||||
break;
|
|
||||||
if (p == next) { /* 'next' is a free slot: merge */
|
|
||||||
NextSlot(old) = NextSlot(p);
|
|
||||||
if (prev)
|
|
||||||
NextFree(prev) = NextFree(p);
|
|
||||||
else
|
|
||||||
_empty = NextFree(p);
|
|
||||||
next = NextSlot(old);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new = old + len;
|
|
||||||
/*
|
|
||||||
* Can we use the old, possibly extended slot?
|
|
||||||
*/
|
|
||||||
if (new <= next && new >= old) { /* it does fit */
|
|
||||||
if (new + PTRSIZE < next) { /* too big, so split */
|
|
||||||
/* + PTRSIZE avoids tiny slots on free list */
|
|
||||||
NextSlot(new) = next;
|
|
||||||
NextSlot(old) = new;
|
|
||||||
free(new);
|
|
||||||
}
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
if ((new = malloc(size)) == NULL) /* it didn't fit */
|
|
||||||
return NULL;
|
|
||||||
memcpy(new, old, n); /* n < size */
|
|
||||||
free(old);
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free(void *ptr)
|
|
||||||
{
|
|
||||||
register char *prev, *next;
|
|
||||||
char *p = ptr;
|
|
||||||
|
|
||||||
if (p == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CHECK_DBG(_dbg_free(ptr); return);
|
|
||||||
|
|
||||||
#ifdef SLOWDEBUG
|
|
||||||
{
|
|
||||||
int found;
|
|
||||||
char *curr;
|
|
||||||
|
|
||||||
/* block must be in block list */
|
|
||||||
assert(_bottom);
|
|
||||||
found = 0;
|
|
||||||
for (curr = _bottom; (next = NextSlot(curr)) != 0; curr = next) {
|
|
||||||
assert(next > curr);
|
|
||||||
if (curr == p) found = 1;
|
|
||||||
}
|
|
||||||
if (curr == p) found = 1;
|
|
||||||
assert(found);
|
|
||||||
|
|
||||||
/* block must not be in free list */
|
|
||||||
if (_empty) {
|
|
||||||
found = 0;
|
|
||||||
for (curr = _empty; (next = NextFree(curr)) != 0; curr = next) {
|
|
||||||
assert(next > curr);
|
|
||||||
if (curr == p) found = 1;
|
|
||||||
}
|
|
||||||
if (curr == p) found = 1;
|
|
||||||
assert(!found);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert((char *) NextSlot(p) > p);
|
|
||||||
for (prev = 0, next = _empty; next != 0; prev = next, next = NextFree(next))
|
|
||||||
if (p < next)
|
|
||||||
break;
|
|
||||||
NextFree(p) = next;
|
|
||||||
if (prev)
|
|
||||||
NextFree(prev) = p;
|
|
||||||
else
|
|
||||||
_empty = p;
|
|
||||||
if (next) {
|
|
||||||
assert((char *) NextSlot(p) <= next);
|
|
||||||
if (NextSlot(p) == next) { /* merge p and next */
|
|
||||||
NextSlot(p) = NextSlot(next);
|
|
||||||
NextFree(p) = NextFree(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prev) {
|
|
||||||
assert((char *) NextSlot(prev) <= p);
|
|
||||||
if (NextSlot(prev) == p) { /* merge prev and p */
|
|
||||||
NextSlot(prev) = NextSlot(p);
|
|
||||||
NextFree(prev) = NextFree(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue