Last active
September 27, 2016 06:15
-
-
Save fuweid/114be24e151409b01318ee130fecf6bc to your computer and use it in GitHub Desktop.
Memory Management in C (Still no test cases for this)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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++; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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