Skip to content

Instantly share code, notes, and snippets.

@fuweid
Last active September 27, 2016 06:15
Show Gist options
  • Save fuweid/114be24e151409b01318ee130fecf6bc to your computer and use it in GitHub Desktop.
Save fuweid/114be24e151409b01318ee130fecf6bc to your computer and use it in GitHub Desktop.
Memory Management in C (Still no test cases for this)
#include "mem.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define NELEMS(arr) ((sizeof(arr) / sizeof((arr)[0])))
#define NDESCRIPTORS 512
#define EXTRA_MEM 4096
#define ALIGN(x, a) (_ALIGN_MASK((x), (typeof(x))(a) - 1))
#define _ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define IS_ALIGN(x, a) (((unsigned int)(x) % (a)) == 0)
#define ALIGN_SIZE 16
#define HASH(x, a) ((((unsigned int)(x)) >> 3) & NELEMS((a)))
struct descriptor {
struct descriptor *link;
struct descriptor *free;
void *ptr;
int size;
};
static struct descriptor freelist = { .free = &freelist };
static struct descriptor *htab[2048];
struct descriptor *findbp(void *ptr);
struct descriptor *dalloc(void *ptr, int size);
void *
mem_alloc(long nbytes)
{
assert(nbytes > 0);
struct descriptor *bp;
void *ptr;
nbytes = ALIGN(nbytes, ALIGN_SIZE);
for (bp = freelist.free; bp; bp = bp->free) {
if (bp->size > nbytes) {
bp->size -= nbytes;
ptr = (void *) ((char *)bp->ptr + bp->size);
if ((bp = dalloc(ptr, nbytes)) == 0) {
assert(0);
}
bp->link = htab[HASH(ptr, htab)];
htab[HASH(ptr, htab)] = bp;
return ptr;
}
if (bp == &freelist) {
struct descriptor *newbp;
int bsize = nbytes + ALIGN(EXTRA_MEM, ALIGN_SIZE);
if ((ptr = malloc(bsize)) == 0
|| (newbp = dalloc(ptr, bsize)) == 0) {
assert(0);
}
newbp->free = freelist.free;
freelist.free = newbp;
}
}
assert(0);
return 0;
}
void *
mem_realloc(void *ptr, long nbytes)
{
assert(ptr);
assert(nbytes > 0);
struct descriptor *bp;
if (!IS_ALIGN(ptr, ALIGN_SIZE) ||
(bp = findbp(ptr)) == 0 ||
bp->free != 0) {
assert(0);
}
void *newptr = mem_alloc(nbytes);
memcpy(newptr, ptr, bp->size > nbytes ? nbytes : bp->size);
mem_free(ptr);
return newptr;
}
void
mem_free(void *ptr)
{
if (ptr) {
struct descriptor *bp;
if (!IS_ALIGN(ptr, ALIGN_SIZE) ||
(bp = findbp(ptr)) == 0 || bp->free != 0) {
assert(0);
}
bp->free = freelist.free;
freelist.free = bp;
}
}
struct descriptor *
findbp(void *ptr)
{
struct descriptor *bp = htab[HASH(ptr, htab)];
for (; bp && bp->ptr != ptr;) {
bp = bp->link;
}
return bp;
}
struct descriptor *
dalloc(void *ptr, int size)
{
static struct descriptor *avail;
static int nleft;
if (nleft <= 0) {
avail = malloc(sizeof(*avail) * NDESCRIPTORS);
if (!avail) {
return 0;
}
nleft = NDESCRIPTORS;
}
nleft -= 1;
avail->link = 0;
avail->free = 0;
avail->size = size;
avail->ptr = ptr;
return avail++;
}
#ifndef MEM_INCLUDED
#define MEM_INCLUDED
extern void *mem_alloc(long nbytes);
extern void *mem_realloc(void *ptr, long n);
extern void mem_free(void *ptr);
#endif /* MEM_INCLUDED */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment