aboutsummaryrefslogblamecommitdiff
path: root/8.6/malloc.c
blob: 0834669d4ea57ab470be53f64d3032abfd048e3a (plain) (tree)










































































































                                                                    
#include <unistd.h>
#include "malloc.h"

#define NALLOC	128

typedef long long Align;

typedef union header {
	struct {
		union header *ptr;
		size_t size;
	} s;

	Align x;
} Header;

static Header base;
static Header *freep = NULL;

static Header *my_morecore(size_t nunits);

void *my_calloc(size_t n ,size_t size)
{
	char *p, *temp;
	size_t nb;

	nb = n * size;
	if ((p = temp = my_malloc(nb)) == NULL)
		while (nb-- > 0)
			*p = '\0';

	return p;
}

void *my_malloc(size_t nbytes)
{
	Header *prevp, *p;
	size_t nunits;

	if ((prevp = freep) == NULL) {
		base.s.ptr = prevp = freep = &base;
		base.s.size = 0;
	}

	nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1;
	for (p = freep->s.ptr; ; prevp = p, p = p->s.ptr) {
		if (p->s.size >= nunits) {
			if (p->s.size == nunits) {
				prevp->s.ptr = p->s.ptr;
			} else {
				p->s.size -= nunits;
				p += p->s.size;
				p->s.size = nunits;
			}

			freep = prevp;
			return (void *)(p + 1);
		}

		if (p == freep)
			if ((p = my_morecore(nunits)) == NULL)
				return NULL;
	}

	return NULL;
}

static Header *my_morecore(size_t nunits)
{
	Header *p;

	if (nunits < NALLOC)
		nunits = NALLOC;

	if ((p = sbrk(nunits * sizeof(Header))) == (Header *) -1)
		return NULL;

	p->s.size = nunits;
	my_free (p + 1);
	return freep;
}

void my_free(void *ap)
{
	Header *bp, *p;

	bp = (Header *)ap - 1;
	for (p = freep; !(bp > p && bp < p->s.ptr) ; p = p->s.ptr)
		if (p >= p->s.ptr && (bp > p || bp < p->s.ptr))
			break;

	if (bp + bp->s.size == p->s.ptr) {
		bp->s.size += p->s.ptr->s.size;
		bp->s.ptr = p->s.ptr->s.ptr;
	} else {
		bp->s.ptr = p->s.ptr;
	}

	if (p + p->s.size == bp) {
		p->s.size += bp->s.size;
		p->s.ptr = bp->s.ptr;
	} else {
		p->s.ptr = bp;
	}

	freep = p;
}