1 #include <stdlib.h>
2 #include <string.h> /* memset */
3 #include "mem.h"
4 
5 struct CHUNK
6 {
7 	char *memory;
8 	char *current;
9 	char *end;
10 	struct CHUNK *next;
11 };
12 
13 struct HEAP
14 {
15 	struct CHUNK *current;
16 };
17 
18 /* how large each chunk should be */
19 static const int default_chunksize = 1024*16;
20 
21 /* allocates a new chunk to be used */
mem_newchunk(int chunksize)22 static struct CHUNK *mem_newchunk(int chunksize)
23 {
24 	struct CHUNK *chunk;
25 	char *mem;
26 
27 	/* allocate memory */
28 	mem = malloc(sizeof(struct CHUNK)+chunksize);
29 	if(!mem)
30 		return 0x0;
31 
32 	memset(mem, 0, sizeof(struct CHUNK)+chunksize);
33 
34 	/* the chunk structure is located in the begining of the chunk */
35 	/* init it and return the chunk */
36 	chunk = (struct CHUNK*)mem;
37 	chunk->memory = (char*)(chunk+1);
38 	chunk->current = chunk->memory;
39 	chunk->end = chunk->memory + chunksize;
40 	chunk->next = (struct CHUNK *)0x0;
41 	return chunk;
42 }
43 
44 /******************/
mem_allocate_from_chunk(struct CHUNK * chunk,int size)45 static void *mem_allocate_from_chunk(struct CHUNK *chunk, int size)
46 {
47 	char *mem;
48 
49 	/* check if we need can fit the allocation */
50 	if(chunk->current + size > chunk->end)
51 		return (void*)0x0;
52 
53 	/* get memory and move the pointer forward */
54 	mem = chunk->current;
55 	chunk->current += size;
56 	return mem;
57 }
58 
59 /* creates a heap */
mem_create()60 struct HEAP *mem_create()
61 {
62 	struct CHUNK *chunk;
63 	struct HEAP *heap;
64 
65 	/* allocate a chunk and allocate the heap structure on that chunk */
66 	chunk = mem_newchunk(default_chunksize);
67 	heap = (struct HEAP *)mem_allocate_from_chunk(chunk, sizeof(struct HEAP));
68 	heap->current = chunk;
69 	return heap;
70 }
71 
72 /* destroys the heap */
mem_destroy(struct HEAP * heap)73 void mem_destroy(struct HEAP *heap)
74 {
75 	struct CHUNK *chunk = heap->current;
76 	struct CHUNK *next;
77 
78 	while(chunk)
79 	{
80 		next = chunk->next;
81 		free(chunk);
82 		chunk = next;
83 	}
84 }
85 
86 /* */
mem_allocate(struct HEAP * heap,int size)87 void *mem_allocate(struct HEAP *heap, int size)
88 {
89 	char *mem;
90 
91 	/* align the size to the size of a pointer */
92 	size = (size+sizeof(void*)-1)&(~(sizeof(void*)-1));
93 
94 	/* try to allocate from current chunk */
95 	mem = (char *)mem_allocate_from_chunk(heap->current, size);
96 	if(!mem)
97 	{
98 		if(size > default_chunksize/2)
99 		{
100 			/* this block is kinda big, allocate it's own chunk */
101 			struct CHUNK *chunk = mem_newchunk(size);
102 			chunk->next = heap->current->next;
103 			heap->current->next = chunk;
104 			mem = (char *)mem_allocate_from_chunk(chunk, size);
105 		}
106 		else
107 		{
108 			/* allocate new chunk and add it to the heap */
109 			struct CHUNK *chunk = mem_newchunk(default_chunksize);
110 			chunk->next = heap->current;
111 			heap->current = chunk;
112 
113 			/* try to allocate again */
114 			mem = (char *)mem_allocate_from_chunk(heap->current, size);
115 		}
116 	}
117 
118 	return mem;
119 }
120