home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 4
/
DATAFILE_PDCD4.iso
/
unix
/
unixlib36d
/
src
/
c
/
alloc
< prev
next >
Wrap
Text File
|
1994-03-08
|
6KB
|
406 lines
static char sccs_id[] = "@(#) alloc.c 5.0 " __DATE__ " HJR";
/* alloc.c (c) Copyright 1990 H.Rogers */
/* features multiple free lists hashed on block size */
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#ifdef M_DEBUG
#include <stdio.h>
#include <signal.h>
static int
__m_fail (char *exp, char *file, int line)
{
fprintf (stderr, "\n\"%s\", line %d: Assertion failed: %s\n", file, line, exp);
raise (SIGABRT);
return (0);
}
#define assert(x) (void)((x) ? 0 : __m_fail(#x,__FILE__,__LINE__))
#define addr(x) ((x) ? (*((int *)(x)) | 1) : 0)
#define MAGIC 0x4349474d
#endif
extern void *sbrk (int);
typedef struct _blk
{
#ifdef M_DEBUG
int magic;
#endif
struct _blk *next;
size_t size;
}
blk;
#ifdef M_DEBUG
#define BLKSIZ 16 /* smallest power of 2 >= sizeof(blk) */
#else
#define BLKSIZ 8
#endif
#define blkalign(x) (((x) + (BLKSIZ<<1) - 1) & (~(BLKSIZ - 1)))
#define NFL 8
static blk __fl[NFL];
static size_t __flmin[NFL] =
{
4096 + BLKSIZ,
1024 + BLKSIZ,
256 + BLKSIZ,
64 + BLKSIZ,
32 + BLKSIZ,
16 + BLKSIZ,
8 + BLKSIZ,
0 + BLKSIZ /* catchall */
};
#define MEMINC 12 /* sbrk() memory block bit alignment */
void
__allocinit (void)
{
register blk *b;
register int i;
#ifdef M_DEBUG
assert (sizeof (struct _blk) <= BLKSIZ);
#endif
for (i = 0; i < NFL; i++)
{
b = __fl + i;
b->next = b;
b->size = BLKSIZ;
#ifdef M_DEBUG
b->magic = MAGIC;
#endif
}
}
static blk *
findblk (register int i, register blk * a)
{
register blk *b, *p;
p = __fl + i;
b = p->next;
#ifdef M_DEBUG
assert (addr (p));
assert (p->magic == MAGIC);
#endif
while (b > p)
{
#ifdef M_DEBUG
assert (addr (b));
assert (b->magic == MAGIC);
#endif
if (b >= a)
break;
p = b;
b = b->next;
}
return (p);
}
#define addblk(i,n,p) ((n)->next = (p)->next,(p)->next = (n))
#define delblk(i,b,p) ((p)->next = (b)->next)
static void
concatblk (register blk * a, register blk * p)
{
register blk *b;
if (!p)
return;
b = p->next;
while ((char *) a + a->size == (char *) b)
{
a->size += b->size;
#ifdef M_DEBUG
b->magic = 0;
#endif
b = b->next;
}
p->next = b;
}
static int
flindex (register int size)
{
register int i;
for (i = 0; size < __flmin[i]; i++);
return (i);
}
static blk *
findsize (register int i, register int size, register blk ** p_)
{
register blk *b, *p;
p = __fl + i;
b = p->next;
while (b > p)
{
if (b->size >= size)
{
delblk (i, b, p);
break;
}
p = b;
b = b->next;
}
if (p_)
*p_ = p;
return (b);
}
void *
malloc (register size_t size)
{
register blk *b;
register int i;
blk *p;
if (!size)
return (0);
size = blkalign (size);
i = flindex (size);
b = findsize (i, size, &p);
if (b <= p)
{
register void *m;
register int _size;
_size = ((size >> MEMINC) + 1) << MEMINC;
if ((m = sbrk (_size)) == (void *) -1)
return (0);
if ((char *) p + p->size == (char *) m)
{
b = p;
p = findblk (i, b);
delblk (i, b, p);
b->size += _size;
}
else
{
b = (blk *) m;
b->size = _size;
#ifdef M_DEBUG
b->magic = MAGIC;
#endif
}
}
#ifdef M_DEBUG
assert (addr (b));
assert (b->magic == MAGIC);
#endif
if (b->size > (size + __flmin[i]))
{
register blk *n;
n = (blk *) ((char *) b + size);
addblk (i, n, p);
n->size = b->size - size;
#ifdef M_DEBUG
n->magic = MAGIC;
#endif
b->size = size;
}
return ((void *) ((char *) b + BLKSIZ));
}
void *
realloc (register void *_a, register size_t size)
{
register blk *a;
register int i;
blk *p;
if (!(_a))
return (malloc (size));
if (!size)
{
free (_a);
return (0);
}
size = blkalign (size);
#ifdef M_DEBUG
assert (addr (_a));
#endif
a = (blk *) ((char *) _a - BLKSIZ);
#ifdef M_DEBUG
assert (addr (a));
assert (a->magic == MAGIC);
#endif
i = flindex (a->size);
p = findblk (i, a);
concatblk (a, p);
if (a->size < size)
{
if ((char *) p + p->size == (char *) a && p->size + a->size >= size)
{
register blk *b;
#ifdef M_DEBUG
assert (addr (p));
assert (p->magic == MAGIC);
#endif
b = p;
p = findblk (i, b);
delblk (i, b, p);
b->size += a->size;
#ifdef M_DEBUG
a->magic = 0;
#endif
memmove ((char *) b + BLKSIZ, _a, a->size - BLKSIZ);
_a = (char *) (a = b) + BLKSIZ;
}
else
{
register void *m;
register int _size;
_size = ((size >> MEMINC) + 1) << MEMINC;
if ((m = sbrk (_size)) == (void *) -1)
return (0);
if ((char *) a + a->size == (char *) m)
a->size += _size;
else
{
register blk *b;
addblk (i, a, p);
b = (blk *) m;
b->size = _size;
#ifdef M_DEBUG
b->magic = MAGIC;
#endif
memcpy ((char *) b + BLKSIZ, _a, a->size - BLKSIZ);
_a = (char *) (a = b) + BLKSIZ;
}
}
}
i = flindex (size);
if (a->size > (size + __flmin[i]))
{
register blk *n;
p = findblk (i, a);
n = (blk *) ((char *) a + size);
addblk (i, n, p);
n->size = a->size - size;
#ifdef M_DEBUG
n->magic = MAGIC;
#endif
a->size = size;
}
return (_a);
}
void
free (register void *_a)
{
register blk *a, *p;
register int i;
if (!_a)
return;
#ifdef M_DEBUG
assert (addr (_a));
#endif
a = (blk *) ((char *) _a - BLKSIZ);
#ifdef M_DEBUG
assert (addr (a));
assert (a->magic == MAGIC);
#endif
i = flindex (a->size);
p = findblk (i, a);
concatblk (a, p);
if ((char *) p + p->size == (char *) a)
{
p->size += a->size;
#ifdef M_DEBUG
a->magic = 0;
#endif
}
else
addblk (i, a, p);
}
#ifdef M_DEBUG
void
__m_debug (void) /* dump free lists */
{
register blk *b;
register int i;
for (i = 0; i < NFL; i++)
{
printf ("\nfl: %d ( >= %d )\n", i, __flmin[i] - BLKSIZ);
b = __fl + i;
do
{
b = b->next;
printf ("%7x: next: %7x [%7x] size: %x\n", b, b->next,
(char *) b + b->size, b->size - BLKSIZ);
assert (addr (b));
assert (b->magic == MAGIC);
}
while (b->next > b);
}
putchar ('\n');
}
#endif