#include "sh.h"
RCSID("$Id: tc.alloc.c,v 3.39 2005/01/05 16:06:14 christos Exp $")
static char *memtop = NULL;
static char *membot = NULL;
int dont_free = 0;
#ifdef WINNT_NATIVE
# define malloc fmalloc
# define free ffree
# define calloc fcalloc
# define realloc frealloc
#endif
#ifndef SYSMALLOC
#undef RCHECK
#undef DEBUG
#ifdef SX
extern void* sbrk();
#endif
#ifndef NULL
#define NULL 0
#endif
typedef unsigned char U_char;
typedef unsigned int U_int;
typedef unsigned short U_short;
typedef unsigned long U_long;
#define MEMALIGN(a) (((a) + ROUNDUP) & ~ROUNDUP)
union overhead {
union overhead *ov_next;
struct {
U_char ovu_magic;
U_char ovu_index;
#ifdef RCHECK
U_short ovu_size;
U_int ovu_rmagic;
#endif
} ovu;
#define ov_magic ovu.ovu_magic
#define ov_index ovu.ovu_index
#define ov_size ovu.ovu_size
#define ov_rmagic ovu.ovu_rmagic
};
#define MAGIC 0xfd
#define RMAGIC 0x55555555
#ifdef RCHECK
#define RSLOP sizeof (U_int)
#else
#define RSLOP 0
#endif
#define ROUNDUP 7
#define NBUCKETS ((sizeof(long) << 3) - 3)
static union overhead *nextf[NBUCKETS] IZERO_STRUCT;
static U_int nmalloc[NBUCKETS] IZERO_STRUCT;
#ifndef lint
static int findbucket __P((union overhead *, int));
static void morecore __P((int));
#endif
#ifdef DEBUG
# define CHECK(a, str, p) \
if (a) { \
xprintf(str, p); \
xprintf(" (memtop = %lx membot = %lx)\n", memtop, membot); \
abort(); \
}
#else
# define CHECK(a, str, p) \
if (a) { \
xprintf(str, p); \
xprintf(" (memtop = %lx membot = %lx)\n", memtop, membot); \
return; \
}
#endif
memalign_t
malloc(nbytes)
size_t nbytes;
{
#ifndef lint
union overhead *p;
int bucket = 0;
unsigned shiftr;
#ifdef SUNOS4
nbytes++;
#endif
nbytes = MEMALIGN(MEMALIGN(sizeof(union overhead)) + nbytes + RSLOP);
shiftr = (nbytes - 1) >> 2;
while ((shiftr >>= 1) != 0)
bucket++;
if (nextf[bucket] == NULL)
morecore(bucket);
if ((p = (union overhead *) nextf[bucket]) == NULL) {
child++;
#ifndef DEBUG
stderror(ERR_NOMEM);
#else
showall(NULL, NULL);
xprintf(CGETS(19, 1, "nbytes=%d: Out of memory\n"), nbytes);
abort();
#endif
return ((memalign_t) 0);
}
nextf[bucket] = nextf[bucket]->ov_next;
p->ov_magic = MAGIC;
p->ov_index = bucket;
nmalloc[bucket]++;
#ifdef RCHECK
p->ov_size = (p->ov_index <= 13) ? nbytes - 1 : 0;
p->ov_rmagic = RMAGIC;
*((U_int *) (((caddr_t) p) + nbytes - RSLOP)) = RMAGIC;
#endif
return ((memalign_t) (((caddr_t) p) + MEMALIGN(sizeof(union overhead))));
#else
if (nbytes)
return ((memalign_t) 0);
else
return ((memalign_t) 0);
#endif
}
#ifndef lint
static void
morecore(bucket)
int bucket;
{
union overhead *op;
int rnu;
int nblks;
int siz;
if (nextf[bucket])
return;
op = (union overhead *) sbrk(0);
memtop = (char *) op;
if (membot == NULL)
membot = memtop;
if ((long) op & 0x3ff) {
memtop = (char *) sbrk((int) (1024 - ((long) op & 0x3ff)));
memtop += (long) (1024 - ((long) op & 0x3ff));
}
rnu = (bucket <= 8) ? 11 : bucket + 3;
nblks = 1 << (rnu - (bucket + 3));
memtop = (char *) sbrk(1 << rnu);
op = (union overhead *) memtop;
if ((long) op == -1)
return;
memtop += (long) (1 << rnu);
if (((U_long) op) & ROUNDUP) {
op = (union overhead *) (((U_long) op + (ROUNDUP + 1)) & ~ROUNDUP);
nblks--;
}
nextf[bucket] = op;
siz = 1 << (bucket + 3);
while (--nblks > 0) {
op->ov_next = (union overhead *) (((caddr_t) op) + siz);
op = (union overhead *) (((caddr_t) op) + siz);
}
op->ov_next = NULL;
}
#endif
void
free(cp)
ptr_t cp;
{
#ifndef lint
int size;
union overhead *op;
if (cp == NULL || dont_free)
return;
CHECK(!memtop || !membot,
CGETS(19, 2, "free(%lx) called before any allocations."), cp);
CHECK(cp > (ptr_t) memtop,
CGETS(19, 3, "free(%lx) above top of memory."), cp);
CHECK(cp < (ptr_t) membot,
CGETS(19, 4, "free(%lx) below bottom of memory."), cp);
op = (union overhead *) (((caddr_t) cp) - MEMALIGN(sizeof(union overhead)));
CHECK(op->ov_magic != MAGIC,
CGETS(19, 5, "free(%lx) bad block."), cp);
#ifdef RCHECK
if (op->ov_index <= 13)
CHECK(*(U_int *) ((caddr_t) op + op->ov_size + 1 - RSLOP) != RMAGIC,
CGETS(19, 6, "free(%lx) bad range check."), cp);
#endif
CHECK(op->ov_index >= NBUCKETS,
CGETS(19, 7, "free(%lx) bad block index."), cp);
size = op->ov_index;
op->ov_next = nextf[size];
nextf[size] = op;
nmalloc[size]--;
#else
if (cp == NULL)
return;
#endif
}
memalign_t
calloc(i, j)
size_t i, j;
{
#ifndef lint
char *cp, *scp;
i *= j;
scp = cp = (char *) xmalloc((size_t) i);
if (i != 0)
do
*cp++ = 0;
while (--i);
return ((memalign_t) scp);
#else
if (i && j)
return ((memalign_t) 0);
else
return ((memalign_t) 0);
#endif
}
#ifndef lint
static int realloc_srchlen = 4;
#endif
memalign_t
realloc(cp, nbytes)
ptr_t cp;
size_t nbytes;
{
#ifndef lint
U_int onb;
union overhead *op;
ptr_t res;
int i;
int was_alloced = 0;
if (cp == NULL)
return (malloc(nbytes));
op = (union overhead *) (((caddr_t) cp) - MEMALIGN(sizeof(union overhead)));
if (op->ov_magic == MAGIC) {
was_alloced++;
i = op->ov_index;
}
else
if ((i = findbucket(op, 1)) < 0 &&
(i = findbucket(op, realloc_srchlen)) < 0)
i = 0;
onb = MEMALIGN(nbytes + MEMALIGN(sizeof(union overhead)) + RSLOP);
if (was_alloced && (onb <= (U_int) (1 << (i + 3))) &&
(onb > (U_int) (1 << (i + 2)))) {
#ifdef RCHECK
nbytes = MEMALIGN(MEMALIGN(sizeof(union overhead))+nbytes+RSLOP);
*((U_int *) (((caddr_t) op) + nbytes - RSLOP)) = RMAGIC;
op->ov_rmagic = RMAGIC;
op->ov_size = (op->ov_index <= 13) ? nbytes - 1 : 0;
#endif
return ((memalign_t) cp);
}
if ((res = malloc(nbytes)) == NULL)
return ((memalign_t) NULL);
if (cp != res) {
onb = (1 << (i + 3)) - MEMALIGN(sizeof(union overhead)) - RSLOP;
(void) memmove((ptr_t) res, (ptr_t) cp,
(size_t) (onb < nbytes ? onb : nbytes));
}
if (was_alloced)
free(cp);
return ((memalign_t) res);
#else
if (cp && nbytes)
return ((memalign_t) 0);
else
return ((memalign_t) 0);
#endif
}
#ifndef lint
static int
findbucket(freep, srchlen)
union overhead *freep;
int srchlen;
{
union overhead *p;
size_t i;
int j;
for (i = 0; i < NBUCKETS; i++) {
j = 0;
for (p = nextf[i]; p && j != srchlen; p = p->ov_next) {
if (p == freep)
return (i);
j++;
}
}
return (-1);
}
#endif
#else
memalign_t
smalloc(n)
size_t n;
{
ptr_t ptr;
n = n ? n : 1;
#ifdef HAVE_SBRK
if (membot == NULL)
membot = (char*) sbrk(0);
#endif
if ((ptr = malloc(n)) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
#ifndef HAVE_SBRK
if (memtop < ((char *) ptr) + n)
memtop = ((char *) ptr) + n;
if (membot == NULL)
membot = (char*) ptr;
#endif
return ((memalign_t) ptr);
}
memalign_t
srealloc(p, n)
ptr_t p;
size_t n;
{
ptr_t ptr;
n = n ? n : 1;
#ifdef HAVE_SBRK
if (membot == NULL)
membot = (char*) sbrk(0);
#endif
if ((ptr = (p ? realloc(p, n) : malloc(n))) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
#ifndef HAVE_SBRK
if (memtop < ((char *) ptr) + n)
memtop = ((char *) ptr) + n;
if (membot == NULL)
membot = (char*) ptr;
#endif
return ((memalign_t) ptr);
}
memalign_t
scalloc(s, n)
size_t s, n;
{
char *sptr;
ptr_t ptr;
n *= s;
n = n ? n : 1;
#ifdef HAVE_SBRK
if (membot == NULL)
membot = (char*) sbrk(0);
#endif
if ((ptr = malloc(n)) == (ptr_t) 0) {
child++;
stderror(ERR_NOMEM);
}
sptr = (char *) ptr;
if (n != 0)
do
*sptr++ = 0;
while (--n);
#ifndef HAVE_SBRK
if (memtop < ((char *) ptr) + n)
memtop = ((char *) ptr) + n;
if (membot == NULL)
membot = (char*) ptr;
#endif
return ((memalign_t) ptr);
}
void
sfree(p)
ptr_t p;
{
if (p && !dont_free)
free(p);
}
#endif
void
showall(v, c)
Char **v;
struct command *c;
{
#ifndef SYSMALLOC
size_t i, j;
union overhead *p;
int totfree = 0, totused = 0;
xprintf(CGETS(19, 8, "%s current memory allocation:\nfree:\t"), progname);
for (i = 0; i < NBUCKETS; i++) {
for (j = 0, p = nextf[i]; p; p = p->ov_next, j++)
continue;
xprintf(" %4d", j);
totfree += j * (1 << (i + 3));
}
xprintf(CGETS(19, 9, "\nused:\t"));
for (i = 0; i < NBUCKETS; i++) {
xprintf(" %4u", nmalloc[i]);
totused += nmalloc[i] * (1 << (i + 3));
}
xprintf(CGETS(19, 10, "\n\tTotal in use: %d, total free: %d\n"),
totused, totfree);
xprintf(CGETS(19, 11,
"\tAllocated memory from 0x%lx to 0x%lx. Real top at 0x%lx\n"),
(unsigned long) membot, (unsigned long) memtop,
(unsigned long) sbrk(0));
#else
#ifdef HAVE_SBRK
memtop = (char *) sbrk(0);
#endif
xprintf(CGETS(19, 12, "Allocated memory from 0x%lx to 0x%lx (%ld).\n"),
(unsigned long) membot, (unsigned long) memtop,
(unsigned long) (memtop - membot));
#endif
USE(c);
USE(v);
}