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