view src/ploki/xmalloc.c @ 10131:bbbdb09e6365

<boily> le/rn mate//Mat\xc3\xa9 is a southern hemisphere shamanist beverage that opens your inner self to the Sacred World. Its enlightened users become friendly, wishing \xe2\x80\x9cG\'day, mat\xc3\xa9!\xe2\x80\x9d to one another.
author HackBot
date Sat, 14 Jan 2017 14:02:22 +0000
parents ac0403686959
children
line wrap: on
line source

#include "config.h"
#include "main.h"
#include "xmalloc.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef DEBUG_MALLOC
	#define IF_DB(x) x
#else
	#define IF_DB(x)
#endif

static struct node {
	void *ptr;
	struct node *prev, *next;
	size_t size;
	#if DEBUG_P
		const char *file;
		unsigned line;
	#endif
} *Root;

#if 0
int xdump(void) {
	struct node *p;

	fprintf(stderr, ":%p\n", Root);
	for (p = Root; p; p = p->next) {
		fprintf(stderr, "\\<%p [%p]%p %p>\n", p->prev, p, p->ptr, p->next);
		assert(p != p->next);
	}
	fprintf(stderr, "\n");
	return 0;
}
#endif

void xend(void) {
	struct node *p;

	while ((p = Root)) {
#if DEBUG_P
		unsigned char *ptr;
		for (ptr = p->ptr; memcmp(ptr, &p, sizeof p); ++ptr)
			;
		ptr += sizeof p;
		fprintf(stderr, "%s: autofreeing pointer %p (%p) from %s:%u\n", Prog, p->ptr, (void *)ptr, p->file, p->line);
#else
		fprintf(stderr, "%s: autofreeing pointer %p\n", Prog, p->ptr);
#endif
		free(p->ptr);
		assert(Root != p->next);
		Root = p->next;
		free(p);
	}
}

#define XFACTOR(size) ((sizeof (struct node *) - 1) / (size) + 1u)

#if DEBUG_P
void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) {
#else
void *xrealloc(void *optr, size_t nmemb) {
#endif
	struct node *p;
	size_t k;
	size_t size;
	unsigned char *r;
	void *ptr;

	assert(optr != NULL);

	memcpy(&p, (unsigned char *)optr - sizeof Root, sizeof p);
	size = p->size;
	k = XFACTOR(size) * size;
	if (!(ptr = realloc(p->ptr, size * nmemb + k))) {
		fprintf(stderr, "%s: realloc(%p, %lu): %s\n", Prog, ptr, (unsigned long)(nmemb * size), strerror(errno));
		abort();
	}
	r = (unsigned char *)ptr + k;
	#if DEBUG_P
		IF_DB(fprintf(stderr, "%s: xrealloc(%zu): %p (%p) from %s:%u -> %p (%p) from %s:%u\n", Prog, nmemb, p->ptr, optr, p->file, p->line, ptr, r, file, line));
		p->file = file;
		p->line = line;
	#endif
	p->ptr = ptr;
	return r;
}

#if DEBUG_P
void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
#else
void *xmalloc(size_t nmemb, size_t size) {
#endif
	struct node *p;
	size_t k;
	unsigned char *r;

	if ((p = malloc(sizeof *p))) {
		k = XFACTOR(size) * size;
		if (!(p->ptr = malloc(size * nmemb + k))) {
			free(p);
			goto failure;
		}
	} else failure: {
		fprintf(stderr, "%s: malloc(%lu): %s\n", Prog, (unsigned long)(nmemb * size), strerror(errno));
		abort();
	}
	#if DEBUG_P
		memset(p->ptr, 'U', k);
	#endif
	r = (unsigned char *)p->ptr + k;
	memcpy(r - sizeof Root, &p, sizeof p);
	p->size = size;
	p->prev = NULL;
	p->next = Root;
	#if DEBUG_P
		p->file = file;
		p->line = line;
		IF_DB(fprintf(stderr, "%s: xmalloc(%zu, %zu): %p (%p) from %s:%u\n", Prog, nmemb, size, p->ptr, r, file, line));
	#endif
	if (Root) {
		Root->prev = p;
	}
	Root = p;
	return r;
}

#if 0
#if DEBUG_P
void *(xcalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {
	void *const p = xmalloc(nmemb, size, file, line);
#else
void *xcalloc(size_t nmemb, size_t size) {
	void *const p = xmalloc(nmemb, size);
#endif
	memset(p, '\0', nmemb * size);
	return p;
}
#endif

void xfree(void *ptr) {
	struct node *p;

	if (!ptr)
		return;
	memcpy(&p, (unsigned char *)ptr - sizeof Root, sizeof p);
	assert(p != NULL);
	DEBUG(memset((unsigned char *)ptr - sizeof Root, 'F', sizeof Root));

	if (p->next) {
		p->next->prev = p->prev;
	}
	if (p->prev) {
		p->prev->next = p->next;
	} else {
		assert(p == Root);
		Root = Root->next;
	}
	#if DEBUG_P
		IF_DB(fprintf(stderr, "%s: xfree(): %p (%p) from %s:%u\n", Prog, p->ptr, ptr, p->file, p->line));
	#endif
	free(p->ptr);
	free(p);
}