uc-sdk
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
malloc.c
Go to the documentation of this file.
1 #include <stddef.h>
2 #include <stdint.h>
3 #include "string.h"
4 #include "malloc.h"
5 
6 void * sbrk(ptrdiff_t incr);
7 
8 typedef struct _heap_t {
9  void * ptr;
10  size_t size;
11  struct _heap_t * prev, * next;
12 } heap_t;
13 
14 static void * heap_base = NULL;
15 static heap_t * head = NULL, * tail = NULL;
16 
17 static heap_t * find_fit(heap_t * head, size_t size) {
18  heap_t * prev = head;
19  uintptr_t prev_top, next_bot;
20 
21  while (prev) {
22  if (prev->next) {
23  prev_top = (uintptr_t) prev->ptr + prev->size;
24  next_bot = (uintptr_t) prev->next - prev_top;
25  if (next_bot >= size)
26  return prev;
27  }
28  prev = prev->next;
29  }
30 
31  return prev;
32 }
33 
34 void * base_malloc(size_t size) {
35  void * ptr = NULL, * heap_ptr;
36  heap_t * new, * prev;
37 
38  size = (size + sizeof(heap_t) + 7) & ~7;
39 
40  // Nothing's initialized yet ? Let's just initialize the bottom of our heap,
41  // flag it as allocated.
42  if (!head) {
43  if (!heap_base)
44  heap_base = sbrk(0);
45  heap_ptr = sbrk(size);
46 
47  if (!heap_ptr)
48  return NULL;
49 
50  ptr = (void *) ((uintptr_t) heap_ptr + sizeof(heap_t));
51  head = (heap_t *) heap_ptr;
52  head->ptr = ptr;
53  head->size = size - sizeof(heap_t);
54  head->prev = NULL;
55  head->next = NULL;
56  tail = head;
57  return ptr;
58  }
59 
60  // We *may* have the bottom of our heap that has shifted, because of a free.
61  // So let's check first if we have free space there, because I'm nervous
62  // about having an incomplete data structure.
63  if (((uintptr_t) heap_base + size) < (uintptr_t) head) {
64  new = (heap_t *) heap_base;
65  ptr = (void *) ((uintptr_t) new + sizeof(heap_t));
66 
67  new->ptr = ptr;
68  new->size = size - sizeof(heap_t);
69  new->prev = NULL;
70  new->next = head;
71  head->prev = new;
72  head = new;
73  return ptr;
74  }
75 
76  // No luck at the beginning of the heap, let's walk the heap to find a fit.
77  prev = find_fit(head, size);
78  if (prev) {
79  new = (heap_t *) ((uintptr_t) prev->ptr + prev->size);
80  ptr = (void *) ((uintptr_t) new + sizeof(heap_t));
81 
82  new->ptr = ptr;
83  new->size = size - sizeof(heap_t);
84  new->prev = prev;
85  new->next = prev->next;
86  new->next->prev = new;
87  prev->next = new;
88  return ptr;
89  }
90 
91  // Time to extend the size of the heap.
92  heap_ptr = sbrk(size);
93  if (!heap_ptr)
94  return NULL;
95 
96  ptr = (void *) ((uintptr_t) heap_ptr + sizeof(heap_t));
97  new = (heap_t *) heap_ptr;
98  new->ptr = ptr;
99  new->size = size - sizeof(heap_t);
100  new->prev = tail;
101  new->next = NULL;
102  tail->next = new;
103  tail = new;
104  return ptr;
105 }
106 
107 void * base_realloc(void * ptr, size_t size) {
108  heap_t * prev;
109  void * new = NULL;
110 
111  if (!size && ptr) {
112  free(ptr);
113  return NULL;
114  }
115 
116  if (!ptr)
117  return malloc(size);
118 
119  size = (size + sizeof(heap_t) + 7) & ~7;
120 
121  prev = (heap_t *) ((uintptr_t) ptr - sizeof(heap_t));
122 
123  // New memory block shorter ?
124  if (prev->size >= size) {
125  prev->size = size;
126  if (!prev->next)
127  sbrk(ptr + size - sbrk(0));
128 
129  return ptr;
130  }
131 
132  // New memory block larger
133  // Is it the last one ?
134  if (!prev->next) {
135  new = sbrk(size - prev->size);
136  if (!new)
137  return NULL;
138 
139  prev->size = size;
140  return ptr;
141  }
142 
143  // Do we have free memory after it ?
144  if ((prev->next->ptr - ptr) > size) {
145  prev->size = size;
146  return ptr;
147  }
148 
149  // No luck.
150  new = malloc(size);
151  if (!new)
152  return NULL;
153 
154  memcpy(new, ptr, prev->size);
155  free(ptr);
156  return new;
157 }
158 
159 void base_free(void * ptr) {
160  heap_t * cur;
161  void * top;
162  size_t size;
163 
164  if (!ptr || !head)
165  return;
166 
167  // First block; bumping head ahead.
168  if (ptr == head->ptr) {
169  size = head->size + (size_t) (head->ptr - (void *) head);
170  head = head->next;
171 
172  if (head) {
173  head->prev = NULL;
174  } else {
175  tail = NULL;
176  sbrk(-size);
177  }
178 
179  return;
180  }
181 
182  // Finding the proper block
183  cur = head;
184  for (cur = head; ptr != cur->ptr; cur = cur->next)
185  if (!cur->next)
186  return;
187 
188  if (cur->next) {
189  // In the middle, just unlink it
190  cur->next->prev = cur->prev;
191  } else {
192  // At the end, shrink heap
193  tail = cur->prev;
194  top = sbrk(0);
195  size = (top - cur->prev->ptr) - cur->prev->size;
196  sbrk(-size);
197  }
198 
199  cur->prev->next = cur->next;
200 }
201 
202 __attribute__((weak)) void * __builtin_new(size_t size) { return malloc(size); }
203 __attribute__((weak)) void __builtin_delete(void * ptr) { free(ptr); }
204