142 lines
3.4 KiB
C
142 lines
3.4 KiB
C
/* M E M O R Y A L L O C A T I O N R O U T I N E S */
|
|
|
|
/* The reason for having own memory allocation routines (malloc(),
|
|
realloc() and free()) is plain: the garbage collection performed by
|
|
the library functions malloc(), realloc() and free() costs a lot of
|
|
time, while in most cases (on a VAX) the freeing and reallocation of
|
|
memory is not necessary.
|
|
The (basic) memory allocating routines offered by this memory
|
|
handling package are:
|
|
|
|
char *malloc(n) : allocate n bytes
|
|
char *realloc(ptr, n) : reallocate buffer to n bytes
|
|
(works only if ptr was last allocated)
|
|
free(ptr) : if ptr points to last allocated
|
|
memory, this memory is re-allocatable
|
|
|
|
This module imports routines from "system", an assertion macro,
|
|
and the compile-time
|
|
constants ALIGNBITS, ALLOCSIZ, DEBUG.
|
|
ALIGNBITS is an integer constant defining suitable alignment,
|
|
ALLOCSIZ is the size of the chunks of memory asked from the system,
|
|
DEBUG enables the assertions.
|
|
*/
|
|
|
|
#include <assert.h>
|
|
#include <system.h>
|
|
|
|
#ifndef ALIGNBITS
|
|
#define ALIGNBITS 07
|
|
#endif
|
|
|
|
#ifndef ALLOCSIZ
|
|
#define ALLOCSIZ 4096
|
|
#endif
|
|
|
|
/* the following variables are used for book-keeping */
|
|
static int nfreebytes = 0; /* # free bytes in sys_break-ed space */
|
|
static char *freeb = 0; /* pointer to first free byte */
|
|
static char *lastalloc; /* pointer to last malloced sp */
|
|
static int lastnbytes; /* nr of bytes in last allocated space */
|
|
static char *firstfreeb; /* pointer to first ever free byte */
|
|
|
|
#define ALIGN(m) (((m)&ALIGNBITS)? (m)+((1+ALIGNBITS)-((m)&ALIGNBITS)):(m))
|
|
|
|
char *sys_break();
|
|
|
|
char *
|
|
malloc(n)
|
|
unsigned int n;
|
|
{
|
|
/* malloc() is a very simple malloc().
|
|
*/
|
|
|
|
n = ALIGN(n);
|
|
if (nfreebytes < n) {
|
|
register int nbts = (n <= ALLOCSIZ) ? ALLOCSIZ : n;
|
|
|
|
if (!nfreebytes) {
|
|
if (!firstfreeb) {
|
|
/* We arrive here the first time malloc is
|
|
called
|
|
*/
|
|
int diff;
|
|
|
|
if (!(freeb = sys_break(0))) return 0;
|
|
if ((diff = (int)((long)freeb&ALIGNBITS))!=0) {
|
|
/* align memory to ALIGNBITS ... */
|
|
diff = (1 + ALIGNBITS) - diff;
|
|
if (!(freeb = sys_break(diff))) {
|
|
return 0;
|
|
}
|
|
freeb += diff;
|
|
assert(((long)freeb & ALIGNBITS) == 0);
|
|
}
|
|
firstfreeb = freeb;
|
|
}
|
|
if (!(freeb = sys_break(nbts))) return 0;
|
|
}
|
|
else {
|
|
if (!sys_break(nbts)) return 0;
|
|
}
|
|
nfreebytes += nbts;
|
|
}
|
|
lastalloc = freeb;
|
|
freeb = lastalloc + n;
|
|
lastnbytes = n;
|
|
nfreebytes -= n;
|
|
return lastalloc;
|
|
}
|
|
|
|
char *
|
|
realloc(ptr, n)
|
|
char *ptr;
|
|
unsigned int n;
|
|
{
|
|
/* realloc() is designed to append more bytes to the latest
|
|
allocated piece of memory.
|
|
*/
|
|
register int nbytes = n;
|
|
|
|
if (!ptr || ptr != lastalloc) { /* security */
|
|
return 0;
|
|
}
|
|
nbytes -= lastnbytes; /* # bytes required */
|
|
if (nbytes == 0) { /* no extra bytes */
|
|
return lastalloc;
|
|
}
|
|
|
|
/* if nbytes < 0: free last allocated bytes;
|
|
if nbytes > 0: allocate more bytes
|
|
*/
|
|
if (nbytes > 0) nbytes = ALIGN(nbytes);
|
|
if (nfreebytes < nbytes) {
|
|
register int nbts = (nbytes < ALLOCSIZ) ? ALLOCSIZ : nbytes;
|
|
if (!sys_break(nbts)) return 0;
|
|
nfreebytes += nbts;
|
|
}
|
|
freeb += nbytes; /* less bytes */
|
|
lastnbytes += nbytes; /* change nr of last all. bytes */
|
|
nfreebytes -= nbytes; /* less or more free bytes */
|
|
return lastalloc;
|
|
}
|
|
|
|
free(p)
|
|
char *p;
|
|
{
|
|
if (lastalloc && lastalloc == p) {
|
|
nfreebytes += lastnbytes;
|
|
freeb = lastalloc;
|
|
lastnbytes = 0;
|
|
lastalloc = 0;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
mem_stat()
|
|
{
|
|
|
|
printf("Total nr of bytes allocated: %d\n",
|
|
sys_break(0) - firstfreeb);
|
|
}
|
|
#endif DEBUG
|